CAT-SOOP is a flexible, programmable learning management system based on the Python programming language. https://catsoop.mit.edu
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

160 lines
3.8 KiB

  1. # This file is part of CAT-SOOP
  2. # Copyright (c) 2011-2020 by The CAT-SOOP Developers <catsoop-dev@mit.edu>
  3. #
  4. # This program is free software: you can redistribute it and/or modify it under
  5. # the terms of the GNU Affero General Public License as published by the Free
  6. # Software Foundation, either version 3 of the License, or (at your option) any
  7. # later version.
  8. #
  9. # This program is distributed in the hope that it will be useful, but WITHOUT
  10. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  11. # FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  12. # details.
  13. #
  14. # You should have received a copy of the GNU Affero General Public License
  15. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. implicit_multiplication = False
  17. def parser(lex=None, yacc=None):
  18. tokens = (
  19. "PLUS",
  20. "MINUS",
  21. "TIMES",
  22. "MATMUL",
  23. "DIVIDE",
  24. "EXP",
  25. "COMMA",
  26. "LPAREN",
  27. "RPAREN",
  28. "NUMBER",
  29. "NAME",
  30. "CARET",
  31. "LBRACKET",
  32. "RBRACKET",
  33. )
  34. t_ignore = " \t"
  35. t_PLUS = r"\+"
  36. t_MINUS = r"-"
  37. t_TIMES = r"\*"
  38. t_MATMUL = r"@"
  39. t_DIVIDE = r"/"
  40. t_EXP = r"\*\*"
  41. t_CARET = r"\^"
  42. t_COMMA = r","
  43. t_LPAREN = r"\("
  44. t_RPAREN = r"\)"
  45. t_LBRACKET = r"\["
  46. t_RBRACKET = r"\]"
  47. t_NAME = r"[A-Za-z][A-Za-z0-9]*(_[A-Za-z0-9]*)?"
  48. t_NUMBER = r"((\d+\.\d*|\.\d+)([eE][-+]?\d+)?|\d+[eE][-+]?\d+|\d+)[jJ]?"
  49. lex.lex()
  50. precedence = (
  51. ("left", "PLUS", "MINUS"),
  52. ("left", "TIMES", "DIVIDE", "MATMUL"),
  53. ("right", "UMINUS"),
  54. ("right", "EXP"),
  55. )
  56. def p_expression_binop(t):
  57. """
  58. expression : expression PLUS expression
  59. | expression MINUS expression
  60. | expression TIMES expression
  61. | expression MATMUL expression
  62. | expression DIVIDE expression
  63. | expression EXP expression
  64. """
  65. if t[2] == "**":
  66. t[2] = "^"
  67. t[0] = [t[2], t[1], t[3]]
  68. def p_expression_xor(t):
  69. """
  70. expression : expression CARET expression
  71. """
  72. t[0] = ["CALL", ["NAME", "XOR"], [t[1], t[3]]]
  73. def p_expression_list(t):
  74. """
  75. expression : LBRACKET list_of_expressions RBRACKET
  76. """
  77. t[0] = ["LIST", t[2]]
  78. def p_expression_grouped(t):
  79. """
  80. expression : LPAREN expression RPAREN
  81. """
  82. t[0] = t[2]
  83. def p_expression_call(t):
  84. """
  85. expression : name LPAREN list_of_expressions RPAREN
  86. """
  87. t[0] = ["CALL", t[1], t[3]]
  88. def p_list_of_expressions(t):
  89. """
  90. list_of_expressions : empty
  91. | expression COMMA list_of_expressions
  92. | expression opt_comma
  93. """
  94. if len(t) == 4:
  95. t[0] = [t[1]] + t[3]
  96. elif len(t) == 3:
  97. t[0] = [t[1]]
  98. else:
  99. t[0] = []
  100. def p_opt_comma(t):
  101. """
  102. opt_comma : empty
  103. | COMMA
  104. """
  105. pass
  106. def p_expression_uminus(t):
  107. """
  108. expression : MINUS expression %prec UMINUS
  109. """
  110. t[0] = ["u-", t[2]]
  111. def p_expression_uplus(t):
  112. """
  113. expression : PLUS expression %prec UMINUS
  114. """
  115. t[0] = ["u+", t[2]]
  116. def p_expression_atom(t):
  117. """
  118. expression : number
  119. | name
  120. """
  121. t[0] = t[1]
  122. def p_number(t):
  123. """
  124. number : NUMBER
  125. """
  126. t[0] = ["NUMBER", t[1].lower()]
  127. def p_name(t):
  128. """
  129. name : NAME
  130. """
  131. t[0] = ["NAME", t[1]]
  132. def p_empty(p):
  133. """
  134. empty :
  135. """
  136. pass
  137. return yacc.yacc(optimize=False, debug=False, write_tables=False)