Repository navigation
Expand file tree
/
Copy pathquestionSubscripts.lsc
More file actions
98 lines (84 loc) · 3.43 KB
/
Copy pathquestionSubscripts.lsc
File metadata and controls
98 lines (84 loc) · 3.43 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
95
96
97
98
// Whitespace-sensitive parsing for `?(`
import { Plugin } from '../core/plugin'
import { types as tt } from "../../tokenizer/types"
questionSubscripts = new Plugin({
name: 'questionSubscripts'
mixin(ParserBase, opts) -> {
return class extends ParserBase {
questionSubscripts_parseSafeCall(lhs, startPos, startLoc, state) -> {
node = this.startNodeAt(startPos, startLoc)
// TODO: factor this out somehow
// tildeCall should be able to declare loadAfter: questionSubscripts
// and then hook by overriding
if this.hasPlugin("tildeCall") and this.match(this.tt_tildeCall):
return this.tildeCall_parse(node, lhs, startPos, startLoc, state, true)
if this.hasPlugin("bangCall") and this.match(tt.bang):
this.bangCall_parse(node, lhs, state)
// optionality
node.optional = true
state.optionalChainMember = true
return this.finishOptionalCallExpression(node)
node.callee = lhs
node.optional = true
this.expect(tt.parenL)
node.arguments = this.parseCallExpressionArguments(tt.parenR, false)
this.toReferencedList(node.arguments)
state.optionalChainMember = true
this.addExtra(node, "dotted", false)
return this.finishOptionalCallExpression(node)
}
questionSubscripts_parseSafeMember(lhs, startPos, startLoc, noCalls, state) -> {
node = this.startNodeAt(startPos, startLoc)
node.object = lhs
this.expect(tt.bracketL)
node.property = this.parseExpression()
node.computed = true
node.optional = true
this.expect(tt.bracketR)
state.optionalChainMember = true
this.addExtra(node, "dotted", false)
return this.finishNode(node, "OptionalMemberExpression")
}
questionSubscripts_isPossibleSafeCall() -> {
this.match(tt.parenL) or
(this.hasPlugin("tildeCall") and this.match(this.tt_tildeCall)) or
(this.hasPlugin("bangCall") and this.match(tt.bang))
}
questionSubscripts_isPossibleMember() -> {
this.match(tt.bracketL)
}
questionSubscripts_parse(lhs, startPos, startLoc, noCalls, parseSubscriptState) -> {
const questionPos = this.state.pos;
const questionLine = this.state.curLine;
const state = this.state.clone();
this.expect(tt.question);
if this.isAdjacent():
if (not noCalls) and this.questionSubscripts_isPossibleSafeCall():
try:
return this.questionSubscripts_parseSafeCall(lhs, startPos, startLoc, parseSubscriptState)
catch err:
null
elif this.questionSubscripts_isPossibleMember():
try:
return this.questionSubscripts_parseSafeMember(lhs, startPos, startLoc, noCalls, parseSubscriptState)
catch err:
null
// Not a safe expr, must be a ternary
this.state = state
parseSubscriptState.stop = true
return lhs
}
parseSubscript(lhs, startPos, startLoc, noCalls, state) -> {
if (
this.match(tt.question) and
this.isAdjacent() and
this.hasPlugin("optionalChaining")
):
this.questionSubscripts_parse(lhs, startPos, startLoc, noCalls, state)
else:
super.parseSubscript(lhs, startPos, startLoc, noCalls, state)
}
} // class
} // mixin
})
export default questionSubscripts