PageRenderTime 16ms CodeModel.GetById 13ms app.highlight 1ms RepoModel.GetById 1ms app.codeStats 0ms

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