-
Notifications
You must be signed in to change notification settings - Fork 1
/
syntax.go
127 lines (110 loc) · 2.98 KB
/
syntax.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
/*
Copyright 2021 Aaron Moss
Copyright 2020 Marius Ackerman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package ast
import (
"github.com/bruceiv/pegll/token"
)
// A syntax rule
type SyntaxRule struct {
Head *NT
Alternates []*SyntaxAlternate
IsOrdered bool
}
// An alternate expression
type SyntaxAlternate struct {
Symbols []SyntaxSymbol
}
// A syntax suffix operator
type SyntaxSuffix struct {
// expression made optional
Expr SyntaxSymbol
// token for operator
Tok *token.Token
// signifies the type of suffix
// 0: optional (?)
// 1: repeat zero or more times (*)
// 2: repeat one or more times (+)
Type int
}
// A syntax symbol
type SyntaxSymbol interface {
isSyntaxSymbol()
// Lext returns the left extent of SyntaxSymbol in the input string
Lext() int
// The ID of the symbol
// which is the literal string of a LexRule, SyntaxRule or StringLit.
ID() string
// The string of the symbol
String() string
}
// A lookahead expression
type Lookahead struct {
// operator for expression
Op *token.Token
// operator subexpression. (should not be lookahead)
Expr SyntaxSymbol
}
// non-terminals
func (*NT) isSyntaxSymbol() {}
func (*Lookahead) isSyntaxSymbol() {}
func (SyntaxSuffix) isSyntaxSymbol() {}
// terminals
func (*TokID) isSyntaxSymbol() {}
func (*StringLit) isSyntaxSymbol() {}
/* Syntax Rules */
// ID returns the head of rule r
func (r *SyntaxRule) ID() string {
return r.Head.ID()
}
func (r *SyntaxRule) Lext() int {
return r.Head.Lext()
}
// true if always matches; false if unable to guarantee always matches
func (r *SyntaxRule) AlwaysMatches() bool {
return r.Alternates[len(r.Alternates)-1].Empty()
}
func (a *SyntaxAlternate) Empty() bool {
return len(a.Symbols) == 0
}
func (a *SyntaxAlternate) GetSymbols() []string {
symbols := make([]string, len(a.Symbols))
for i, s := range a.Symbols {
symbols[i] = s.ID()
}
return symbols
}
/* Syntax Suffix */
func (opt *SyntaxSuffix) ID() string {
return opt.Expr.ID() + opt.Tok.LiteralString()
}
func (opt *SyntaxSuffix) Lext() int {
return opt.Expr.Lext()
}
func (opt *SyntaxSuffix) String() string {
return opt.Expr.String() + opt.Tok.LiteralString()
}
/* Lookahead */
func (e *Lookahead) Lext() int {
return e.Op.Lext()
}
func (e *Lookahead) ID() string {
return e.Op.LiteralString() + e.Expr.ID()
}
func (e *Lookahead) String() string {
return e.Op.LiteralString() + e.Expr.String()
}
// true for positive (&) lookahead, false for negative (!) lookahead
func (e *Lookahead) Positive() bool {
return e.Op.LiteralString() == "&"
}