-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexpression_shape.go
More file actions
94 lines (89 loc) · 2.68 KB
/
Copy pathexpression_shape.go
File metadata and controls
94 lines (89 loc) · 2.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package ember
// expressionSingleCall recognizes a call with no surrounding operators or
// selectors. IDs are stable arena handles; callers resolve payloads through
// the same syntaxTree rather than copying mutable node views.
func expressionSingleCall(tree syntaxTree, expr expressionID) (arenaCallID, bool) {
value, ok := expressionRawSingleTerm(tree, expr)
if !ok || tree.termKind(value) == syntaxTermCast {
return 0, false
}
for tree.termKind(value) == syntaxTermGroup {
inner, ok := tree.termGroup(value)
if !ok {
return 0, false
}
value, ok = expressionRawSingleTerm(tree, inner)
if !ok {
return 0, false
}
}
call, ok := tree.termCall(value)
if !ok {
return 0, false
}
selectors, ok := tree.termSelectors(value)
return call, ok && len(selectors) == 0
}
func expressionSingleVararg(tree syntaxTree, expr expressionID) (termID, bool) {
value, ok := expressionRawSingleTerm(tree, expr)
if !ok || tree.termKind(value) == syntaxTermCast || !tree.termVararg(value) {
return 0, false
}
selectors, ok := tree.termSelectors(value)
return value, ok && len(selectors) == 0
}
func expressionSingleTerm(tree syntaxTree, expr expressionID) (termID, bool) {
value, ok := expressionRawSingleTerm(tree, expr)
if !ok {
return 0, false
}
return termWithoutCastsAndGroups(tree, value), true
}
func expressionRawSingleTerm(tree syntaxTree, expr expressionID) (termID, bool) {
terms, ok := tree.expressionTerms(expr)
if !ok || len(terms) != 1 {
return 0, false
}
comparisons, ok := tree.andTerms(terms[0])
if !ok || len(comparisons) != 1 {
return 0, false
}
comparison := comparisons[0]
if tree.comparisonOperator(comparison) != "" || tree.comparisonRight(comparison) != 0 {
return 0, false
}
left := tree.comparisonLeft(comparison)
rest, ok := tree.concatRest(left)
if !ok || len(rest) != 0 {
return 0, false
}
additive := tree.concatFirst(left)
restAdd, ok := tree.additiveRest(additive)
if !ok || len(restAdd) != 0 {
return 0, false
}
multiplicative := tree.additiveFirst(additive)
restMul, ok := tree.multiplicativeRest(multiplicative)
if !ok || len(restMul) != 0 {
return 0, false
}
return tree.multiplicativeFirst(multiplicative), true
}
func termWithoutCastsAndGroups(tree syntaxTree, value termID) termID {
for tree.termKind(value) == syntaxTermCast || tree.termKind(value) == syntaxTermGroup {
if tree.termKind(value) == syntaxTermCast {
// Casts are represented as a distinct immutable term; there is no
// child expression to unwrap, so stop at the underlying handle.
return value
}
inner, ok := tree.termGroup(value)
if !ok {
return value
}
value, ok = expressionSingleTerm(tree, inner)
if !ok {
return value
}
}
return value
}