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

/src/lib/parse/parse_table.e

http://github.com/tybor/Liberty
Specman e | 217 lines | 157 code | 19 blank | 41 comment | 4 complexity | a2f0d215e9a14ada9b89938cb8b5eaa8 MD5 | raw file
  1-- This file is part of a Liberty Eiffel library.
  2-- See the full copyright at the end.
  3--
  4class PARSE_TABLE[C_ -> PARSE_CONTEXT]
  5   --
  6   -- A parsing table (aka Grammar).
  7   --
  8   -- The only way to create a parse table is to use Liberty Eiffel's manifest notation.
  9   --
 10   -- The structure of this notation is:
 11   --
 12   --    {PARSE_TABLE[...] << name, atom;
 13   --                         name, atom;
 14   --                           . . .
 15   --                         name, atom
 16   --                      >>}
 17   --
 18   -- where each name is a STRING and each atom may be either a PARSE_NON_TERMINAL or a PARSE_TERMINAL.
 19   --
 20
 21insert
 22   LOGGING
 23      redefine
 24         out_in_tagged_out_memory
 25      end
 26
 27create {ANY}
 28   manifest_creation
 29
 30create {PARSER_FACET}
 31   with_capacity
 32
 33feature {ANY}
 34   is_coherent: BOOLEAN
 35         -- True if all the used atoms are defined
 36      local
 37         i: INTEGER; atom: PARSE_ATOM[C_]
 38      do
 39         from
 40            Result := True
 41            i := atoms.lower
 42         until
 43            not Result or else i > atoms.upper
 44         loop
 45            atom := atoms.item(i)
 46            Result := atom.is_coherent
 47            if not Result then
 48               breakpoint
 49            end
 50            i := i + 1
 51         end
 52      ensure
 53         must_be_coherent: Result
 54      end
 55
 56   has (atom_name: ABSTRACT_STRING): BOOLEAN
 57      require
 58         not atom_name.is_empty
 59      do
 60         Result := atoms.fast_has(atom_name.intern)
 61      end
 62
 63   set_default_tree_builders (non_terminal_builder: PROCEDURE[TUPLE[FIXED_STRING, TRAVERSABLE[FIXED_STRING]]]; terminal_builder: PROCEDURE[TUPLE[FIXED_STRING, PARSER_IMAGE]])
 64      require
 65         is_coherent
 66      local
 67         i: INTEGER
 68      do
 69         from
 70            i := atoms.lower
 71         until
 72            i > atoms.upper
 73         loop
 74            atoms.item(i).set_default_tree_builders(non_terminal_builder, terminal_builder)
 75            i := i + 1
 76         end
 77      end
 78
 79   extend (a_table: like Current)
 80         -- Extends Current with a *copy* of the atoms of `a_table'. Any atom with a name already existing in
 81         -- Current is ignored.
 82      require
 83         a_table /= Void
 84         a_table /= Current
 85      local
 86         i: INTEGER; atom: PARSE_ATOM[C_]
 87      do
 88         from
 89            i := a_table.atoms.lower
 90         until
 91            i > a_table.atoms.upper
 92         loop
 93            if not atoms.fast_has(a_table.atoms.key(i)) then
 94               atom := a_table.atoms.item(i).twin
 95               atom.set_table(Current)
 96               atoms.add(atom, a_table.atoms.key(i))
 97            end
 98            i := i + 1
 99         end
100      end
101
102   add_or_replace (atom_name: ABSTRACT_STRING; atom: PARSE_ATOM[C_])
103      require
104         atom_name /= Void
105         atom /= Void
106      do
107         atoms.put(atom, atom_name.intern)
108      ensure
109         item(atom_name.intern) = atom
110      end
111
112   item (atom_name: ABSTRACT_STRING): PARSE_ATOM[C_]
113      require
114         not atom_name.is_empty
115         has(atom_name)
116      do
117         Result := atoms.fast_reference_at(atom_name.intern)
118         debug
119            if Result = Void then
120               log.trace.put_string(once "Unknown atom: ")
121               log.trace.put_line(atom_name)
122               log.trace.put_line(once "Known atoms:")
123               log.trace.put_line(once "--8<--------")
124               atoms.for_each(agent print_atom(?, ?))
125               log.trace.put_line(once "-------->8--")
126               breakpoint
127            end
128         end
129      end
130
131   out_in_tagged_out_memory
132      do
133         for_all_atoms(agent (atom: PARSE_ATOM[C_]) do atom.out_in_tagged_out_memory; tagged_out_memory.extend('%N') end)
134      end
135
136   pretty_print_on (stream: OUTPUT_STREAM)
137      require
138         stream.is_connected
139      do
140         for_all_atoms(agent {PARSE_ATOM[C_]}.pretty_print_on(stream))
141      end
142
143   for_all_atoms (action: PROCEDURE[TUPLE[PARSE_ATOM[C_]]])
144      require
145         action /= Void
146      do
147         atoms.for_each(action)
148      end
149
150feature {}
151   print_atom (v: PARSE_ATOM[C_]; k: FIXED_STRING)
152      do
153         log.trace.put_character('"')
154         log.trace.put_string(k)
155         log.trace.put_character('"')
156         log.trace.put_string(once " => ")
157         log.trace.put_line(v.out)
158      end
159
160feature {PARSE_TABLE}
161   atoms: LINKED_HASHED_DICTIONARY[PARSE_ATOM[C_], FIXED_STRING]
162
163feature {PARSER_FACET}
164   add (name: ABSTRACT_STRING; atom: PARSE_ATOM[C_])
165      require
166         not has(name)
167         atom.name = Void
168      do
169         atoms.add(atom, name.intern)
170         atom.set(name, Current)
171      ensure
172         atoms.count = old atoms.count + 1
173         atoms.last = atom
174      end
175
176feature {}
177   with_capacity, manifest_make (needed_capacity: INTEGER)
178      do
179         create atoms.with_capacity(needed_capacity)
180      end
181
182   manifest_put (index: INTEGER; name: ABSTRACT_STRING; atom: PARSE_ATOM[C_])
183      require
184         not has(name)
185         atom.name = Void
186         atoms.count = index
187      do
188         add(name, atom)
189      ensure
190         atom.name = name.intern
191         atoms.count = old atoms.count + 1
192         atoms.last = atom
193      end
194
195   manifest_semicolon_check: INTEGER 2
196
197end -- class PARSE_TABLE
198--
199-- Copyright (C) 2009-2017: by all the people cited in the AUTHORS file.
200--
201-- Permission is hereby granted, free of charge, to any person obtaining a copy
202-- of this software and associated documentation files (the "Software"), to deal
203-- in the Software without restriction, including without limitation the rights
204-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
205-- copies of the Software, and to permit persons to whom the Software is
206-- furnished to do so, subject to the following conditions:
207--
208-- The above copyright notice and this permission notice shall be included in
209-- all copies or substantial portions of the Software.
210--
211-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
212-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
213-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
214-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
215-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
216-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
217-- THE SOFTWARE.