parser.py 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. # This file is part of TRS (http://math.kompiler.org)
  2. #
  3. # TRS is free software: you can redistribute it and/or modify it under the
  4. # terms of the GNU Affero General Public License as published by the Free
  5. # Software Foundation, either version 3 of the License, or (at your option) any
  6. # later version.
  7. #
  8. # TRS is distributed in the hope that it will be useful, but WITHOUT ANY
  9. # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  10. # A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
  11. # details.
  12. #
  13. # You should have received a copy of the GNU Affero General Public License
  14. # along with TRS. If not, see <http://www.gnu.org/licenses/>.
  15. import sys
  16. from external.graph_drawing.graph import generate_graph
  17. from external.graph_drawing.line import generate_line
  18. def create_graph(node):
  19. return node.graph() if node else None
  20. class ParserWrapper(object):
  21. def __init__(self, base_class, **kwargs):
  22. self.input_buffer = []
  23. self.last_buffer = ''
  24. self.input_position = 0
  25. self.closed = False
  26. self.verbose = kwargs.get('verbose', False)
  27. self.parser = base_class(file=self, read=self.read, **kwargs)
  28. def __getattr__(self, name):
  29. if name in self.__dict__:
  30. return getattr(self, name)
  31. return getattr(self.parser, name)
  32. def readline(self, nbytes=False):
  33. return self.read(nbytes)
  34. def read(self, nbytes=False):
  35. if len(self.last_buffer) >= nbytes:
  36. buf = self.last_buffer[:nbytes]
  37. self.last_buffer = self.last_buffer[nbytes:]
  38. return buf
  39. buf = self.last_buffer
  40. try:
  41. buf += self.input_buffer[self.input_position]
  42. if self.verbose:
  43. print 'read:', buf # pragma: nocover
  44. self.input_position += 1
  45. except IndexError:
  46. self.closed = True
  47. return ''
  48. self.last_buffer = buf[nbytes:]
  49. return buf
  50. def close(self):
  51. self.closed = True
  52. self.input_position = len(self.input_buffer)
  53. def run(self, input_buffer, *args, **kwargs):
  54. map(self.append, input_buffer)
  55. return self.parser.run(*args, **kwargs)
  56. def append(self, input):
  57. self.closed = False
  58. self.input_buffer.append(input + '\n')
  59. def run_expressions(base_class, expressions, fail=True, silent=False,
  60. **kwargs):
  61. """
  62. Run a list of mathematical expression through the term rewriting system and
  63. check if the output matches the expected output. The list of EXPRESSIONS
  64. consists of tuples (expression, output), where expression is the
  65. mathematical expression to evaluate (String) and output is the expected
  66. output of the evaluation (thus, the output can be Float, Int or None).
  67. If KEEPFILES is non-zero or True, the generated Flex and Bison files will
  68. be kept. Otherwise, those temporary files will be deleted. If FAIL is True,
  69. and the output of the expression is not equal to the expected output, an
  70. assertion error is raised. If SILENT is False, and an assertion error is
  71. raised, an error message is printed on stderr. If SILENT is True, no error
  72. message will be printed.
  73. If VERBOSE is non-zero and a positive integer number, verbosity of the term
  74. rewriting system will be increased. This will output debug messages and a
  75. higher value will print more types of debug messages.
  76. """
  77. parser = ParserWrapper(base_class, **kwargs)
  78. for exp, out in expressions:
  79. res = None
  80. try:
  81. res = parser.run([exp])
  82. assert res == out
  83. except: # pragma: nocover
  84. if not silent:
  85. print >>sys.stderr, 'error: %s gives %s, but expected: %s' \
  86. % (exp, str(res), str(out))
  87. if not silent and hasattr(res, 'nodes'):
  88. print >>sys.stderr, 'result graph:'
  89. print >>sys.stderr, create_graph(res)
  90. print >>sys.stderr, 'expected graph:'
  91. print >>sys.stderr, create_graph(out)
  92. if fail:
  93. raise
  94. def apply_expressions(base_class, expressions, fail=True, silent=False,
  95. **kwargs):
  96. parser = ParserWrapper(base_class, **kwargs)
  97. for exp, times, out in expressions:
  98. res = None
  99. try:
  100. parser.run([exp])
  101. parser.parser.rewrite(check_implicit=False)
  102. res = parser.parser.root_node
  103. assert res == out
  104. except: # pragma: nocover
  105. if not silent:
  106. print >>sys.stderr, 'error: %s gives %s, but expected: %s' \
  107. % (exp, str(res), str(out))
  108. if not silent and hasattr(res, 'nodes'):
  109. print >>sys.stderr, 'result graph:'
  110. print >>sys.stderr, create_graph(res)
  111. print >>sys.stderr, 'expected graph:'
  112. print >>sys.stderr, create_graph(out)
  113. if fail:
  114. raise
  115. def graph(parser, *exp, **kwargs):
  116. return create_graph(ParserWrapper(parser, **kwargs).run(exp))
  117. def line(parser, *exp, **kwargs):
  118. return generate_line(ParserWrapper(parser, **kwargs).run(exp))