Class: Ibex::Runtime::CST::SyntaxNode
- Inherits:
-
Object
- Object
- Ibex::Runtime::CST::SyntaxNode
- Includes:
- Enumerable
- Defined in:
- lib/json5/generated_parser.rb
Overview
Lazy Red navigation facade for one Green node occurrence.
Instance Attribute Summary collapse
- #green ⇒ Object readonly
- #index ⇒ Object readonly
- #kinds ⇒ Object readonly
- #offset ⇒ Object readonly
- #parent ⇒ Object readonly
- #source_text ⇒ Object readonly
- #trivia_policy ⇒ Object readonly
Instance Method Summary collapse
- #==(other) ⇒ Object
- #ancestors ⇒ Object
- #annotate(annotation) ⇒ Object
- #annotated(annotation) ⇒ Object
- #child_at(child_index) ⇒ Object
- #child_nodes ⇒ Object
- #children ⇒ Object
- #contains_error? ⇒ Boolean
-
#covering(range) ⇒ Object
Return the smallest syntax element whose full span covers a range.
- #cursor ⇒ Object
- #deconstruct ⇒ Object
- #deconstruct_keys(_keys) ⇒ Object
- #descendants ⇒ Object
- #each(&block) ⇒ Object
- #each_error(&block) ⇒ Object
- #error? ⇒ Boolean
- #find(kind:) ⇒ Object
- #first_token ⇒ Object
- #full_span ⇒ Object
- #full_text ⇒ Object (also: #to_source)
- #incomplete_input? ⇒ Boolean
-
#initialize(green:, kinds:, parent: nil, index: 0, offset: 0, trivia_policy: :leading, source_text: nil) ⇒ SyntaxNode
constructor
A new instance of SyntaxNode.
- #insert_child(child_index, child) ⇒ Object
- #kind ⇒ Object
- #kind_name ⇒ Object
- #last_token ⇒ Object
- #location ⇒ Object
- #missing? ⇒ Boolean
- #next_sibling ⇒ Object
- #prev_sibling ⇒ Object
-
#production_id ⇒ Object
Green kinds replace occurrence-local production ids.
- #remove_child(child_index) ⇒ Object
- #replace_with(replacement) ⇒ Object
- #root ⇒ Object
- #same_node?(other) ⇒ Boolean
- #span ⇒ Object
-
#symbol ⇒ Object
Compatibility name for the physical grammar symbol.
- #text ⇒ Object
- #to_h ⇒ Object
-
#token_at(source_offset) ⇒ Object
Find the full-span-owning token for a byte offset.
- #tokens ⇒ Object
-
#trailing_trivia ⇒ Object
Compatibility view of file-tail trivia.
- #walk(&block) ⇒ Object
- #with_child(child_index, child) ⇒ Object
Constructor Details
#initialize(green:, kinds:, parent: nil, index: 0, offset: 0, trivia_policy: :leading, source_text: nil) ⇒ SyntaxNode
Returns a new instance of SyntaxNode.
1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 |
# File 'lib/json5/generated_parser.rb', line 1136 def initialize(green:, kinds:, parent: nil, index: 0, offset: 0, trivia_policy: :leading, source_text: nil) @green = green @kinds = kinds @parent = parent @index = index @offset = offset @trivia_policy = trivia_policy @source_text = source_text || SourceText.new(root_source) @children = Array.new(@green.children.length) #: Array[element?] end |
Instance Attribute Details
#green ⇒ Object (readonly)
1126 1127 1128 |
# File 'lib/json5/generated_parser.rb', line 1126 def green @green end |
#index ⇒ Object (readonly)
1128 1129 1130 |
# File 'lib/json5/generated_parser.rb', line 1128 def index @index end |
#kinds ⇒ Object (readonly)
1130 1131 1132 |
# File 'lib/json5/generated_parser.rb', line 1130 def kinds @kinds end |
#offset ⇒ Object (readonly)
1129 1130 1131 |
# File 'lib/json5/generated_parser.rb', line 1129 def offset @offset end |
#parent ⇒ Object (readonly)
1127 1128 1129 |
# File 'lib/json5/generated_parser.rb', line 1127 def parent @parent end |
#source_text ⇒ Object (readonly)
1132 1133 1134 |
# File 'lib/json5/generated_parser.rb', line 1132 def source_text @source_text end |
#trivia_policy ⇒ Object (readonly)
1131 1132 1133 |
# File 'lib/json5/generated_parser.rb', line 1131 def trivia_policy @trivia_policy end |
Instance Method Details
#==(other) ⇒ Object
1461 1462 1463 |
# File 'lib/json5/generated_parser.rb', line 1461 def ==(other) other.is_a?(SyntaxNode) && @green == other.green end |
#ancestors ⇒ Object
1234 1235 1236 1237 1238 1239 1240 1241 1242 |
# File 'lib/json5/generated_parser.rb', line 1234 def ancestors Enumerator.new do |yielder| ancestor = @parent while ancestor yielder << ancestor ancestor = ancestor.parent end end end |
#annotate(annotation) ⇒ Object
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 |
# File 'lib/json5/generated_parser.rb', line 1357 def annotate(annotation) raise TypeError, "annotation must be a SyntaxAnnotation" unless annotation.is_a?(SyntaxAnnotation) return root if @green.annotations.include?(annotation) replace_with( GreenNode.new( kind: @green.kind, children: @green.children, flags: @green.intrinsic_flags, annotations: @green.annotations + [annotation] ) ) end |
#annotated(annotation) ⇒ Object
1370 1371 1372 1373 1374 1375 1376 1377 1378 |
# File 'lib/json5/generated_parser.rb', line 1370 def annotated(annotation) Enumerator.new do |yielder| visit = lambda do |node| yielder << node if node.green.annotations.include?(annotation) node.child_nodes.each { |child| visit.call(child) } end visit.call(self) end end |
#child_at(child_index) ⇒ Object
1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 |
# File 'lib/json5/generated_parser.rb', line 1179 def child_at(child_index) cached = @children.fetch(child_index) return cached if cached green_child = @green.children.fetch(child_index) child_offset = offset_for(child_index) value = if green_child.is_a?(GreenNode) self.class.new( green: green_child, kinds: @kinds, parent: self, index: child_index, offset: child_offset, trivia_policy: @trivia_policy, source_text: @source_text ) else SyntaxToken.new(green: green_child, parent: self, index: child_index, offset: child_offset) end @children[child_index] = value end |
#child_nodes ⇒ Object
1197 1198 1199 1200 1201 |
# File 'lib/json5/generated_parser.rb', line 1197 def child_nodes nodes = [] #: Array[SyntaxNode] children.each { |child| nodes << child if child.is_a?(SyntaxNode) } nodes.freeze end |
#children ⇒ Object
1163 1164 1165 |
# File 'lib/json5/generated_parser.rb', line 1163 def children @green.children.each_index.map { |child_index| child_at(child_index) }.freeze end |
#contains_error? ⇒ Boolean
1307 |
# File 'lib/json5/generated_parser.rb', line 1307 def contains_error? = @green.flags.anybits?(Flags::CONTAINS_ERROR) |
#covering(range) ⇒ Object
Return the smallest syntax element whose full span covers a range.
1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 |
# File 'lib/json5/generated_parser.rb', line 1398 def covering(range) ensure_coordinates! start_offset, end_offset = normalize_range(range) return unless covers_offsets?(start_offset, end_offset) node = self loop do child = node.children.find do |candidate| candidate_start = candidate.offset candidate_end = candidate.offset + candidate.green.full_width candidate_start <= start_offset && candidate_end >= end_offset end return node unless child return child if child.is_a?(SyntaxToken) node = child end end |
#cursor ⇒ Object
1453 |
# File 'lib/json5/generated_parser.rb', line 1453 def cursor = Cursor.new(self) |
#deconstruct ⇒ Object
1466 |
# File 'lib/json5/generated_parser.rb', line 1466 def deconstruct = children |
#deconstruct_keys(_keys) ⇒ Object
1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 |
# File 'lib/json5/generated_parser.rb', line 1469 def deconstruct_keys(_keys) values = { kind: :node, symbol: symbol, production_id: production_id, children: children, location: location, trailing_trivia: trailing_trivia } #: Hash[Symbol, Object?] @kinds.fields(kind).each do |name, slot| index = slot.is_a?(Hash) ? slot.fetch(:index) : slot values[name.to_sym] = child_at(index) end values.freeze end |
#descendants ⇒ Object
1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 |
# File 'lib/json5/generated_parser.rb', line 1245 def descendants Enumerator.new do |yielder| visit = lambda do |node| node.children.each do |child| yielder << child visit.call(child) if child.is_a?(SyntaxNode) end end visit.call(self) end end |
#each(&block) ⇒ Object
1171 1172 1173 1174 1175 1176 |
# File 'lib/json5/generated_parser.rb', line 1171 def each(&block) return enum_for(:each) unless block children.each(&block) self end |
#each_error(&block) ⇒ Object
1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 |
# File 'lib/json5/generated_parser.rb', line 1427 def each_error(&block) errors = Enumerator.new do |yielder| descendants.each do |element| yielder << element if element.error? || element.missing? end end #: Enumerator[element, void] return errors unless block errors.each(&block) self end |
#error? ⇒ Boolean
1301 |
# File 'lib/json5/generated_parser.rb', line 1301 def error? = @kinds.error?(kind) |
#find(kind:) ⇒ Object
1418 1419 1420 1421 1422 1423 |
# File 'lib/json5/generated_parser.rb', line 1418 def find(kind:) expected = kind.is_a?(Integer) ? kind : @kinds.fetch(kind) Enumerator.new do |yielder| descendants.each { |element| yielder << element if element.kind == expected } end end |
#first_token ⇒ Object
1211 |
# File 'lib/json5/generated_parser.rb', line 1211 def first_token = tokens.first |
#full_span ⇒ Object
1264 1265 1266 1267 |
# File 'lib/json5/generated_parser.rb', line 1264 def full_span ensure_coordinates! @offset...(@offset + @green.full_width) end |
#full_text ⇒ Object Also known as: to_source
1279 |
# File 'lib/json5/generated_parser.rb', line 1279 def full_text = @green.to_source |
#incomplete_input? ⇒ Boolean
1310 |
# File 'lib/json5/generated_parser.rb', line 1310 def incomplete_input? = @green.flags.anybits?(Flags::INCOMPLETE_INPUT) |
#insert_child(child_index, child) ⇒ Object
1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 |
# File 'lib/json5/generated_parser.rb', line 1329 def insert_child(child_index, child) raise IndexError, "child index #{child_index} is outside 0..#{@green.children.length}" unless child_index.between?(0, @green.children.length) children = @green.children.dup children.insert(child_index, Editing.green_element(child)) replace_with( GreenNode.new( kind: @green.kind, children: children, flags: @green.intrinsic_flags, annotations: @green.annotations ) ) end |
#kind ⇒ Object
1148 |
# File 'lib/json5/generated_parser.rb', line 1148 def kind = @green.kind |
#kind_name ⇒ Object
1151 |
# File 'lib/json5/generated_parser.rb', line 1151 def kind_name = @kinds.name(kind) |
#last_token ⇒ Object
1214 |
# File 'lib/json5/generated_parser.rb', line 1214 def last_token = tokens.last |
#location ⇒ Object
1276 |
# File 'lib/json5/generated_parser.rb', line 1276 def location = @source_text.location(span) |
#missing? ⇒ Boolean
1304 |
# File 'lib/json5/generated_parser.rb', line 1304 def missing? = false |
#next_sibling ⇒ Object
1217 1218 1219 1220 1221 1222 |
# File 'lib/json5/generated_parser.rb', line 1217 def next_sibling parent = @parent return unless parent parent.children[@index + 1] end |
#prev_sibling ⇒ Object
1225 1226 1227 1228 1229 1230 1231 |
# File 'lib/json5/generated_parser.rb', line 1225 def prev_sibling parent = @parent return unless parent return if @index.zero? parent.children[@index - 1] end |
#production_id ⇒ Object
Green kinds replace occurrence-local production ids. Keep the legacy key and reader with the historical synthetic sentinel.
1160 |
# File 'lib/json5/generated_parser.rb', line 1160 def production_id = -1 |
#remove_child(child_index) ⇒ Object
1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 |
# File 'lib/json5/generated_parser.rb', line 1344 def remove_child(child_index) children = @green.children.dup children.fetch(child_index) children.delete_at(child_index) replace_with( GreenNode.new( kind: @green.kind, children: children, flags: @green.intrinsic_flags, annotations: @green.annotations ) ) end |
#replace_with(replacement) ⇒ Object
1313 |
# File 'lib/json5/generated_parser.rb', line 1313 def replace_with(replacement) = Editing.replace(self, replacement) |
#root ⇒ Object
1258 1259 1260 1261 |
# File 'lib/json5/generated_parser.rb', line 1258 def root parent = @parent parent ? parent.root : self end |
#same_node?(other) ⇒ Boolean
1456 1457 1458 |
# File 'lib/json5/generated_parser.rb', line 1456 def same_node?(other) root.equal?(other.root) && @green.equal?(other.green) && @offset == other.offset end |
#span ⇒ Object
1270 1271 1272 1273 |
# File 'lib/json5/generated_parser.rb', line 1270 def span ensure_coordinates! (@offset + @green.leading_width)...(@offset + @green.full_width - @green.trailing_width) end |
#symbol ⇒ Object
Compatibility name for the physical grammar symbol.
1155 |
# File 'lib/json5/generated_parser.rb', line 1155 def symbol = @kinds.name(@kinds.nonterminal_of(kind)) |
#text ⇒ Object
1283 1284 1285 1286 1287 |
# File 'lib/json5/generated_parser.rb', line 1283 def text start_offset = @green.leading_width width = @green.full_width - @green.leading_width - @green.trailing_width full_text.byteslice(start_offset, width) || "".b end |
#to_h ⇒ Object
1482 |
# File 'lib/json5/generated_parser.rb', line 1482 def to_h = deconstruct_keys(nil) |
#token_at(source_offset) ⇒ Object
Find the full-span-owning token for a byte offset.
1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 |
# File 'lib/json5/generated_parser.rb', line 1382 def token_at(source_offset) ensure_coordinates! return unless source_offset >= @offset && source_offset < @offset + @green.full_width node = self loop do child = node.child_covering_offset(source_offset) return unless child return child if child.is_a?(SyntaxToken) node = child end end |
#tokens ⇒ Object
1204 1205 1206 1207 1208 |
# File 'lib/json5/generated_parser.rb', line 1204 def tokens values = [] #: Array[SyntaxToken] descendants.each { |element| values << element if element.is_a?(SyntaxToken) } values.freeze end |
#trailing_trivia ⇒ Object
Compatibility view of file-tail trivia. The Red/Green layout owns it on EOF rather than on the start node.
1292 1293 1294 1295 1296 1297 1298 |
# File 'lib/json5/generated_parser.rb', line 1292 def trailing_trivia eof = compatibility_eof return (eof.green.leading + eof.green.trailing).freeze if eof token = last_token token ? token.green.trailing : [] end |
#walk(&block) ⇒ Object
1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 |
# File 'lib/json5/generated_parser.rb', line 1440 def walk(&block) raise ArgumentError, "walk requires a block" unless block visit = lambda do |element| block.call(:enter, element) element.children.each { |child| visit.call(child) } if element.is_a?(SyntaxNode) block.call(:leave, element) end visit.call(self) self end |
#with_child(child_index, child) ⇒ Object
1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 |
# File 'lib/json5/generated_parser.rb', line 1316 def with_child(child_index, child) children = @green.children.dup children.fetch(child_index) children[child_index] = Editing.green_element(child) replace_with( GreenNode.new( kind: @green.kind, children: children, flags: @green.intrinsic_flags, annotations: @green.annotations ) ) end |