■ ■ ■ ■ ■ ■
pkg/ast/languages/ruby/patterns/patterns.go
| skipped 156 lines |
157 | 157 | | return nil |
158 | 158 | | } |
159 | 159 | | |
160 | | - | nodeElement := writer.Identifier(writer.nodeVariableGenerator.Get(node)) |
| 160 | + | nodeElement := writer.nodeVariable(node) |
161 | 161 | | |
162 | 162 | | if node.Type() == "program" { |
163 | 163 | | if node.ChildCount() != 1 { |
| skipped 15 lines |
179 | 179 | | ) |
180 | 180 | | } else { |
181 | 181 | | childIndexVariable := writer.Identifier(fmt.Sprintf("tmp%d", writer.tempIdGenerator.Get())) |
182 | | - | nodeAnchoredBefore, _ := writer.langImplementation.PatternIsAnchored(node) |
| 182 | + | nodeAnchoredBefore, nodeAnchoredAfter := writer.langImplementation.PatternIsAnchored(node) |
183 | 183 | | |
184 | | - | // Anchored before |
185 | | - | if node.IsNamed() && nodeAnchoredBefore && !slices.Contains(writer.inputParams.UnanchoredOffsets, int(node.StartByte())) { |
| 184 | + | // anonymous node, or anchored before |
| 185 | + | if !node.IsNamed() || (nodeAnchoredBefore && !slices.Contains(writer.inputParams.UnanchoredOffsets, int(node.StartByte()))) { |
186 | 186 | | if writer.lastChildIndexVariable != nil { |
187 | 187 | | writer.literals = append( |
188 | 188 | | writer.literals, |
| skipped 7 lines |
196 | 196 | | ) |
197 | 197 | | |
198 | 198 | | } |
199 | | - | } else { |
| 199 | + | } else { // Unanchored before |
200 | 200 | | if writer.lastChildIndexVariable != nil { |
201 | 201 | | writer.literals = append( |
202 | 202 | | writer.literals, |
| skipped 7 lines |
210 | 210 | | } |
211 | 211 | | } |
212 | 212 | | |
213 | | - | // FIXME: end anchoring |
214 | | - | // if node.IsNamed() && isLastChild && nodeAnchoredAfter && !slices.Contains(writer.inputParams.UnanchoredOffsets, int(node.EndByte())) { |
215 | | - | // // Last anchored |
216 | | - | // } |
| 213 | + | // Last anchored after |
| 214 | + | // FIXME: Maybe this should happen one level up? |
| 215 | + | if node.IsNamed() && nodeIsLastNamed(node) && nodeAnchoredAfter && !slices.Contains(writer.inputParams.UnanchoredOffsets, int(node.EndByte())) { |
| 216 | + | writer.literals = append( |
| 217 | + | writer.literals, |
| 218 | + | writer.NegativePredicate( |
| 219 | + | "AST_ParentChild", |
| 220 | + | writer.parentElement, |
| 221 | + | // FIXME: hack! need expressions (maybe just make it all text!) |
| 222 | + | writer.Identifier(fmt.Sprintf("%s + 1", childIndexVariable)), |
| 223 | + | writer.Any(), |
| 224 | + | ), |
| 225 | + | ) |
| 226 | + | } |
217 | 227 | | |
218 | 228 | | writer.literals = append( |
219 | 229 | | writer.literals, |
| skipped 78 lines |
298 | 308 | | } |
299 | 309 | | |
300 | 310 | | func (writer *patternWriter) optionalEmpty(node *sitter.Node, fieldName string) writerbase.Literal { |
301 | | - | nodeElement := writer.Identifier(writer.nodeVariableGenerator.Get(node)) |
| 311 | + | nodeElement := writer.nodeVariable(node) |
302 | 312 | | tempVariable := writer.tempVariable() |
303 | 313 | | |
304 | 314 | | return writer.Disjunction( |
| skipped 8 lines |
313 | 323 | | ), |
314 | 324 | | ), |
315 | 325 | | ) |
| 326 | + | } |
| 327 | + | |
| 328 | + | func (writer *patternWriter) nodeVariable(node *sitter.Node) writerbase.Identifier { |
| 329 | + | return writer.Identifier(writer.nodeVariableGenerator.Get(node)) |
| 330 | + | } |
| 331 | + | |
| 332 | + | func nodeIsLastNamed(node *sitter.Node) bool { |
| 333 | + | for { |
| 334 | + | next := node.NextSibling() |
| 335 | + | if next == nil { |
| 336 | + | return true |
| 337 | + | } |
| 338 | + | |
| 339 | + | if next.IsNamed() { |
| 340 | + | return false |
| 341 | + | } |
| 342 | + | |
| 343 | + | node = next |
| 344 | + | } |
316 | 345 | | } |
317 | 346 | | |
318 | 347 | | type literalNode struct { |
| skipped 66 lines |