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.
 
 
 

135 lines
3.5 KiB

  1. # This file is part of CAT-SOOP
  2. # Copyright (c) 2011-2017 Adam Hartz <hartz@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. import ast
  17. def parser(lex=None, yacc=None):
  18. tokens = ("PLUS", "MINUS", "TIMES", "DIVIDE", "EXP", "COMMA", "LPAREN",
  19. "RPAREN", "NAME", "NUMBER")
  20. t_ignore = " \t"
  21. t_PLUS = r"\+"
  22. t_MINUS = r"-"
  23. t_TIMES = r"\*"
  24. t_DIVIDE = r"/"
  25. t_EXP = r"\^"
  26. t_COMMA = r","
  27. t_LPAREN = r"\("
  28. t_RPAREN = r"\)"
  29. t_NAME = r"[A-Za-z][A-Za-z0-9]*(_[A-Za-z0-9]*)?"
  30. t_NUMBER = r"((\d+\.\d*|\.\d+)([eE][-+]?\d+)?|\d+[eE][-+]?\d+|\d+)"
  31. lex.lex()
  32. precedence = (('left', 'PLUS', 'MINUS'),
  33. ('left', 'TIMES', 'DIVIDE'),
  34. ('right', 'UMINUS'),
  35. ('left', 'EXP'), )
  36. def p_expression_binop(t):
  37. """
  38. expression : expression PLUS expression
  39. | expression MINUS expression
  40. | expression TIMES expression
  41. | expression DIVIDE expression
  42. | expression EXP expression
  43. | number name
  44. """
  45. if len(t) == 4:
  46. t[0] = [t[2], t[1], t[3]]
  47. elif len(t) == 5:
  48. t[0] = ['*', t[1], t[3]]
  49. else:
  50. t[0] = ['*', t[1], t[2]]
  51. def p_expression_grouped(t):
  52. """
  53. expression : LPAREN expression RPAREN
  54. """
  55. t[0] = t[2]
  56. def p_expression_call(t):
  57. """
  58. expression : name LPAREN list_of_expressions RPAREN
  59. """
  60. t[0] = ['CALL', t[1], t[3]]
  61. def p_expression_impmul(t):
  62. """
  63. expression : LPAREN expression RPAREN LPAREN expression RPAREN
  64. | number LPAREN expression RPAREN
  65. """
  66. if len(t) == 5:
  67. t[0] = ['*', t[1], t[3]]
  68. else:
  69. t[0] = ['*', t[2], t[5]]
  70. def p_list_of_expressions(t):
  71. """
  72. list_of_expressions : empty
  73. | expression COMMA list_of_expressions
  74. | expression opt_comma
  75. """
  76. if len(t) == 4:
  77. t[0] = [t[1]] + t[3]
  78. elif len(t) == 3:
  79. t[0] = [t[1]]
  80. else:
  81. t[0] = []
  82. def p_opt_comma(t):
  83. """
  84. opt_comma : empty
  85. | COMMA
  86. """
  87. pass
  88. def p_expression_uminus(t):
  89. """
  90. expression : MINUS expression %prec UMINUS
  91. """
  92. t[0] = ['u-', t[2]]
  93. def p_expression_atom(t):
  94. """
  95. expression : number
  96. | name
  97. """
  98. t[0] = t[1]
  99. def p_number(t):
  100. """
  101. number : NUMBER
  102. """
  103. t[0] = ['NUMBER', t[1]]
  104. def p_name(t):
  105. """
  106. name : NAME
  107. """
  108. t[0] = ['NAME', t[1]]
  109. def p_empty(p):
  110. """
  111. empty :
  112. """
  113. pass
  114. return yacc.yacc(optimize=False, debug=False, write_tables=False)