/src/lib/parse/descending_parser.e

http://github.com/tybor/Liberty · Specman e · 172 lines · 128 code · 13 blank · 31 comment · 6 complexity · 9d5e7c737259e9117995a8455df61375 MD5 · raw file

  1. -- This file is part of a Liberty Eiffel library.
  2. -- See the full copyright at the end.
  3. --
  4. class DESCENDING_PARSER
  5. --
  6. -- The entry point to LL(n) parsing. Currently that top-down parsing is directly implemented in the
  7. -- PARSE_ATOM classes.
  8. --
  9. insert
  10. TRISTATE_VALUES
  11. LOGGING
  12. creation {ANY}
  13. make
  14. feature {ANY}
  15. parse (buffer: MINI_PARSER_BUFFER; grammar: PARSE_TABLE; start: STRING; a_actions: COLLECTION[PARSE_ACTION]): BOOLEAN is
  16. -- Returns True if the parsing succeeded or definitely could not succeed, False if some more text
  17. -- could make it succeed.
  18. require
  19. a_actions /= Void
  20. grammar.is_coherent
  21. grammar.has(start)
  22. local
  23. atom: PARSE_ATOM
  24. parsed: TRISTATE
  25. do
  26. error := Void
  27. atom := grammar.item(start)
  28. parsed := atom.parse(buffer, a_actions)
  29. if parsed = yes then
  30. Result := True
  31. elseif parsed = no then
  32. error := buffer.last_error
  33. if error = Void then
  34. create error.make(1, once "This does not look like Eiffel, not even remotely.", Void)
  35. end
  36. Result := True
  37. else
  38. check
  39. should_add_more: not Result
  40. end
  41. end
  42. ensure
  43. a_actions.count >= old a_actions.count
  44. end
  45. eval (buffer: MINI_PARSER_BUFFER; grammar: PARSE_TABLE; start: STRING): BOOLEAN is
  46. -- Returns True if the parsing succeeded or definitely could not succeed, False if some more text
  47. -- could make it succeed.
  48. local
  49. i: INTEGER
  50. do
  51. save_actions
  52. Result := parse(buffer, grammar, start, actions)
  53. if Result and then error = Void then
  54. debug ("parse")
  55. log.trace.put_line(once "Actions:")
  56. log.trace.put_line(once "--8<-------- <start actions>")
  57. from
  58. i := actions.lower
  59. until
  60. i > actions.upper
  61. loop
  62. log.trace.put_integer(i)
  63. log.trace.put_character('%T')
  64. log.trace.put_line(actions.item(i).name)
  65. i := i + 1
  66. end
  67. log.trace.put_line(once "-------->8-- <end actions>")
  68. end
  69. from
  70. i := actions.lower
  71. until
  72. i > actions.upper
  73. loop
  74. debug ("parse")
  75. log.trace.put_string(once "Calling action #")
  76. log.trace.put_integer(i)
  77. log.trace.put_string(once ": ")
  78. log.trace.put_line(actions.item(i).name)
  79. end
  80. actions.item(i).call
  81. i := i + 1
  82. end
  83. end
  84. actions.clear_count
  85. restore_actions
  86. end
  87. error: PARSE_ERROR
  88. feature {}
  89. make is
  90. do
  91. end
  92. used_actions: FAST_ARRAY[FAST_ARRAY[PARSE_ACTION]] is
  93. once
  94. create Result.make(0)
  95. end
  96. free_actions: FAST_ARRAY[FAST_ARRAY[PARSE_ACTION]] is
  97. once
  98. create Result.make(0)
  99. end
  100. actions: FAST_ARRAY[PARSE_ACTION]
  101. save_actions is
  102. do
  103. if actions = Void then
  104. actions := new_free_actions
  105. elseif not actions.is_empty then
  106. used_actions.add_last(actions)
  107. actions := new_free_actions
  108. end
  109. ensure
  110. actions.is_empty
  111. ;(old (actions /= Void and then not actions.is_empty)) implies (used_actions.last = old actions)
  112. ;(old (actions /= Void and then not actions.is_empty)) implies (used_actions.count = old used_actions.count + 1)
  113. end
  114. restore_actions is
  115. require
  116. actions.is_empty
  117. do
  118. if not used_actions.is_empty then
  119. free_actions.add_last(actions)
  120. actions := used_actions.last
  121. used_actions.remove_last
  122. end
  123. ensure
  124. actions /= Void
  125. ;(not old used_actions.is_empty) implies (actions = (old used_actions.twin).last)
  126. ;(not old used_actions.is_empty) implies (used_actions.count = old used_actions.count - 1)
  127. end
  128. new_free_actions: like actions is
  129. do
  130. if free_actions.is_empty then
  131. create Result.make(0)
  132. else
  133. Result := free_actions.last
  134. free_actions.remove_last
  135. end
  136. ensure
  137. Result.is_empty
  138. end
  139. end -- class DESCENDING_PARSER
  140. --
  141. -- Copyright (c) 2009 by all the people cited in the AUTHORS file.
  142. --
  143. -- Permission is hereby granted, free of charge, to any person obtaining a copy
  144. -- of this software and associated documentation files (the "Software"), to deal
  145. -- in the Software without restriction, including without limitation the rights
  146. -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  147. -- copies of the Software, and to permit persons to whom the Software is
  148. -- furnished to do so, subject to the following conditions:
  149. --
  150. -- The above copyright notice and this permission notice shall be included in
  151. -- all copies or substantial portions of the Software.
  152. --
  153. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  154. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  155. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  156. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  157. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  158. -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  159. -- THE SOFTWARE.