/src/lib/parse/parse_non_terminal.e

http://github.com/tybor/Liberty · Specman e · 211 lines · 150 code · 21 blank · 40 comment · 5 complexity · 24e024b1fae342f8602dbec56821c178 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class PARSE_NON_TERMINAL
  5. --
  6. -- A non-terminal meant to be put in a PARSE_TABLE.
  7. --
  8. -- The only way to create a non-terminal is to use SmartEiffel's manifest notation.
  9. --
  10. -- The structure of this notation is:
  11. --
  12. -- {PARSE_NON_TERMINAL << rule, agent;
  13. -- rule, agent;
  14. -- . . .
  15. -- rule, agent
  16. -- >>}
  17. --
  18. -- where each rule is a TRAVERSABLE[STRING] (with each String being the name of an atom of the
  19. -- PARSE_TABLE), and each agent may either be Void or a PROCEDURE[TUPLE] called when reducing the
  20. -- non-terminal.
  21. --
  22. inherit
  23. PARSE_ATOM
  24. redefine
  25. copy, is_equal, out_in_tagged_out_memory
  26. end
  27. insert
  28. LOGGING
  29. redefine
  30. copy, is_equal, out_in_tagged_out_memory
  31. end
  32. creation {ANY}
  33. manifest_creation
  34. feature {ANY}
  35. out_in_tagged_out_memory is
  36. do
  37. tagged_out_memory.extend('{')
  38. parser_tree.out_in_tagged_out_memory
  39. tagged_out_memory.extend('}')
  40. end
  41. feature {PARSE_TABLE}
  42. is_coherent: BOOLEAN is
  43. do
  44. Result := parser_tree.is_coherent
  45. end
  46. set_default_tree_builders (non_terminal_builder: PROCEDURE[TUPLE[FIXED_STRING, TRAVERSABLE[FIXED_STRING]]]; terminal_builder: PROCEDURE[TUPLE[FIXED_STRING, PARSER_IMAGE]]) is
  47. do
  48. if non_terminal_builder /= Void then
  49. save_tree_builder_path
  50. parser_tree.set_default_tree_builder(non_terminal_builder, tree_builder_path)
  51. restore_tree_builder_path
  52. end
  53. end
  54. feature {DESCENDING_PARSER, PARSE_NT_NODE}
  55. parse (buffer: MINI_PARSER_BUFFER; actions: COLLECTION[PARSE_ACTION]): TRISTATE is
  56. do
  57. Result := parser_tree.parse(buffer, actions)
  58. if Result = yes then
  59. buffer.set_last_error(Void)
  60. debug ("parse")
  61. log.trace.put_string(once "%T-->%Tnon-terminal ")
  62. print_error_position(log.trace, buffer)
  63. log.trace.put_character(' ')
  64. log.trace.put_character('"')
  65. log.trace.put_string(name)
  66. log.trace.put_character('"')
  67. log.trace.put_new_line
  68. end
  69. else
  70. debug ("parse")
  71. log.trace.put_string(once "** Expected non-terminal %"")
  72. log.trace.put_string(name)
  73. log.trace.put_string(once "%" ")
  74. print_error_position(log.trace, buffer)
  75. log.trace.put_new_line
  76. end
  77. end
  78. end
  79. feature {ANY}
  80. copy (other: like Current) is
  81. do
  82. name := other.name
  83. parser_tree := other.parser_tree.twin
  84. parser_tree.set_non_terminal(Current)
  85. end
  86. is_equal (other: like Current): BOOLEAN is
  87. do
  88. Result := name.is_equal(other.name) and then parser_tree.is_equal(other.parser_tree)
  89. end
  90. add (rule: TRAVERSABLE[FIXED_STRING]; action: PROCEDURE[TUPLE]) is
  91. require
  92. rule /= Void
  93. do
  94. parser_tree.add(rule, action)
  95. end
  96. feature {PARSE_NON_TERMINAL}
  97. parser_tree: PARSE_NT_NODE
  98. feature {}
  99. tree_builder_path_used: FAST_ARRAY[FAST_ARRAY[FIXED_STRING]] is
  100. once
  101. create Result.make(0)
  102. end
  103. tree_builder_path_free: FAST_ARRAY[FAST_ARRAY[FIXED_STRING]] is
  104. once
  105. create Result.make(0)
  106. end
  107. tree_builder_path: FAST_ARRAY[FIXED_STRING]
  108. save_tree_builder_path is
  109. do
  110. if tree_builder_path = Void then
  111. tree_builder_path := free_tree_builder_path
  112. elseif not tree_builder_path.is_empty then
  113. tree_builder_path_used.add_last(tree_builder_path)
  114. tree_builder_path := free_tree_builder_path
  115. end
  116. ensure
  117. tree_builder_path.is_empty
  118. ;(old (tree_builder_path /= Void and then not tree_builder_path.is_empty)) implies (tree_builder_path_used.last = old tree_builder_path)
  119. ;(old (tree_builder_path /= Void and then not tree_builder_path.is_empty)) implies (tree_builder_path_used.count = old tree_builder_path_used.count + 1)
  120. end
  121. restore_tree_builder_path is
  122. require
  123. tree_builder_path.is_empty
  124. do
  125. if not tree_builder_path_used.is_empty then
  126. tree_builder_path_free.add_last(tree_builder_path)
  127. tree_builder_path := tree_builder_path_used.last
  128. tree_builder_path_used.remove_last
  129. end
  130. ensure
  131. tree_builder_path /= Void
  132. ;(not old tree_builder_path_used.is_empty) implies (tree_builder_path = (old tree_builder_path_used.twin).last)
  133. ;(not old tree_builder_path_used.is_empty) implies (tree_builder_path_used.count = old tree_builder_path_used.count - 1)
  134. end
  135. free_tree_builder_path: like tree_builder_path is
  136. do
  137. if tree_builder_path_free.is_empty then
  138. create Result.make(0)
  139. else
  140. Result := tree_builder_path_free.last
  141. tree_builder_path_free.remove_last
  142. end
  143. ensure
  144. Result.is_empty
  145. end
  146. feature {}
  147. manifest_make (needed_capacity: INTEGER) is
  148. do
  149. create parser_tree.root(Current)
  150. end
  151. manifest_put (index: INTEGER; rule: TRAVERSABLE[ABSTRACT_STRING]; action: PROCEDURE[TUPLE[FIXED_STRING, TRAVERSABLE[FIXED_STRING]]]) is
  152. require
  153. rule /= Void
  154. local
  155. fixed_rule: FAST_ARRAY[FIXED_STRING]
  156. i: INTEGER
  157. do
  158. create fixed_rule.with_capacity(rule.count)
  159. from
  160. i := rule.lower
  161. until
  162. i > rule.upper
  163. loop
  164. fixed_rule.add_last(rule.item(i).intern)
  165. i := i + 1
  166. end
  167. parser_tree.add(fixed_rule, action)
  168. end
  169. manifest_semicolon_check: INTEGER is 2
  170. end -- class PARSE_NON_TERMINAL
  171. --
  172. -- Copyright (c) 2009 by all the people cited in the AUTHORS file.
  173. --
  174. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  175. -- of this software and associated documentation files (the "Software"), to deal
  176. -- in the Software without restriction, including without limitation the rights
  177. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  178. -- copies of the Software, and to permit persons to whom the Software is
  179. -- furnished to do so, subject to the following conditions:
  180. --
  181. -- The above copyright notice and this permission notice shall be included in
  182. -- all copies or substantial portions of the Software.
  183. --
  184. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  185. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  186. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  187. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  188. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  189. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  190. -- THE SOFTWARE.