/src/lib/parse/parse_table.e
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.