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.
 
 
 

153 lines
3.8 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. implicit_multiplication = False
  17. def parser(lex=None, yacc=None):
  18. tokens = ("PLUS",
  19. "MINUS",
  20. "TIMES",
  21. "DIVIDE",
  22. "EXP",
  23. "COMMA",
  24. "LPAREN",
  25. "RPAREN",
  26. "NAME",
  27. "NUMBER",
  28. "CARET",
  29. "LBRACKET",
  30. "RBRACKET", )
  31. t_ignore = " \t"
  32. t_PLUS = r"\+"
  33. t_MINUS = r"-"
  34. t_TIMES = r"\*"
  35. t_DIVIDE = r"/"
  36. t_EXP = r"\*\*"
  37. t_CARET = r"\^"
  38. t_COMMA = r","
  39. t_LPAREN = r"\("
  40. t_RPAREN = r"\)"
  41. t_LBRACKET = r"\["
  42. t_RBRACKET = r"\]"
  43. t_NAME = r"[A-Za-z][A-Za-z0-9]*(_[A-Za-z0-9]*)?"
  44. t_NUMBER = r"((\d+\.\d*|\.\d+)([eE][-+]?\d+)?|\d+[eE][-+]?\d+|\d+)"
  45. lex.lex()
  46. precedence = (('left', 'PLUS', 'MINUS'),
  47. ('left', 'TIMES', 'DIVIDE'),
  48. ('left', 'EXP'),
  49. ('right', 'UMINUS'), )
  50. def p_expression_binop(t):
  51. """
  52. expression : expression PLUS expression
  53. | expression MINUS expression
  54. | expression TIMES expression
  55. | expression DIVIDE expression
  56. | expression EXP expression
  57. """
  58. if t[2] == '**':
  59. t[2] = '^'
  60. t[0] = [t[2], t[1], t[3]]
  61. def p_expression_xor(t):
  62. """
  63. expression : expression CARET expression
  64. """
  65. t[0] = ['CALL', ['NAME', 'XOR'], [t[1], t[3]]]
  66. def p_expression_list(t):
  67. """
  68. expression : LBRACKET list_of_expressions RBRACKET
  69. """
  70. t[0] = ['LIST', t[2]]
  71. def p_expression_grouped(t):
  72. """
  73. expression : LPAREN expression RPAREN
  74. """
  75. t[0] = t[2]
  76. def p_expression_call(t):
  77. """
  78. expression : name LPAREN list_of_expressions RPAREN
  79. """
  80. t[0] = ['CALL', t[1], t[3]]
  81. def p_list_of_expressions(t):
  82. """
  83. list_of_expressions : empty
  84. | expression COMMA list_of_expressions
  85. | expression opt_comma
  86. """
  87. if len(t) == 4:
  88. t[0] = [t[1]] + t[3]
  89. elif len(t) == 3:
  90. t[0] = [t[1]]
  91. else:
  92. t[0] = []
  93. def p_opt_comma(t):
  94. """
  95. opt_comma : empty
  96. | COMMA
  97. """
  98. pass
  99. def p_expression_uminus(t):
  100. """
  101. expression : MINUS expression %prec UMINUS
  102. """
  103. t[0] = ['u-', t[2]]
  104. def p_expression_uplus(t):
  105. """
  106. expression : PLUS expression %prec UMINUS
  107. """
  108. t[0] = ['u+', t[2]]
  109. def p_expression_atom(t):
  110. """
  111. expression : number
  112. | name
  113. """
  114. t[0] = t[1]
  115. def p_number(t):
  116. """
  117. number : NUMBER
  118. """
  119. t[0] = ['NUMBER', t[1]]
  120. def p_name(t):
  121. """
  122. name : NAME
  123. """
  124. t[0] = ['NAME', t[1]]
  125. def p_empty(p):
  126. """
  127. empty :
  128. """
  129. pass
  130. return yacc.yacc(optimize=False, debug=False, write_tables=False)