-
Notifications
You must be signed in to change notification settings - Fork 0
/
grammar.go
executable file
·176 lines (135 loc) · 5.55 KB
/
grammar.go
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
/*
Package grammar contains data types used by LL(*) parser.
Grammar is represented in the form of nondeterministic state machine.
The machine uses stack holding current syntax tree node and its ancestor nodes together with their current states.
State contains map of transition rules (or ambiguous variants of rules).
A key is either a token type id, a literal id, or AnyToken value.
When parser tries to match a rule for current token the priorities are:
- a literal id;
- a token type id (unless the token text matches some reserved literal);
- AnyToken.
Transition rule contains the next state index (or FinalState value
if parsing of current node is finished) and new node index
(or SameNode value if no nested node is pushed).
Each time parser enters FinalState it drops current node.
When a rule is applied:
- if new node is SameNode:
- current state is set to next state;
- if matched rule key is not AnyToken: next token is read;
- else:
- new node and its initial state index are pushed;
*/
package grammar
const (
// RootNode is the index of root node in Grammar.Nodes.
RootNode = 0
)
// BitSet is a general bit set, where i-th bit represents item with index i.
type BitSet = int
// TokenFlags contain information about token type.
type TokenFlags int
// Token contains information about some token or literal.
type Token struct {
// Name is either a token type name or exact text for a literal.
Name string
// Re is RE2 expression defining this token type. Must not contain capturing groups.
// Empty string for literal and external tokens.
Re string
// Groups is a bit set of all groups this token belongs to.
// First defined group has index 0, "default" group is the last one.
// For literals this is a union of all Groups of all suitable token types.
Groups BitSet
// Flags contain information about token type.
Flags TokenFlags
}
const (
// LiteralToken matches exact text of some token.
LiteralToken TokenFlags = 1 << iota
// ExternalToken is a token type that is not actually present in source code,
// but can be emitted by token hooks.
// E.g. fake $begin and $end can be emitted when source code indentation level changes.
ExternalToken
// AsideToken is a token type that does not affect syntax and thus
// not fed to parser normally, but can be hooked. E.g. space or comment.
AsideToken
// ErrorToken is a token type that represents some lexical error, e.g. unmatched opening quote.
// This token automatically generates an error message containing captured text.
ErrorToken
// ShrinkableToken is a token that can be split into smaller parts if there is no suitable rule.
ShrinkableToken
// CaselessToken text consists of case-insensitive symbols.
// Parser converts its text to uppercase before comparing it with a literal.
CaselessToken
// ReservedToken marks literal that represents a reserved word.
ReservedToken
// NoLiteralsToken marks token type that cannot match any literal, e.g. raw text in HTML.
NoLiteralsToken
)
// Node contains information about some syntax tree node.
type Node struct {
// Name of node.
Name string
// FirstState is an index of initial state for this node.
FirstState int
}
const (
// AnyToken stored in Rule.Token matches any token except EoF.
// Used for fallback rules to skip optional or repeated parts of nodes.
AnyToken = -1
// FinalState stored in Rule.State means that current node must be finalized and dropped.
FinalState = -1
// SameNode stored in Rule.Node means that no nested node is pushed at this point.
SameNode = -1
)
// Rule contains a grammar rule for some set of tokens at some parsing state.
type Rule struct {
// Token is either an index in Grammar.Tokens slice or AnyToken.
Token int
// State is the index of next state or FinalState if this rule is the final one for node.
State int
// Node contains either SameNode or the index of nested node to push.
Node int
}
// MultiRule defines a list of ambiguous rules for some set of tokens at some parsing state.
type MultiRule struct {
// Token is an index in Grammar.Tokens slice.
Token int
// LowRule is the low index of the rule sub-slice for this token type.
LowRule int
// HighRule is the high index of the rule sub-slice for this token type.
HighRule int
}
// State represents a parsing state.
type State struct {
// Group is 0-based index of token group shared by all tokens
// that are acceptable at this point.
Group int `json:",omitempty"`
// LowMultiRule is the low index of the multi-rule sub-slice for this state.
// 0 if not used.
LowMultiRule int `json:",omitempty"`
// HighMultiRule is the high index of the multi-rule sub-slice for this state.
// 0 if not used.
HighMultiRule int `json:",omitempty"`
// LowRule is the low index of the rule sub-slice for this state.
// 0 if not used.
LowRule int `json:",omitempty"`
// HighRule is the high index of the rule sub-slice for this state.
// 0 if not used.
HighRule int `json:",omitempty"`
}
// Grammar holds all information required to make a parser.
type Grammar struct {
// Tokens is a list of tokens defined in grammar.
// First go defined token types, then external tokens, and the last are literals.
Tokens []Token
// Nodes is a list of defined nodes.
Nodes []Node
// States is a list of all parsing states for all nodes, grouped by node.
States []State
// MultiRules is a list of all ambiguous rule entries for all states.
// Grouped by state, entries in a group are sorted by Token field.
MultiRules []MultiRule
// Rules is a list of all parsing rules for all states.
// Grouped by state, entries in a group are sorted by Token field.
Rules []Rule
}