r - ast_parser.go
1 package r
2
3 import (
4 "fmt"
5
6 "vimagination.zapto.org/parser"
7 )
8
9 // Token represents a single parsed token with source positioning.
10 type Token struct {
11 parser.Token
12 Pos, Line, LinePos uint64
13 }
14
15 // Tokens is a collection of Token values.
16 type Tokens []Token
17
18 type rParser Tokens
19
20 type Comments []Token
21
22 // Tokeniser is an interface representing a tokeniser.
23 type Tokeniser interface {
24 TokeniserState(parser.TokenFunc)
25 Iter(func(parser.Token) bool)
26 GetError() error
27 }
28
29 func newRParser(t Tokeniser) (rParser, error) {
30 t.TokeniserState(new(rTokeniser).expression)
31
32 var (
33 tokens rParser
34 pos, line, linePos uint64
35 err error
36 )
37
38 for tk := range t.Iter {
39 tokens = append(tokens, Token{
40 Token: tk,
41 Pos: pos,
42 Line: line,
43 LinePos: linePos,
44 })
45
46 switch tk.Type {
47 case parser.TokenError:
48 err = Error{
49 Err: t.GetError(),
50 Parsing: "Tokens",
51 Token: tokens[len(tokens)-1],
52 }
53 case TokenLineTerminator, TokenWhitespaceLineTerminator:
54 line++
55 linePos = 0
56 default:
57 linePos += uint64(len(tk.Data))
58 }
59
60 pos += uint64(len(tk.Data))
61 }
62
63 return tokens[0:0:len(tokens)], err
64 }
65
66 func (r rParser) NewGoal() rParser {
67 return r[len(r):]
68 }
69
70 func (r *rParser) Score(k rParser) {
71 *r = (*r)[:len(*r)+len(k)]
72 }
73
74 func (r *rParser) Next() Token {
75 l := len(*r)
76 *r = (*r)[:l+1]
77 tk := (*r)[l]
78
79 return tk
80 }
81
82 func (r *rParser) backup() {
83 *r = (*r)[:len(*r)-1]
84 }
85
86 func (r *rParser) Peek() parser.Token {
87 tk := r.Next().Token
88
89 r.backup()
90
91 return tk
92 }
93
94 func (r *rParser) Accept(ts ...parser.TokenType) bool {
95 tt := r.Next().Type
96
97 for _, pt := range ts {
98 if pt == tt {
99 return true
100 }
101 }
102
103 r.backup()
104
105 return false
106 }
107
108 func (r *rParser) AcceptRun(ts ...parser.TokenType) parser.TokenType {
109 Loop:
110 for {
111 tt := r.Next().Type
112
113 for _, pt := range ts {
114 if pt == tt {
115 continue Loop
116 }
117 }
118
119 r.backup()
120
121 return tt
122 }
123 }
124
125 func (r *rParser) AcceptToken(tk parser.Token) bool {
126 if r.Next().Token == tk {
127 return true
128 }
129
130 r.backup()
131
132 return false
133 }
134
135 func (r *rParser) ToTokens() Tokens {
136 return Tokens((*r)[:len(*r):len(*r)])
137 }
138
139 func (r *rParser) AcceptRunWhitespace() parser.TokenType {
140 return r.AcceptRun(TokenWhitespace, TokenLineTerminator, TokenWhitespaceLineTerminator, TokenComment)
141 }
142
143 func (r *rParser) AcceptRunWhitespaceNoComment() parser.TokenType {
144 return r.AcceptRun(TokenWhitespace, TokenWhitespaceLineTerminator, TokenLineTerminator)
145 }
146
147 func (r *rParser) AcceptRunWhitespaceComments() Comments {
148 var c Comments
149
150 s := r.NewGoal()
151
152 for s.AcceptRunWhitespaceNoComment() == TokenComment {
153 c = append(c, s.Next())
154
155 r.Score(s)
156
157 s = r.NewGoal()
158 }
159
160 return c
161 }
162
163 func (r *rParser) AcceptRunWhitespaceCommentsNoNewline() Comments {
164 var c Comments
165
166 s := r.NewGoal()
167
168 for s.AcceptRun(TokenWhitespace, TokenWhitespaceLineTerminator) == TokenComment {
169 r.Score(s)
170
171 c = append(c, r.Next())
172 s = r.NewGoal()
173
174 s.Accept(TokenLineTerminator, TokenWhitespaceLineTerminator)
175 }
176
177 return c
178 }
179
180 func (r *rParser) AcceptRunWhitespaceNoNewLine() parser.TokenType {
181 return r.AcceptRun(TokenWhitespace, TokenWhitespaceLineTerminator, TokenComment)
182 }
183
184 func (r *rParser) GetLastToken() *Token {
185 return &(*r)[len(*r)-1]
186 }
187
188 // Error is a parsing error with trace details.
189 type Error struct {
190 Err error
191 Parsing string
192 Token Token
193 }
194
195 // Error returns the error string.
196 func (e Error) Error() string {
197 return fmt.Sprintf("%s: error at position %d (%d:%d):\n%s", e.Parsing, e.Token.Pos+1, e.Token.Line+1, e.Token.LinePos+1, e.Err)
198 }
199
200 // Unwrap returns the wrapped error.
201 func (e Error) Unwrap() error {
202 return e.Err
203 }
204
205 func (r *rParser) Error(parsingFunc string, err error) error {
206 tk := r.Next()
207
208 r.backup()
209
210 return Error{
211 Err: err,
212 Parsing: parsingFunc,
213 Token: tk,
214 }
215 }
216