parser.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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. from src.node import negation_to_node
  19. def create_graph(node):
  20. return generate_graph(negation_to_node(node))
  21. class ParserWrapper(object):
  22. def __init__(self, base_class, **kwargs):
  23. self.input_buffer = []
  24. self.last_buffer = ''
  25. self.input_position = 0
  26. self.closed = False
  27. self.verbose = kwargs.get('verbose', False)
  28. self.parser = base_class(file=self, read=self.read, **kwargs)
  29. def __getattr__(self, name):
  30. if name in self.__dict__:
  31. return getattr(self, name)
  32. return getattr(self.parser, name)
  33. def readline(self, nbytes=False):
  34. return self.read(nbytes)
  35. def read(self, nbytes=False):
  36. if len(self.last_buffer) >= nbytes:
  37. buf = self.last_buffer[:nbytes]
  38. self.last_buffer = self.last_buffer[nbytes:]
  39. return buf
  40. buf = self.last_buffer
  41. try:
  42. buf += self.input_buffer[self.input_position]
  43. if self.verbose:
  44. print 'read:', buf # pragma: nocover
  45. self.input_position += 1
  46. except IndexError:
  47. self.closed = True
  48. return ''
  49. self.last_buffer = buf[nbytes:]
  50. return buf
  51. def close(self):
  52. self.closed = True
  53. self.input_position = len(self.input_buffer)
  54. def run(self, input_buffer, *args, **kwargs):
  55. map(self.append, input_buffer)
  56. return self.parser.run(*args, **kwargs)
  57. def append(self, input):
  58. self.closed = False
  59. self.input_buffer.append(input + '\n')
  60. def run_expressions(base_class, expressions, fail=True, silent=False,
  61. **kwargs):
  62. """
  63. Run a list of mathematical expression through the term rewriting system and
  64. check if the output matches the expected output. The list of EXPRESSIONS
  65. consists of tuples (expression, output), where expression is the
  66. mathematical expression to evaluate (String) and output is the expected
  67. output of the evaluation (thus, the output can be Float, Int or None).
  68. If KEEPFILES is non-zero or True, the generated Flex and Bison files will
  69. be kept. Otherwise, those temporary files will be deleted. If FAIL is True,
  70. and the output of the expression is not equal to the expected output, an
  71. assertion error is raised. If SILENT is False, and an assertion error is
  72. raised, an error message is printed on stderr. If SILENT is True, no error
  73. message will be printed.
  74. If VERBOSE is non-zero and a positive integer number, verbosity of the term
  75. rewriting system will be increased. This will output debug messages and a
  76. higher value will print more types of debug messages.
  77. """
  78. parser = ParserWrapper(base_class, **kwargs)
  79. for exp, out in expressions:
  80. res = None
  81. try:
  82. res = parser.run([exp])
  83. assert res == out
  84. except: # pragma: nocover
  85. if not silent:
  86. print >>sys.stderr, 'error: %s gives %s, but expected: %s' \
  87. % (exp, str(res), str(out))
  88. if not silent and hasattr(res, 'nodes'):
  89. print >>sys.stderr, 'result graph:'
  90. print >>sys.stderr, create_graph(res)
  91. print >>sys.stderr, 'expected graph:'
  92. print >>sys.stderr, create_graph(out)
  93. if fail:
  94. raise
  95. def apply_expressions(base_class, expressions, fail=True, silent=False,
  96. **kwargs):
  97. parser = ParserWrapper(base_class, **kwargs)
  98. for exp, times, out in expressions:
  99. res = None
  100. try:
  101. parser.run([exp])
  102. parser.parser.rewrite(check_implicit=False)
  103. res = parser.parser.root_node
  104. assert res == out
  105. except: # pragma: nocover
  106. if not silent:
  107. print >>sys.stderr, 'error: %s gives %s, but expected: %s' \
  108. % (exp, str(res), str(out))
  109. if not silent and hasattr(res, 'nodes'):
  110. print >>sys.stderr, 'result graph:'
  111. print >>sys.stderr, create_graph(res)
  112. print >>sys.stderr, 'expected graph:'
  113. print >>sys.stderr, create_graph(out)
  114. if fail:
  115. raise
  116. def graph(parser, *exp, **kwargs):
  117. return create_graph(ParserWrapper(parser, **kwargs).run(exp))
  118. def line(parser, *exp, **kwargs):
  119. return generate_line(ParserWrapper(parser, **kwargs).run(exp))