New upstream version 0.0~git20160905.0.58700b5
Alexandre Viau
7 years ago
0 | # This is the official list of Go authors for copyright purposes. | |
1 | ||
2 | # Names should be added to this file as | |
3 | # Name or Organization <email address> | |
4 | # The email address is not required for organizations. | |
5 | ||
6 | Andrew J Snodgrass <andy@pointlander.info> |
0 | Copyright (c) 2010, Go Authors | |
1 | All rights reserved. | |
2 | ||
3 | Redistribution and use in source and binary forms, with or without modification, | |
4 | are permitted provided that the following conditions are met: | |
5 | * Redistributions of source code must retain the above copyright notice, | |
6 | this list of conditions and the following disclaimer. | |
7 | * Redistributions in binary form must reproduce the above copyright notice, | |
8 | this list of conditions and the following disclaimer in the documentation and/or | |
9 | other materials provided with the distribution. | |
10 | * Neither the name of the Go Authors nor the names of its contributors may be used to | |
11 | endorse or promote products derived from this software without specific prior written permission. | |
12 | ||
13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY | |
14 | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |
15 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL | |
16 | THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
17 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | |
18 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
19 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
20 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, | |
21 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | peg: bootstrap.peg.go peg.go main.go | |
5 | go build | |
6 | ||
7 | bootstrap.peg.go: bootstrap/main.go peg.go | |
8 | cd bootstrap; go build | |
9 | bootstrap/bootstrap | |
10 | ||
11 | clean: | |
12 | rm -f bootstrap/bootstrap peg peg.peg.go |
0 | # About | |
1 | ||
2 | Peg, Parsing Expression Grammar, is an implementation of a Packrat parser | |
3 | generator. A Packrat parser is a descent recursive parser capable of | |
4 | backtracking. The generated parser searches for the correct parsing of the | |
5 | input. | |
6 | ||
7 | For more information see: | |
8 | * http://en.wikipedia.org/wiki/Parsing_expression_grammar | |
9 | * http://pdos.csail.mit.edu/~baford/packrat/ | |
10 | ||
11 | This Go implementation is based on: | |
12 | * http://piumarta.com/software/peg/ | |
13 | ||
14 | ||
15 | # Usage | |
16 | ||
17 | ``` | |
18 | -inline | |
19 | Tells the parser generator to inline parser rules. | |
20 | -switch | |
21 | Reduces the number of rules that have to be tried for some pegs. | |
22 | If statements are replaced with switch statements. | |
23 | ``` | |
24 | ||
25 | ||
26 | # Syntax | |
27 | ||
28 | First declare the package name: | |
29 | ``` | |
30 | package <package name> | |
31 | ``` | |
32 | ||
33 | Then declare the parser: | |
34 | ``` | |
35 | type <parser name> Peg { | |
36 | <parser state variables> | |
37 | } | |
38 | ``` | |
39 | ||
40 | Next declare the rules. The first rule is the entry point into the parser: | |
41 | ``` | |
42 | <rule name> <- <rule body> | |
43 | ``` | |
44 | ||
45 | The first rule should probably end with '!.' to indicate no more input follows: | |
46 | ``` | |
47 | first <- . !. | |
48 | ``` | |
49 | ||
50 | '.' means any character matches. For zero or more character matches use: | |
51 | ``` | |
52 | repetition <- .* | |
53 | ``` | |
54 | ||
55 | For one or more character matches use: | |
56 | ``` | |
57 | oneOrMore <- .+ | |
58 | ``` | |
59 | ||
60 | For an optional character match use: | |
61 | ``` | |
62 | optional <- .? | |
63 | ``` | |
64 | ||
65 | If specific characters are to be matched use single quotes: | |
66 | ``` | |
67 | specific <- 'a'* 'bc'+ 'de'? | |
68 | ``` | |
69 | will match the string "aaabcbcde". | |
70 | ||
71 | For choosing between different inputs use alternates: | |
72 | ``` | |
73 | prioritized <- 'a' 'a'* / 'bc'+ / 'de'? | |
74 | ``` | |
75 | will match "aaaa" or "bcbc" or "de" or "". The matches are attempted in order. | |
76 | ||
77 | If the characters are case insensitive use double quotes: | |
78 | ``` | |
79 | insensitive <- "abc" | |
80 | ``` | |
81 | will match "abc" or "Abc" or "ABc" etc... | |
82 | ||
83 | For matching a set of characters use a character class: | |
84 | ``` | |
85 | class <- [a-z] | |
86 | ``` | |
87 | will watch "a" or "b" or all the way to "z". | |
88 | ||
89 | For an inverse character class start with a tilde: | |
90 | ``` | |
91 | inverse <- [~a-z] | |
92 | ``` | |
93 | will match anything but "a" or "b" or all the way to "z" | |
94 | ||
95 | If the character class is case insensitive use double brackets: | |
96 | ``` | |
97 | insensitive <- [[A-Z]] | |
98 | ``` | |
99 | ||
100 | Use parentheses for grouping: | |
101 | ``` | |
102 | grouping <- (rule1 / rule2) rule3 | |
103 | ``` | |
104 | ||
105 | For looking ahead for a match (predicate) use: | |
106 | ``` | |
107 | lookAhead <- &rule1 rule2 | |
108 | ``` | |
109 | ||
110 | For inverse look ahead use: | |
111 | ``` | |
112 | inverse <- !rule1 rule2 | |
113 | ``` | |
114 | ||
115 | Use curly braces for Go code: | |
116 | ``` | |
117 | gocode <- { fmt.Println("hello world") } | |
118 | ``` | |
119 | ||
120 | For string captures use less than greater than: | |
121 | ``` | |
122 | capture <- <'capture'> { fmt.Println(buffer[begin:end]) } | |
123 | ``` | |
124 | Will print out "capture". The captured string is stored in buffer[begin:end]. | |
125 | ||
126 | ||
127 | # Files | |
128 | ||
129 | * bootstrap/main.go: bootstrap syntax tree of peg | |
130 | * peg.go: syntax tree and code generator | |
131 | * main.go: bootstrap main | |
132 | * peg.peg: peg in its own language | |
133 | ||
134 | ||
135 | # Testing | |
136 | ||
137 | There should be no differences between the bootstrap and self compiled: | |
138 | ||
139 | ``` | |
140 | ./peg -inline -switch peg.peg | |
141 | diff bootstrap.peg.go peg.peg.go | |
142 | ``` | |
143 | ||
144 | ||
145 | # Author | |
146 | ||
147 | Andrew Snodgrass |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "fmt" | |
8 | "os" | |
9 | "runtime" | |
10 | ) | |
11 | ||
12 | func main() { | |
13 | runtime.GOMAXPROCS(2) | |
14 | t := New(true, true) | |
15 | ||
16 | /*package main | |
17 | ||
18 | import "fmt" | |
19 | import "math" | |
20 | import "sort" | |
21 | import "strconv" | |
22 | ||
23 | type Peg Peg { | |
24 | *Tree | |
25 | }*/ | |
26 | t.AddPackage("main") | |
27 | t.AddPeg("Peg") | |
28 | t.AddState(` | |
29 | *Tree | |
30 | `) | |
31 | ||
32 | addDot := t.AddDot | |
33 | addName := t.AddName | |
34 | addCharacter := t.AddCharacter | |
35 | addDoubleCharacter := t.AddDoubleCharacter | |
36 | addHexaCharacter := t.AddHexaCharacter | |
37 | addAction := t.AddAction | |
38 | ||
39 | addRule := func(name string, item func()) { | |
40 | t.AddRule(name) | |
41 | item() | |
42 | t.AddExpression() | |
43 | } | |
44 | ||
45 | addSequence := func(items ...func()) { | |
46 | sequence := false | |
47 | for _, item := range items { | |
48 | item() | |
49 | if sequence { | |
50 | t.AddSequence() | |
51 | } else { | |
52 | sequence = true | |
53 | } | |
54 | } | |
55 | } | |
56 | ||
57 | addAlternate := func(items ...func()) { | |
58 | alternate := false | |
59 | for _, item := range items { | |
60 | item() | |
61 | if alternate { | |
62 | t.AddAlternate() | |
63 | } else { | |
64 | alternate = true | |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | addString := func(s string) { | |
70 | sequence := false | |
71 | for _, r := range s { | |
72 | t.AddCharacter(string(r)) | |
73 | if sequence { | |
74 | t.AddSequence() | |
75 | } else { | |
76 | sequence = true | |
77 | } | |
78 | } | |
79 | } | |
80 | ||
81 | addRange := func(begin, end string) { | |
82 | addCharacter(begin) | |
83 | addCharacter(end) | |
84 | t.AddRange() | |
85 | } | |
86 | ||
87 | addDoubleRange := func(begin, end string) { | |
88 | addCharacter(begin) | |
89 | addCharacter(end) | |
90 | t.AddDoubleRange() | |
91 | } | |
92 | ||
93 | addStar := func(item func()) { | |
94 | item() | |
95 | t.AddStar() | |
96 | } | |
97 | ||
98 | addPlus := func(item func()) { | |
99 | item() | |
100 | t.AddPlus() | |
101 | } | |
102 | ||
103 | addQuery := func(item func()) { | |
104 | item() | |
105 | t.AddQuery() | |
106 | } | |
107 | ||
108 | addPush := func(item func()) { | |
109 | item() | |
110 | t.AddPush() | |
111 | } | |
112 | ||
113 | addPeekNot := func(item func()) { | |
114 | item() | |
115 | t.AddPeekNot() | |
116 | } | |
117 | ||
118 | addPeekFor := func(item func()) { | |
119 | item() | |
120 | t.AddPeekFor() | |
121 | } | |
122 | ||
123 | /* Grammar <- Spacing 'package' MustSpacing Identifier { p.AddPackage(text) } | |
124 | Import* | |
125 | 'type' MustSpacing Identifier { p.AddPeg(text) } | |
126 | 'Peg' Spacing Action { p.AddState(text) } | |
127 | Definition+ EndOfFile */ | |
128 | addRule("Grammar", func() { | |
129 | addSequence( | |
130 | func() { addName("Spacing") }, | |
131 | func() { addString("package") }, | |
132 | func() { addName("MustSpacing") }, | |
133 | func() { addName("Identifier") }, | |
134 | func() { addAction(" p.AddPackage(text) ") }, | |
135 | func() { addStar(func() { addName("Import") }) }, | |
136 | func() { addString("type") }, | |
137 | func() { addName("MustSpacing") }, | |
138 | func() { addName("Identifier") }, | |
139 | func() { addAction(" p.AddPeg(text) ") }, | |
140 | func() { addString("Peg") }, | |
141 | func() { addName("Spacing") }, | |
142 | func() { addName("Action") }, | |
143 | func() { addAction(" p.AddState(text) ") }, | |
144 | func() { addPlus(func() { addName("Definition") }) }, | |
145 | func() { addName("EndOfFile") }, | |
146 | ) | |
147 | }) | |
148 | ||
149 | /* Import <- 'import' Spacing ["] < [a-zA-Z_/.\-]+ > ["] Spacing { p.AddImport(text) } */ | |
150 | addRule("Import", func() { | |
151 | addSequence( | |
152 | func() { addString("import") }, | |
153 | func() { addName("Spacing") }, | |
154 | func() { addCharacter(`"`) }, | |
155 | func() { | |
156 | addPush(func() { | |
157 | addPlus(func() { | |
158 | addAlternate( | |
159 | func() { addRange(`a`, `z`) }, | |
160 | func() { addRange(`A`, `Z`) }, | |
161 | func() { addCharacter(`_`) }, | |
162 | func() { addCharacter(`/`) }, | |
163 | func() { addCharacter(`.`) }, | |
164 | func() { addCharacter(`-`) }, | |
165 | ) | |
166 | }) | |
167 | }) | |
168 | }, | |
169 | func() { addCharacter(`"`) }, | |
170 | func() { addName("Spacing") }, | |
171 | func() { addAction(" p.AddImport(text) ") }, | |
172 | ) | |
173 | }) | |
174 | ||
175 | /* Definition <- Identifier { p.AddRule(text) } | |
176 | LeftArrow Expression { p.AddExpression() } &(Identifier LeftArrow / !.)*/ | |
177 | addRule("Definition", func() { | |
178 | addSequence( | |
179 | func() { addName("Identifier") }, | |
180 | func() { addAction(" p.AddRule(text) ") }, | |
181 | func() { addName("LeftArrow") }, | |
182 | func() { addName("Expression") }, | |
183 | func() { addAction(" p.AddExpression() ") }, | |
184 | func() { | |
185 | addPeekFor(func() { | |
186 | addAlternate( | |
187 | func() { | |
188 | addSequence( | |
189 | func() { addName("Identifier") }, | |
190 | func() { addName("LeftArrow") }, | |
191 | ) | |
192 | }, | |
193 | func() { addPeekNot(func() { addDot() }) }, | |
194 | ) | |
195 | }) | |
196 | }, | |
197 | ) | |
198 | }) | |
199 | ||
200 | /* Expression <- Sequence (Slash Sequence { p.AddAlternate() } | |
201 | )* (Slash { p.AddNil(); p.AddAlternate() } | |
202 | )? | |
203 | / { p.AddNil() } */ | |
204 | addRule("Expression", func() { | |
205 | addAlternate( | |
206 | func() { | |
207 | addSequence( | |
208 | func() { addName("Sequence") }, | |
209 | func() { | |
210 | addStar(func() { | |
211 | addSequence( | |
212 | func() { addName("Slash") }, | |
213 | func() { addName("Sequence") }, | |
214 | func() { addAction(" p.AddAlternate() ") }, | |
215 | ) | |
216 | }) | |
217 | }, | |
218 | func() { | |
219 | addQuery(func() { | |
220 | addSequence( | |
221 | func() { addName("Slash") }, | |
222 | func() { addAction(" p.AddNil(); p.AddAlternate() ") }, | |
223 | ) | |
224 | }) | |
225 | }, | |
226 | ) | |
227 | }, | |
228 | func() { addAction(" p.AddNil() ") }, | |
229 | ) | |
230 | }) | |
231 | ||
232 | /* Sequence <- Prefix (Prefix { p.AddSequence() } | |
233 | )* */ | |
234 | addRule("Sequence", func() { | |
235 | addSequence( | |
236 | func() { addName("Prefix") }, | |
237 | func() { | |
238 | addStar(func() { | |
239 | addSequence( | |
240 | func() { addName("Prefix") }, | |
241 | func() { addAction(" p.AddSequence() ") }, | |
242 | ) | |
243 | }) | |
244 | }, | |
245 | ) | |
246 | }) | |
247 | ||
248 | /* Prefix <- And Action { p.AddPredicate(text) } | |
249 | / Not Action { p.AddStateChange(text) } | |
250 | / And Suffix { p.AddPeekFor() } | |
251 | / Not Suffix { p.AddPeekNot() } | |
252 | / Suffix */ | |
253 | addRule("Prefix", func() { | |
254 | addAlternate( | |
255 | func() { | |
256 | addSequence( | |
257 | func() { addName("And") }, | |
258 | func() { addName("Action") }, | |
259 | func() { addAction(" p.AddPredicate(text) ") }, | |
260 | ) | |
261 | }, | |
262 | func() { | |
263 | addSequence( | |
264 | func() { addName("Not") }, | |
265 | func() { addName("Action") }, | |
266 | func() { addAction(" p.AddStateChange(text) ") }, | |
267 | ) | |
268 | }, | |
269 | func() { | |
270 | addSequence( | |
271 | func() { addName("And") }, | |
272 | func() { addName("Suffix") }, | |
273 | func() { addAction(" p.AddPeekFor() ") }, | |
274 | ) | |
275 | }, | |
276 | func() { | |
277 | addSequence( | |
278 | func() { addName("Not") }, | |
279 | func() { addName("Suffix") }, | |
280 | func() { addAction(" p.AddPeekNot() ") }, | |
281 | ) | |
282 | }, | |
283 | func() { addName("Suffix") }, | |
284 | ) | |
285 | }) | |
286 | ||
287 | /* Suffix <- Primary (Question { p.AddQuery() } | |
288 | / Star { p.AddStar() } | |
289 | / Plus { p.AddPlus() } | |
290 | )? */ | |
291 | addRule("Suffix", func() { | |
292 | addSequence( | |
293 | func() { addName("Primary") }, | |
294 | func() { | |
295 | addQuery(func() { | |
296 | addAlternate( | |
297 | func() { | |
298 | addSequence( | |
299 | func() { addName("Question") }, | |
300 | func() { addAction(" p.AddQuery() ") }, | |
301 | ) | |
302 | }, | |
303 | func() { | |
304 | addSequence( | |
305 | func() { addName("Star") }, | |
306 | func() { addAction(" p.AddStar() ") }, | |
307 | ) | |
308 | }, | |
309 | func() { | |
310 | addSequence( | |
311 | func() { addName("Plus") }, | |
312 | func() { addAction(" p.AddPlus() ") }, | |
313 | ) | |
314 | }, | |
315 | ) | |
316 | }) | |
317 | }, | |
318 | ) | |
319 | }) | |
320 | ||
321 | /* Primary <- Identifier !LeftArrow { p.AddName(text) } | |
322 | / Open Expression Close | |
323 | / Literal | |
324 | / Class | |
325 | / Dot { p.AddDot() } | |
326 | / Action { p.AddAction(text) } | |
327 | / Begin Expression End { p.AddPush() }*/ | |
328 | addRule("Primary", func() { | |
329 | addAlternate( | |
330 | func() { | |
331 | addSequence( | |
332 | func() { addName("Identifier") }, | |
333 | func() { addPeekNot(func() { t.AddName("LeftArrow") }) }, | |
334 | func() { addAction(" p.AddName(text) ") }, | |
335 | ) | |
336 | }, | |
337 | func() { | |
338 | addSequence( | |
339 | func() { addName("Open") }, | |
340 | func() { addName("Expression") }, | |
341 | func() { addName("Close") }, | |
342 | ) | |
343 | }, | |
344 | func() { addName("Literal") }, | |
345 | func() { addName("Class") }, | |
346 | func() { | |
347 | addSequence( | |
348 | func() { addName("Dot") }, | |
349 | func() { addAction(" p.AddDot() ") }, | |
350 | ) | |
351 | }, | |
352 | func() { | |
353 | addSequence( | |
354 | func() { addName("Action") }, | |
355 | func() { addAction(" p.AddAction(text) ") }, | |
356 | ) | |
357 | }, | |
358 | func() { | |
359 | addSequence( | |
360 | func() { addName("Begin") }, | |
361 | func() { addName("Expression") }, | |
362 | func() { addName("End") }, | |
363 | func() { addAction(" p.AddPush() ") }, | |
364 | ) | |
365 | }, | |
366 | ) | |
367 | }) | |
368 | ||
369 | /* Identifier <- < IdentStart IdentCont* > Spacing */ | |
370 | addRule("Identifier", func() { | |
371 | addSequence( | |
372 | func() { | |
373 | addPush(func() { | |
374 | addSequence( | |
375 | func() { addName("IdentStart") }, | |
376 | func() { addStar(func() { addName("IdentCont") }) }, | |
377 | ) | |
378 | }) | |
379 | }, | |
380 | func() { addName("Spacing") }, | |
381 | ) | |
382 | }) | |
383 | ||
384 | /* IdentStart <- [[a-z_]] */ | |
385 | addRule("IdentStart", func() { | |
386 | addAlternate( | |
387 | func() { addDoubleRange(`a`, `z`) }, | |
388 | func() { addCharacter(`_`) }, | |
389 | ) | |
390 | }) | |
391 | ||
392 | /* IdentCont <- IdentStart / [0-9] */ | |
393 | addRule("IdentCont", func() { | |
394 | addAlternate( | |
395 | func() { addName("IdentStart") }, | |
396 | func() { addRange(`0`, `9`) }, | |
397 | ) | |
398 | }) | |
399 | ||
400 | /* Literal <- ['] (!['] Char)? (!['] Char { p.AddSequence() } | |
401 | )* ['] Spacing | |
402 | / ["] (!["] DoubleChar)? (!["] DoubleChar { p.AddSequence() } | |
403 | )* ["] Spacing */ | |
404 | addRule("Literal", func() { | |
405 | addAlternate( | |
406 | func() { | |
407 | addSequence( | |
408 | func() { addCharacter(`'`) }, | |
409 | func() { | |
410 | addQuery(func() { | |
411 | addSequence( | |
412 | func() { addPeekNot(func() { addCharacter(`'`) }) }, | |
413 | func() { addName("Char") }, | |
414 | ) | |
415 | }) | |
416 | }, | |
417 | func() { | |
418 | addStar(func() { | |
419 | addSequence( | |
420 | func() { addPeekNot(func() { addCharacter(`'`) }) }, | |
421 | func() { addName("Char") }, | |
422 | func() { addAction(` p.AddSequence() `) }, | |
423 | ) | |
424 | }) | |
425 | }, | |
426 | func() { addCharacter(`'`) }, | |
427 | func() { addName("Spacing") }, | |
428 | ) | |
429 | }, | |
430 | func() { | |
431 | addSequence( | |
432 | func() { addCharacter(`"`) }, | |
433 | func() { | |
434 | addQuery(func() { | |
435 | addSequence( | |
436 | func() { addPeekNot(func() { addCharacter(`"`) }) }, | |
437 | func() { addName("DoubleChar") }, | |
438 | ) | |
439 | }) | |
440 | }, | |
441 | func() { | |
442 | addStar(func() { | |
443 | addSequence( | |
444 | func() { addPeekNot(func() { addCharacter(`"`) }) }, | |
445 | func() { addName("DoubleChar") }, | |
446 | func() { addAction(` p.AddSequence() `) }, | |
447 | ) | |
448 | }) | |
449 | }, | |
450 | func() { addCharacter(`"`) }, | |
451 | func() { addName("Spacing") }, | |
452 | ) | |
453 | }, | |
454 | ) | |
455 | }) | |
456 | ||
457 | /* Class <- ( '[[' ( '^' DoubleRanges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } | |
458 | / DoubleRanges )? | |
459 | ']]' | |
460 | / '[' ( '^' Ranges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } | |
461 | / Ranges )? | |
462 | ']' ) | |
463 | Spacing */ | |
464 | addRule("Class", func() { | |
465 | addSequence( | |
466 | func() { | |
467 | addAlternate( | |
468 | func() { | |
469 | addSequence( | |
470 | func() { addString(`[[`) }, | |
471 | func() { | |
472 | addQuery(func() { | |
473 | addAlternate( | |
474 | func() { | |
475 | addSequence( | |
476 | func() { addCharacter(`^`) }, | |
477 | func() { addName("DoubleRanges") }, | |
478 | func() { addAction(` p.AddPeekNot(); p.AddDot(); p.AddSequence() `) }, | |
479 | ) | |
480 | }, | |
481 | func() { addName("DoubleRanges") }, | |
482 | ) | |
483 | }) | |
484 | }, | |
485 | func() { addString(`]]`) }, | |
486 | ) | |
487 | }, | |
488 | func() { | |
489 | addSequence( | |
490 | func() { addCharacter(`[`) }, | |
491 | func() { | |
492 | addQuery(func() { | |
493 | addAlternate( | |
494 | func() { | |
495 | addSequence( | |
496 | func() { addCharacter(`^`) }, | |
497 | func() { addName("Ranges") }, | |
498 | func() { addAction(` p.AddPeekNot(); p.AddDot(); p.AddSequence() `) }, | |
499 | ) | |
500 | }, | |
501 | func() { addName("Ranges") }, | |
502 | ) | |
503 | }) | |
504 | }, | |
505 | func() { addCharacter(`]`) }, | |
506 | ) | |
507 | }, | |
508 | ) | |
509 | }, | |
510 | func() { addName("Spacing") }, | |
511 | ) | |
512 | }) | |
513 | ||
514 | /* Ranges <- !']' Range (!']' Range { p.AddAlternate() } | |
515 | )* */ | |
516 | addRule("Ranges", func() { | |
517 | addSequence( | |
518 | func() { addPeekNot(func() { addCharacter(`]`) }) }, | |
519 | func() { addName("Range") }, | |
520 | func() { | |
521 | addStar(func() { | |
522 | addSequence( | |
523 | func() { addPeekNot(func() { addCharacter(`]`) }) }, | |
524 | func() { addName("Range") }, | |
525 | func() { addAction(" p.AddAlternate() ") }, | |
526 | ) | |
527 | }) | |
528 | }, | |
529 | ) | |
530 | }) | |
531 | ||
532 | /* DoubleRanges <- !']]' DoubleRange (!']]' DoubleRange { p.AddAlternate() } | |
533 | )* */ | |
534 | addRule("DoubleRanges", func() { | |
535 | addSequence( | |
536 | func() { addPeekNot(func() { addString(`]]`) }) }, | |
537 | func() { addName("DoubleRange") }, | |
538 | func() { | |
539 | addStar(func() { | |
540 | addSequence( | |
541 | func() { addPeekNot(func() { addString(`]]`) }) }, | |
542 | func() { addName("DoubleRange") }, | |
543 | func() { addAction(" p.AddAlternate() ") }, | |
544 | ) | |
545 | }) | |
546 | }, | |
547 | ) | |
548 | }) | |
549 | ||
550 | /* Range <- Char '-' Char { p.AddRange() } | |
551 | / Char */ | |
552 | addRule("Range", func() { | |
553 | addAlternate( | |
554 | func() { | |
555 | addSequence( | |
556 | func() { addName("Char") }, | |
557 | func() { addCharacter(`-`) }, | |
558 | func() { addName("Char") }, | |
559 | func() { addAction(" p.AddRange() ") }, | |
560 | ) | |
561 | }, | |
562 | func() { addName("Char") }, | |
563 | ) | |
564 | }) | |
565 | ||
566 | /* DoubleRange <- Char '-' Char { p.AddDoubleRange() } | |
567 | / DoubleChar */ | |
568 | addRule("DoubleRange", func() { | |
569 | addAlternate( | |
570 | func() { | |
571 | addSequence( | |
572 | func() { addName("Char") }, | |
573 | func() { addCharacter(`-`) }, | |
574 | func() { addName("Char") }, | |
575 | func() { addAction(" p.AddDoubleRange() ") }, | |
576 | ) | |
577 | }, | |
578 | func() { addName("DoubleChar") }, | |
579 | ) | |
580 | }) | |
581 | ||
582 | /* Char <- Escape | |
583 | / !'\\' <.> { p.AddCharacter(text) } */ | |
584 | addRule("Char", func() { | |
585 | addAlternate( | |
586 | func() { addName("Escape") }, | |
587 | func() { | |
588 | addSequence( | |
589 | func() { addPeekNot(func() { addCharacter("\\") }) }, | |
590 | func() { addPush(func() { addDot() }) }, | |
591 | func() { addAction(` p.AddCharacter(text) `) }, | |
592 | ) | |
593 | }, | |
594 | ) | |
595 | }) | |
596 | ||
597 | /* DoubleChar <- Escape | |
598 | / <[a-zA-Z]> { p.AddDoubleCharacter(text) } | |
599 | / !'\\' <.> { p.AddCharacter(text) } */ | |
600 | addRule("DoubleChar", func() { | |
601 | addAlternate( | |
602 | func() { addName("Escape") }, | |
603 | func() { | |
604 | addSequence( | |
605 | func() { | |
606 | addPush(func() { | |
607 | addAlternate( | |
608 | func() { addRange(`a`, `z`) }, | |
609 | func() { addRange(`A`, `Z`) }, | |
610 | ) | |
611 | }) | |
612 | }, | |
613 | func() { addAction(` p.AddDoubleCharacter(text) `) }, | |
614 | ) | |
615 | }, | |
616 | func() { | |
617 | addSequence( | |
618 | func() { addPeekNot(func() { addCharacter("\\") }) }, | |
619 | func() { addPush(func() { addDot() }) }, | |
620 | func() { addAction(` p.AddCharacter(text) `) }, | |
621 | ) | |
622 | }, | |
623 | ) | |
624 | }) | |
625 | ||
626 | /* Escape <- "\\a" { p.AddCharacter("\a") } # bell | |
627 | / "\\b" { p.AddCharacter("\b") } # bs | |
628 | / "\\e" { p.AddCharacter("\x1B") } # esc | |
629 | / "\\f" { p.AddCharacter("\f") } # ff | |
630 | / "\\n" { p.AddCharacter("\n") } # nl | |
631 | / "\\r" { p.AddCharacter("\r") } # cr | |
632 | / "\\t" { p.AddCharacter("\t") } # ht | |
633 | / "\\v" { p.AddCharacter("\v") } # vt | |
634 | / "\\'" { p.AddCharacter("'") } | |
635 | / '\\"' { p.AddCharacter("\"") } | |
636 | / '\\[' { p.AddCharacter("[") } | |
637 | / '\\]' { p.AddCharacter("]") } | |
638 | / '\\-' { p.AddCharacter("-") } | |
639 | / '\\' "0x"<[0-9a-fA-F]+> { p.AddHexaCharacter(text) } | |
640 | / '\\' <[0-3][0-7][0-7]> { p.AddOctalCharacter(text) } | |
641 | / '\\' <[0-7][0-7]?> { p.AddOctalCharacter(text) } | |
642 | / '\\\\' { p.AddCharacter("\\") } */ | |
643 | addRule("Escape", func() { | |
644 | addAlternate( | |
645 | func() { | |
646 | addSequence( | |
647 | func() { addCharacter("\\") }, | |
648 | func() { addDoubleCharacter(`a`) }, | |
649 | func() { addAction(` p.AddCharacter("\a") `) }, | |
650 | ) | |
651 | }, | |
652 | func() { | |
653 | addSequence( | |
654 | func() { addCharacter("\\") }, | |
655 | func() { addDoubleCharacter(`b`) }, | |
656 | func() { addAction(` p.AddCharacter("\b") `) }, | |
657 | ) | |
658 | }, | |
659 | func() { | |
660 | addSequence( | |
661 | func() { addCharacter("\\") }, | |
662 | func() { addDoubleCharacter(`e`) }, | |
663 | func() { addAction(` p.AddCharacter("\x1B") `) }, | |
664 | ) | |
665 | }, | |
666 | func() { | |
667 | addSequence( | |
668 | func() { addCharacter("\\") }, | |
669 | func() { addDoubleCharacter(`f`) }, | |
670 | func() { addAction(` p.AddCharacter("\f") `) }, | |
671 | ) | |
672 | }, | |
673 | func() { | |
674 | addSequence( | |
675 | func() { addCharacter("\\") }, | |
676 | func() { addDoubleCharacter(`n`) }, | |
677 | func() { addAction(` p.AddCharacter("\n") `) }, | |
678 | ) | |
679 | }, | |
680 | func() { | |
681 | addSequence( | |
682 | func() { addCharacter("\\") }, | |
683 | func() { addDoubleCharacter(`r`) }, | |
684 | func() { addAction(` p.AddCharacter("\r") `) }, | |
685 | ) | |
686 | }, | |
687 | func() { | |
688 | addSequence( | |
689 | func() { addCharacter("\\") }, | |
690 | func() { addDoubleCharacter(`t`) }, | |
691 | func() { addAction(` p.AddCharacter("\t") `) }, | |
692 | ) | |
693 | }, | |
694 | func() { | |
695 | addSequence( | |
696 | func() { addCharacter("\\") }, | |
697 | func() { addDoubleCharacter(`v`) }, | |
698 | func() { addAction(` p.AddCharacter("\v") `) }, | |
699 | ) | |
700 | }, | |
701 | func() { | |
702 | addSequence( | |
703 | func() { addCharacter("\\") }, | |
704 | func() { addCharacter(`'`) }, | |
705 | func() { addAction(` p.AddCharacter("'") `) }, | |
706 | ) | |
707 | }, | |
708 | func() { | |
709 | addSequence( | |
710 | func() { addCharacter("\\") }, | |
711 | func() { addCharacter(`"`) }, | |
712 | func() { addAction(` p.AddCharacter("\"") `) }, | |
713 | ) | |
714 | }, | |
715 | func() { | |
716 | addSequence( | |
717 | func() { addCharacter("\\") }, | |
718 | func() { addCharacter(`[`) }, | |
719 | func() { addAction(` p.AddCharacter("[") `) }, | |
720 | ) | |
721 | }, | |
722 | func() { | |
723 | addSequence( | |
724 | func() { addCharacter("\\") }, | |
725 | func() { addCharacter(`]`) }, | |
726 | func() { addAction(` p.AddCharacter("]") `) }, | |
727 | ) | |
728 | }, | |
729 | func() { | |
730 | addSequence( | |
731 | func() { addCharacter("\\") }, | |
732 | func() { addCharacter(`-`) }, | |
733 | func() { addAction(` p.AddCharacter("-") `) }, | |
734 | ) | |
735 | }, | |
736 | func() { | |
737 | addSequence( | |
738 | func() { addCharacter("\\") }, | |
739 | func() { | |
740 | addSequence( | |
741 | func() { addCharacter(`0`) }, | |
742 | func() { addDoubleCharacter(`x`) }, | |
743 | ) | |
744 | }, | |
745 | func() { | |
746 | addPush(func() { | |
747 | addPlus(func() { | |
748 | addAlternate( | |
749 | func() { addRange(`0`, `9`) }, | |
750 | func() { addRange(`a`, `f`) }, | |
751 | func() { addRange(`A`, `F`) }, | |
752 | ) | |
753 | }) | |
754 | }) | |
755 | }, | |
756 | func() { addAction(` p.AddHexaCharacter(text) `) }, | |
757 | ) | |
758 | }, | |
759 | func() { | |
760 | addSequence( | |
761 | func() { addCharacter("\\") }, | |
762 | func() { | |
763 | addPush(func() { | |
764 | addSequence( | |
765 | func() { addRange(`0`, `3`) }, | |
766 | func() { addRange(`0`, `7`) }, | |
767 | func() { addRange(`0`, `7`) }, | |
768 | ) | |
769 | }) | |
770 | }, | |
771 | func() { addAction(` p.AddOctalCharacter(text) `) }, | |
772 | ) | |
773 | }, | |
774 | func() { | |
775 | addSequence( | |
776 | func() { addCharacter("\\") }, | |
777 | func() { | |
778 | addPush(func() { | |
779 | addSequence( | |
780 | func() { addRange(`0`, `7`) }, | |
781 | func() { addQuery(func() { addRange(`0`, `7`) }) }, | |
782 | ) | |
783 | }) | |
784 | }, | |
785 | func() { addAction(` p.AddOctalCharacter(text) `) }, | |
786 | ) | |
787 | }, | |
788 | func() { | |
789 | addSequence( | |
790 | func() { addCharacter("\\") }, | |
791 | func() { addCharacter("\\") }, | |
792 | func() { addAction(` p.AddCharacter("\\") `) }, | |
793 | ) | |
794 | }, | |
795 | ) | |
796 | }) | |
797 | ||
798 | /* LeftArrow <- ('<-' / '\0x2190') Spacing */ | |
799 | addRule("LeftArrow", func() { | |
800 | addSequence( | |
801 | func() { | |
802 | addAlternate( | |
803 | func() { addString(`<-`) }, | |
804 | func() { addHexaCharacter("2190") }, | |
805 | ) | |
806 | }, | |
807 | func() { addName("Spacing") }, | |
808 | ) | |
809 | }) | |
810 | ||
811 | /* Slash <- '/' Spacing */ | |
812 | addRule("Slash", func() { | |
813 | addSequence( | |
814 | func() { addCharacter(`/`) }, | |
815 | func() { addName("Spacing") }, | |
816 | ) | |
817 | }) | |
818 | ||
819 | /* And <- '&' Spacing */ | |
820 | addRule("And", func() { | |
821 | addSequence( | |
822 | func() { addCharacter(`&`) }, | |
823 | func() { addName("Spacing") }, | |
824 | ) | |
825 | }) | |
826 | ||
827 | /* Not <- '!' Spacing */ | |
828 | addRule("Not", func() { | |
829 | addSequence( | |
830 | func() { addCharacter(`!`) }, | |
831 | func() { addName("Spacing") }, | |
832 | ) | |
833 | }) | |
834 | ||
835 | /* Question <- '?' Spacing */ | |
836 | addRule("Question", func() { | |
837 | addSequence( | |
838 | func() { addCharacter(`?`) }, | |
839 | func() { addName("Spacing") }, | |
840 | ) | |
841 | }) | |
842 | ||
843 | /* Star <- '*' Spacing */ | |
844 | addRule("Star", func() { | |
845 | addSequence( | |
846 | func() { addCharacter(`*`) }, | |
847 | func() { addName("Spacing") }, | |
848 | ) | |
849 | }) | |
850 | ||
851 | /* Plus <- '+' Spacing */ | |
852 | addRule("Plus", func() { | |
853 | addSequence( | |
854 | func() { addCharacter(`+`) }, | |
855 | func() { addName("Spacing") }, | |
856 | ) | |
857 | }) | |
858 | ||
859 | /* Open <- '(' Spacing */ | |
860 | addRule("Open", func() { | |
861 | addSequence( | |
862 | func() { addCharacter(`(`) }, | |
863 | func() { addName("Spacing") }, | |
864 | ) | |
865 | }) | |
866 | ||
867 | /* Close <- ')' Spacing */ | |
868 | addRule("Close", func() { | |
869 | addSequence( | |
870 | func() { addCharacter(`)`) }, | |
871 | func() { addName("Spacing") }, | |
872 | ) | |
873 | }) | |
874 | ||
875 | /* Dot <- '.' Spacing */ | |
876 | addRule("Dot", func() { | |
877 | addSequence( | |
878 | func() { addCharacter(`.`) }, | |
879 | func() { addName("Spacing") }, | |
880 | ) | |
881 | }) | |
882 | ||
883 | /* SpaceComment <- (Space / Comment) */ | |
884 | addRule("SpaceComment", func() { | |
885 | addAlternate( | |
886 | func() { addName("Space") }, | |
887 | func() { addName("Comment") }, | |
888 | ) | |
889 | }) | |
890 | ||
891 | /* Spacing <- SpaceComment* */ | |
892 | addRule("Spacing", func() { | |
893 | addStar(func() { addName("SpaceComment") }) | |
894 | }) | |
895 | ||
896 | /* MustSpacing <- SpaceComment+ */ | |
897 | addRule("MustSpacing", func() { | |
898 | addPlus(func() { t.AddName("SpaceComment") }) | |
899 | }) | |
900 | ||
901 | /* Comment <- '#' (!EndOfLine .)* EndOfLine */ | |
902 | addRule("Comment", func() { | |
903 | addSequence( | |
904 | func() { addCharacter(`#`) }, | |
905 | func() { | |
906 | addStar(func() { | |
907 | addSequence( | |
908 | func() { addPeekNot(func() { addName("EndOfLine") }) }, | |
909 | func() { addDot() }, | |
910 | ) | |
911 | }) | |
912 | }, | |
913 | func() { addName("EndOfLine") }, | |
914 | ) | |
915 | }) | |
916 | ||
917 | /* Space <- ' ' / '\t' / EndOfLine */ | |
918 | addRule("Space", func() { | |
919 | addAlternate( | |
920 | func() { addCharacter(` `) }, | |
921 | func() { addCharacter("\t") }, | |
922 | func() { addName("EndOfLine") }, | |
923 | ) | |
924 | }) | |
925 | ||
926 | /* EndOfLine <- '\r\n' / '\n' / '\r' */ | |
927 | addRule("EndOfLine", func() { | |
928 | addAlternate( | |
929 | func() { addString("\r\n") }, | |
930 | func() { addCharacter("\n") }, | |
931 | func() { addCharacter("\r") }, | |
932 | ) | |
933 | }) | |
934 | ||
935 | /* EndOfFile <- !. */ | |
936 | addRule("EndOfFile", func() { | |
937 | addPeekNot(func() { addDot() }) | |
938 | }) | |
939 | ||
940 | /* Action <- '{' < ActionBody* > '}' Spacing */ | |
941 | addRule("Action", func() { | |
942 | addSequence( | |
943 | func() { addCharacter(`{`) }, | |
944 | func() { | |
945 | addPush(func() { | |
946 | addStar(func() { addName("ActionBody") }) | |
947 | }) | |
948 | }, | |
949 | func() { addCharacter(`}`) }, | |
950 | func() { addName("Spacing") }, | |
951 | ) | |
952 | }) | |
953 | ||
954 | /* ActionBody <- [^{}] / '{' ActionBody* '}' */ | |
955 | addRule("ActionBody", func() { | |
956 | addAlternate( | |
957 | func() { | |
958 | addSequence( | |
959 | func() { | |
960 | addPeekNot(func() { | |
961 | addAlternate( | |
962 | func() { addCharacter(`{`) }, | |
963 | func() { addCharacter(`}`) }, | |
964 | ) | |
965 | }) | |
966 | }, | |
967 | func() { addDot() }, | |
968 | ) | |
969 | }, | |
970 | func() { | |
971 | addSequence( | |
972 | func() { addCharacter(`{`) }, | |
973 | func() { addStar(func() { addName("ActionBody") }) }, | |
974 | func() { addCharacter(`}`) }, | |
975 | ) | |
976 | }, | |
977 | ) | |
978 | }) | |
979 | ||
980 | /* Begin <- '<' Spacing */ | |
981 | addRule("Begin", func() { | |
982 | addSequence( | |
983 | func() { addCharacter(`<`) }, | |
984 | func() { addName("Spacing") }, | |
985 | ) | |
986 | }) | |
987 | ||
988 | /* End <- '>' Spacing */ | |
989 | addRule("End", func() { | |
990 | addSequence( | |
991 | func() { addCharacter(`>`) }, | |
992 | func() { addName("Spacing") }, | |
993 | ) | |
994 | }) | |
995 | ||
996 | filename := "bootstrap.peg.go" | |
997 | out, error := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | |
998 | if error != nil { | |
999 | fmt.Printf("%v: %v\n", filename, error) | |
1000 | return | |
1001 | } | |
1002 | defer out.Close() | |
1003 | t.Compile(filename, out) | |
1004 | } |
0 | ../peg.go⏎ |
0 | package main | |
1 | ||
2 | import ( | |
3 | "fmt" | |
4 | "math" | |
5 | "sort" | |
6 | "strconv" | |
7 | ) | |
8 | ||
9 | const endSymbol rune = 1114112 | |
10 | ||
11 | /* The rule types inferred from the grammar are below. */ | |
12 | type pegRule uint8 | |
13 | ||
14 | const ( | |
15 | ruleUnknown pegRule = iota | |
16 | ruleGrammar | |
17 | ruleImport | |
18 | ruleDefinition | |
19 | ruleExpression | |
20 | ruleSequence | |
21 | rulePrefix | |
22 | ruleSuffix | |
23 | rulePrimary | |
24 | ruleIdentifier | |
25 | ruleIdentStart | |
26 | ruleIdentCont | |
27 | ruleLiteral | |
28 | ruleClass | |
29 | ruleRanges | |
30 | ruleDoubleRanges | |
31 | ruleRange | |
32 | ruleDoubleRange | |
33 | ruleChar | |
34 | ruleDoubleChar | |
35 | ruleEscape | |
36 | ruleLeftArrow | |
37 | ruleSlash | |
38 | ruleAnd | |
39 | ruleNot | |
40 | ruleQuestion | |
41 | ruleStar | |
42 | rulePlus | |
43 | ruleOpen | |
44 | ruleClose | |
45 | ruleDot | |
46 | ruleSpaceComment | |
47 | ruleSpacing | |
48 | ruleMustSpacing | |
49 | ruleComment | |
50 | ruleSpace | |
51 | ruleEndOfLine | |
52 | ruleEndOfFile | |
53 | ruleAction | |
54 | ruleActionBody | |
55 | ruleBegin | |
56 | ruleEnd | |
57 | ruleAction0 | |
58 | ruleAction1 | |
59 | ruleAction2 | |
60 | rulePegText | |
61 | ruleAction3 | |
62 | ruleAction4 | |
63 | ruleAction5 | |
64 | ruleAction6 | |
65 | ruleAction7 | |
66 | ruleAction8 | |
67 | ruleAction9 | |
68 | ruleAction10 | |
69 | ruleAction11 | |
70 | ruleAction12 | |
71 | ruleAction13 | |
72 | ruleAction14 | |
73 | ruleAction15 | |
74 | ruleAction16 | |
75 | ruleAction17 | |
76 | ruleAction18 | |
77 | ruleAction19 | |
78 | ruleAction20 | |
79 | ruleAction21 | |
80 | ruleAction22 | |
81 | ruleAction23 | |
82 | ruleAction24 | |
83 | ruleAction25 | |
84 | ruleAction26 | |
85 | ruleAction27 | |
86 | ruleAction28 | |
87 | ruleAction29 | |
88 | ruleAction30 | |
89 | ruleAction31 | |
90 | ruleAction32 | |
91 | ruleAction33 | |
92 | ruleAction34 | |
93 | ruleAction35 | |
94 | ruleAction36 | |
95 | ruleAction37 | |
96 | ruleAction38 | |
97 | ruleAction39 | |
98 | ruleAction40 | |
99 | ruleAction41 | |
100 | ruleAction42 | |
101 | ruleAction43 | |
102 | ruleAction44 | |
103 | ruleAction45 | |
104 | ruleAction46 | |
105 | ruleAction47 | |
106 | ruleAction48 | |
107 | ||
108 | rulePre | |
109 | ruleIn | |
110 | ruleSuf | |
111 | ) | |
112 | ||
113 | var rul3s = [...]string{ | |
114 | "Unknown", | |
115 | "Grammar", | |
116 | "Import", | |
117 | "Definition", | |
118 | "Expression", | |
119 | "Sequence", | |
120 | "Prefix", | |
121 | "Suffix", | |
122 | "Primary", | |
123 | "Identifier", | |
124 | "IdentStart", | |
125 | "IdentCont", | |
126 | "Literal", | |
127 | "Class", | |
128 | "Ranges", | |
129 | "DoubleRanges", | |
130 | "Range", | |
131 | "DoubleRange", | |
132 | "Char", | |
133 | "DoubleChar", | |
134 | "Escape", | |
135 | "LeftArrow", | |
136 | "Slash", | |
137 | "And", | |
138 | "Not", | |
139 | "Question", | |
140 | "Star", | |
141 | "Plus", | |
142 | "Open", | |
143 | "Close", | |
144 | "Dot", | |
145 | "SpaceComment", | |
146 | "Spacing", | |
147 | "MustSpacing", | |
148 | "Comment", | |
149 | "Space", | |
150 | "EndOfLine", | |
151 | "EndOfFile", | |
152 | "Action", | |
153 | "ActionBody", | |
154 | "Begin", | |
155 | "End", | |
156 | "Action0", | |
157 | "Action1", | |
158 | "Action2", | |
159 | "PegText", | |
160 | "Action3", | |
161 | "Action4", | |
162 | "Action5", | |
163 | "Action6", | |
164 | "Action7", | |
165 | "Action8", | |
166 | "Action9", | |
167 | "Action10", | |
168 | "Action11", | |
169 | "Action12", | |
170 | "Action13", | |
171 | "Action14", | |
172 | "Action15", | |
173 | "Action16", | |
174 | "Action17", | |
175 | "Action18", | |
176 | "Action19", | |
177 | "Action20", | |
178 | "Action21", | |
179 | "Action22", | |
180 | "Action23", | |
181 | "Action24", | |
182 | "Action25", | |
183 | "Action26", | |
184 | "Action27", | |
185 | "Action28", | |
186 | "Action29", | |
187 | "Action30", | |
188 | "Action31", | |
189 | "Action32", | |
190 | "Action33", | |
191 | "Action34", | |
192 | "Action35", | |
193 | "Action36", | |
194 | "Action37", | |
195 | "Action38", | |
196 | "Action39", | |
197 | "Action40", | |
198 | "Action41", | |
199 | "Action42", | |
200 | "Action43", | |
201 | "Action44", | |
202 | "Action45", | |
203 | "Action46", | |
204 | "Action47", | |
205 | "Action48", | |
206 | ||
207 | "Pre_", | |
208 | "_In_", | |
209 | "_Suf", | |
210 | } | |
211 | ||
212 | type node32 struct { | |
213 | token32 | |
214 | up, next *node32 | |
215 | } | |
216 | ||
217 | func (node *node32) print(depth int, buffer string) { | |
218 | for node != nil { | |
219 | for c := 0; c < depth; c++ { | |
220 | fmt.Printf(" ") | |
221 | } | |
222 | fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[node.pegRule], strconv.Quote(string(([]rune(buffer)[node.begin:node.end])))) | |
223 | if node.up != nil { | |
224 | node.up.print(depth+1, buffer) | |
225 | } | |
226 | node = node.next | |
227 | } | |
228 | } | |
229 | ||
230 | func (node *node32) Print(buffer string) { | |
231 | node.print(0, buffer) | |
232 | } | |
233 | ||
234 | type element struct { | |
235 | node *node32 | |
236 | down *element | |
237 | } | |
238 | ||
239 | /* ${@} bit structure for abstract syntax tree */ | |
240 | type token32 struct { | |
241 | pegRule | |
242 | begin, end, next uint32 | |
243 | } | |
244 | ||
245 | func (t *token32) isZero() bool { | |
246 | return t.pegRule == ruleUnknown && t.begin == 0 && t.end == 0 && t.next == 0 | |
247 | } | |
248 | ||
249 | func (t *token32) isParentOf(u token32) bool { | |
250 | return t.begin <= u.begin && t.end >= u.end && t.next > u.next | |
251 | } | |
252 | ||
253 | func (t *token32) getToken32() token32 { | |
254 | return token32{pegRule: t.pegRule, begin: uint32(t.begin), end: uint32(t.end), next: uint32(t.next)} | |
255 | } | |
256 | ||
257 | func (t *token32) String() string { | |
258 | return fmt.Sprintf("\x1B[34m%v\x1B[m %v %v %v", rul3s[t.pegRule], t.begin, t.end, t.next) | |
259 | } | |
260 | ||
261 | type tokens32 struct { | |
262 | tree []token32 | |
263 | ordered [][]token32 | |
264 | } | |
265 | ||
266 | func (t *tokens32) trim(length int) { | |
267 | t.tree = t.tree[0:length] | |
268 | } | |
269 | ||
270 | func (t *tokens32) Print() { | |
271 | for _, token := range t.tree { | |
272 | fmt.Println(token.String()) | |
273 | } | |
274 | } | |
275 | ||
276 | func (t *tokens32) Order() [][]token32 { | |
277 | if t.ordered != nil { | |
278 | return t.ordered | |
279 | } | |
280 | ||
281 | depths := make([]int32, 1, math.MaxInt16) | |
282 | for i, token := range t.tree { | |
283 | if token.pegRule == ruleUnknown { | |
284 | t.tree = t.tree[:i] | |
285 | break | |
286 | } | |
287 | depth := int(token.next) | |
288 | if length := len(depths); depth >= length { | |
289 | depths = depths[:depth+1] | |
290 | } | |
291 | depths[depth]++ | |
292 | } | |
293 | depths = append(depths, 0) | |
294 | ||
295 | ordered, pool := make([][]token32, len(depths)), make([]token32, len(t.tree)+len(depths)) | |
296 | for i, depth := range depths { | |
297 | depth++ | |
298 | ordered[i], pool, depths[i] = pool[:depth], pool[depth:], 0 | |
299 | } | |
300 | ||
301 | for i, token := range t.tree { | |
302 | depth := token.next | |
303 | token.next = uint32(i) | |
304 | ordered[depth][depths[depth]] = token | |
305 | depths[depth]++ | |
306 | } | |
307 | t.ordered = ordered | |
308 | return ordered | |
309 | } | |
310 | ||
311 | type state32 struct { | |
312 | token32 | |
313 | depths []int32 | |
314 | leaf bool | |
315 | } | |
316 | ||
317 | func (t *tokens32) AST() *node32 { | |
318 | tokens := t.Tokens() | |
319 | stack := &element{node: &node32{token32: <-tokens}} | |
320 | for token := range tokens { | |
321 | if token.begin == token.end { | |
322 | continue | |
323 | } | |
324 | node := &node32{token32: token} | |
325 | for stack != nil && stack.node.begin >= token.begin && stack.node.end <= token.end { | |
326 | stack.node.next = node.up | |
327 | node.up = stack.node | |
328 | stack = stack.down | |
329 | } | |
330 | stack = &element{node: node, down: stack} | |
331 | } | |
332 | return stack.node | |
333 | } | |
334 | ||
335 | func (t *tokens32) PreOrder() (<-chan state32, [][]token32) { | |
336 | s, ordered := make(chan state32, 6), t.Order() | |
337 | go func() { | |
338 | var states [8]state32 | |
339 | for i := range states { | |
340 | states[i].depths = make([]int32, len(ordered)) | |
341 | } | |
342 | depths, state, depth := make([]int32, len(ordered)), 0, 1 | |
343 | write := func(t token32, leaf bool) { | |
344 | S := states[state] | |
345 | state, S.pegRule, S.begin, S.end, S.next, S.leaf = (state+1)%8, t.pegRule, t.begin, t.end, uint32(depth), leaf | |
346 | copy(S.depths, depths) | |
347 | s <- S | |
348 | } | |
349 | ||
350 | states[state].token32 = ordered[0][0] | |
351 | depths[0]++ | |
352 | state++ | |
353 | a, b := ordered[depth-1][depths[depth-1]-1], ordered[depth][depths[depth]] | |
354 | depthFirstSearch: | |
355 | for { | |
356 | for { | |
357 | if i := depths[depth]; i > 0 { | |
358 | if c, j := ordered[depth][i-1], depths[depth-1]; a.isParentOf(c) && | |
359 | (j < 2 || !ordered[depth-1][j-2].isParentOf(c)) { | |
360 | if c.end != b.begin { | |
361 | write(token32{pegRule: ruleIn, begin: c.end, end: b.begin}, true) | |
362 | } | |
363 | break | |
364 | } | |
365 | } | |
366 | ||
367 | if a.begin < b.begin { | |
368 | write(token32{pegRule: rulePre, begin: a.begin, end: b.begin}, true) | |
369 | } | |
370 | break | |
371 | } | |
372 | ||
373 | next := depth + 1 | |
374 | if c := ordered[next][depths[next]]; c.pegRule != ruleUnknown && b.isParentOf(c) { | |
375 | write(b, false) | |
376 | depths[depth]++ | |
377 | depth, a, b = next, b, c | |
378 | continue | |
379 | } | |
380 | ||
381 | write(b, true) | |
382 | depths[depth]++ | |
383 | c, parent := ordered[depth][depths[depth]], true | |
384 | for { | |
385 | if c.pegRule != ruleUnknown && a.isParentOf(c) { | |
386 | b = c | |
387 | continue depthFirstSearch | |
388 | } else if parent && b.end != a.end { | |
389 | write(token32{pegRule: ruleSuf, begin: b.end, end: a.end}, true) | |
390 | } | |
391 | ||
392 | depth-- | |
393 | if depth > 0 { | |
394 | a, b, c = ordered[depth-1][depths[depth-1]-1], a, ordered[depth][depths[depth]] | |
395 | parent = a.isParentOf(b) | |
396 | continue | |
397 | } | |
398 | ||
399 | break depthFirstSearch | |
400 | } | |
401 | } | |
402 | ||
403 | close(s) | |
404 | }() | |
405 | return s, ordered | |
406 | } | |
407 | ||
408 | func (t *tokens32) PrintSyntax() { | |
409 | tokens, ordered := t.PreOrder() | |
410 | max := -1 | |
411 | for token := range tokens { | |
412 | if !token.leaf { | |
413 | fmt.Printf("%v", token.begin) | |
414 | for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { | |
415 | fmt.Printf(" \x1B[36m%v\x1B[m", rul3s[ordered[i][depths[i]-1].pegRule]) | |
416 | } | |
417 | fmt.Printf(" \x1B[36m%v\x1B[m\n", rul3s[token.pegRule]) | |
418 | } else if token.begin == token.end { | |
419 | fmt.Printf("%v", token.begin) | |
420 | for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { | |
421 | fmt.Printf(" \x1B[31m%v\x1B[m", rul3s[ordered[i][depths[i]-1].pegRule]) | |
422 | } | |
423 | fmt.Printf(" \x1B[31m%v\x1B[m\n", rul3s[token.pegRule]) | |
424 | } else { | |
425 | for c, end := token.begin, token.end; c < end; c++ { | |
426 | if i := int(c); max+1 < i { | |
427 | for j := max; j < i; j++ { | |
428 | fmt.Printf("skip %v %v\n", j, token.String()) | |
429 | } | |
430 | max = i | |
431 | } else if i := int(c); i <= max { | |
432 | for j := i; j <= max; j++ { | |
433 | fmt.Printf("dupe %v %v\n", j, token.String()) | |
434 | } | |
435 | } else { | |
436 | max = int(c) | |
437 | } | |
438 | fmt.Printf("%v", c) | |
439 | for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { | |
440 | fmt.Printf(" \x1B[34m%v\x1B[m", rul3s[ordered[i][depths[i]-1].pegRule]) | |
441 | } | |
442 | fmt.Printf(" \x1B[34m%v\x1B[m\n", rul3s[token.pegRule]) | |
443 | } | |
444 | fmt.Printf("\n") | |
445 | } | |
446 | } | |
447 | } | |
448 | ||
449 | func (t *tokens32) PrintSyntaxTree(buffer string) { | |
450 | tokens, _ := t.PreOrder() | |
451 | for token := range tokens { | |
452 | for c := 0; c < int(token.next); c++ { | |
453 | fmt.Printf(" ") | |
454 | } | |
455 | fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[token.pegRule], strconv.Quote(string(([]rune(buffer)[token.begin:token.end])))) | |
456 | } | |
457 | } | |
458 | ||
459 | func (t *tokens32) Add(rule pegRule, begin, end, depth uint32, index int) { | |
460 | t.tree[index] = token32{pegRule: rule, begin: uint32(begin), end: uint32(end), next: uint32(depth)} | |
461 | } | |
462 | ||
463 | func (t *tokens32) Tokens() <-chan token32 { | |
464 | s := make(chan token32, 16) | |
465 | go func() { | |
466 | for _, v := range t.tree { | |
467 | s <- v.getToken32() | |
468 | } | |
469 | close(s) | |
470 | }() | |
471 | return s | |
472 | } | |
473 | ||
474 | func (t *tokens32) Error() []token32 { | |
475 | ordered := t.Order() | |
476 | length := len(ordered) | |
477 | tokens, length := make([]token32, length), length-1 | |
478 | for i := range tokens { | |
479 | o := ordered[length-i] | |
480 | if len(o) > 1 { | |
481 | tokens[i] = o[len(o)-2].getToken32() | |
482 | } | |
483 | } | |
484 | return tokens | |
485 | } | |
486 | ||
487 | func (t *tokens32) Expand(index int) { | |
488 | tree := t.tree | |
489 | if index >= len(tree) { | |
490 | expanded := make([]token32, 2*len(tree)) | |
491 | copy(expanded, tree) | |
492 | t.tree = expanded | |
493 | } | |
494 | } | |
495 | ||
496 | type Peg struct { | |
497 | *Tree | |
498 | ||
499 | Buffer string | |
500 | buffer []rune | |
501 | rules [92]func() bool | |
502 | Parse func(rule ...int) error | |
503 | Reset func() | |
504 | Pretty bool | |
505 | tokens32 | |
506 | } | |
507 | ||
508 | type textPosition struct { | |
509 | line, symbol int | |
510 | } | |
511 | ||
512 | type textPositionMap map[int]textPosition | |
513 | ||
514 | func translatePositions(buffer []rune, positions []int) textPositionMap { | |
515 | length, translations, j, line, symbol := len(positions), make(textPositionMap, len(positions)), 0, 1, 0 | |
516 | sort.Ints(positions) | |
517 | ||
518 | search: | |
519 | for i, c := range buffer { | |
520 | if c == '\n' { | |
521 | line, symbol = line+1, 0 | |
522 | } else { | |
523 | symbol++ | |
524 | } | |
525 | if i == positions[j] { | |
526 | translations[positions[j]] = textPosition{line, symbol} | |
527 | for j++; j < length; j++ { | |
528 | if i != positions[j] { | |
529 | continue search | |
530 | } | |
531 | } | |
532 | break search | |
533 | } | |
534 | } | |
535 | ||
536 | return translations | |
537 | } | |
538 | ||
539 | type parseError struct { | |
540 | p *Peg | |
541 | max token32 | |
542 | } | |
543 | ||
544 | func (e *parseError) Error() string { | |
545 | tokens, error := []token32{e.max}, "\n" | |
546 | positions, p := make([]int, 2*len(tokens)), 0 | |
547 | for _, token := range tokens { | |
548 | positions[p], p = int(token.begin), p+1 | |
549 | positions[p], p = int(token.end), p+1 | |
550 | } | |
551 | translations := translatePositions(e.p.buffer, positions) | |
552 | format := "parse error near %v (line %v symbol %v - line %v symbol %v):\n%v\n" | |
553 | if e.p.Pretty { | |
554 | format = "parse error near \x1B[34m%v\x1B[m (line %v symbol %v - line %v symbol %v):\n%v\n" | |
555 | } | |
556 | for _, token := range tokens { | |
557 | begin, end := int(token.begin), int(token.end) | |
558 | error += fmt.Sprintf(format, | |
559 | rul3s[token.pegRule], | |
560 | translations[begin].line, translations[begin].symbol, | |
561 | translations[end].line, translations[end].symbol, | |
562 | strconv.Quote(string(e.p.buffer[begin:end]))) | |
563 | } | |
564 | ||
565 | return error | |
566 | } | |
567 | ||
568 | func (p *Peg) PrintSyntaxTree() { | |
569 | p.tokens32.PrintSyntaxTree(p.Buffer) | |
570 | } | |
571 | ||
572 | func (p *Peg) Highlighter() { | |
573 | p.PrintSyntax() | |
574 | } | |
575 | ||
576 | func (p *Peg) Execute() { | |
577 | buffer, _buffer, text, begin, end := p.Buffer, p.buffer, "", 0, 0 | |
578 | for token := range p.Tokens() { | |
579 | switch token.pegRule { | |
580 | ||
581 | case rulePegText: | |
582 | begin, end = int(token.begin), int(token.end) | |
583 | text = string(_buffer[begin:end]) | |
584 | ||
585 | case ruleAction0: | |
586 | p.AddPackage(text) | |
587 | case ruleAction1: | |
588 | p.AddPeg(text) | |
589 | case ruleAction2: | |
590 | p.AddState(text) | |
591 | case ruleAction3: | |
592 | p.AddImport(text) | |
593 | case ruleAction4: | |
594 | p.AddRule(text) | |
595 | case ruleAction5: | |
596 | p.AddExpression() | |
597 | case ruleAction6: | |
598 | p.AddAlternate() | |
599 | case ruleAction7: | |
600 | p.AddNil() | |
601 | p.AddAlternate() | |
602 | case ruleAction8: | |
603 | p.AddNil() | |
604 | case ruleAction9: | |
605 | p.AddSequence() | |
606 | case ruleAction10: | |
607 | p.AddPredicate(text) | |
608 | case ruleAction11: | |
609 | p.AddStateChange(text) | |
610 | case ruleAction12: | |
611 | p.AddPeekFor() | |
612 | case ruleAction13: | |
613 | p.AddPeekNot() | |
614 | case ruleAction14: | |
615 | p.AddQuery() | |
616 | case ruleAction15: | |
617 | p.AddStar() | |
618 | case ruleAction16: | |
619 | p.AddPlus() | |
620 | case ruleAction17: | |
621 | p.AddName(text) | |
622 | case ruleAction18: | |
623 | p.AddDot() | |
624 | case ruleAction19: | |
625 | p.AddAction(text) | |
626 | case ruleAction20: | |
627 | p.AddPush() | |
628 | case ruleAction21: | |
629 | p.AddSequence() | |
630 | case ruleAction22: | |
631 | p.AddSequence() | |
632 | case ruleAction23: | |
633 | p.AddPeekNot() | |
634 | p.AddDot() | |
635 | p.AddSequence() | |
636 | case ruleAction24: | |
637 | p.AddPeekNot() | |
638 | p.AddDot() | |
639 | p.AddSequence() | |
640 | case ruleAction25: | |
641 | p.AddAlternate() | |
642 | case ruleAction26: | |
643 | p.AddAlternate() | |
644 | case ruleAction27: | |
645 | p.AddRange() | |
646 | case ruleAction28: | |
647 | p.AddDoubleRange() | |
648 | case ruleAction29: | |
649 | p.AddCharacter(text) | |
650 | case ruleAction30: | |
651 | p.AddDoubleCharacter(text) | |
652 | case ruleAction31: | |
653 | p.AddCharacter(text) | |
654 | case ruleAction32: | |
655 | p.AddCharacter("\a") | |
656 | case ruleAction33: | |
657 | p.AddCharacter("\b") | |
658 | case ruleAction34: | |
659 | p.AddCharacter("\x1B") | |
660 | case ruleAction35: | |
661 | p.AddCharacter("\f") | |
662 | case ruleAction36: | |
663 | p.AddCharacter("\n") | |
664 | case ruleAction37: | |
665 | p.AddCharacter("\r") | |
666 | case ruleAction38: | |
667 | p.AddCharacter("\t") | |
668 | case ruleAction39: | |
669 | p.AddCharacter("\v") | |
670 | case ruleAction40: | |
671 | p.AddCharacter("'") | |
672 | case ruleAction41: | |
673 | p.AddCharacter("\"") | |
674 | case ruleAction42: | |
675 | p.AddCharacter("[") | |
676 | case ruleAction43: | |
677 | p.AddCharacter("]") | |
678 | case ruleAction44: | |
679 | p.AddCharacter("-") | |
680 | case ruleAction45: | |
681 | p.AddHexaCharacter(text) | |
682 | case ruleAction46: | |
683 | p.AddOctalCharacter(text) | |
684 | case ruleAction47: | |
685 | p.AddOctalCharacter(text) | |
686 | case ruleAction48: | |
687 | p.AddCharacter("\\") | |
688 | ||
689 | } | |
690 | } | |
691 | _, _, _, _, _ = buffer, _buffer, text, begin, end | |
692 | } | |
693 | ||
694 | func (p *Peg) Init() { | |
695 | p.buffer = []rune(p.Buffer) | |
696 | if len(p.buffer) == 0 || p.buffer[len(p.buffer)-1] != endSymbol { | |
697 | p.buffer = append(p.buffer, endSymbol) | |
698 | } | |
699 | ||
700 | tree := tokens32{tree: make([]token32, math.MaxInt16)} | |
701 | var max token32 | |
702 | position, depth, tokenIndex, buffer, _rules := uint32(0), uint32(0), 0, p.buffer, p.rules | |
703 | ||
704 | p.Parse = func(rule ...int) error { | |
705 | r := 1 | |
706 | if len(rule) > 0 { | |
707 | r = rule[0] | |
708 | } | |
709 | matches := p.rules[r]() | |
710 | p.tokens32 = tree | |
711 | if matches { | |
712 | p.trim(tokenIndex) | |
713 | return nil | |
714 | } | |
715 | return &parseError{p, max} | |
716 | } | |
717 | ||
718 | p.Reset = func() { | |
719 | position, tokenIndex, depth = 0, 0, 0 | |
720 | } | |
721 | ||
722 | add := func(rule pegRule, begin uint32) { | |
723 | tree.Expand(tokenIndex) | |
724 | tree.Add(rule, begin, position, depth, tokenIndex) | |
725 | tokenIndex++ | |
726 | if begin != position && position > max.end { | |
727 | max = token32{rule, begin, position, depth} | |
728 | } | |
729 | } | |
730 | ||
731 | matchDot := func() bool { | |
732 | if buffer[position] != endSymbol { | |
733 | position++ | |
734 | return true | |
735 | } | |
736 | return false | |
737 | } | |
738 | ||
739 | /*matchChar := func(c byte) bool { | |
740 | if buffer[position] == c { | |
741 | position++ | |
742 | return true | |
743 | } | |
744 | return false | |
745 | }*/ | |
746 | ||
747 | /*matchRange := func(lower byte, upper byte) bool { | |
748 | if c := buffer[position]; c >= lower && c <= upper { | |
749 | position++ | |
750 | return true | |
751 | } | |
752 | return false | |
753 | }*/ | |
754 | ||
755 | _rules = [...]func() bool{ | |
756 | nil, | |
757 | /* 0 Grammar <- <(Spacing ('p' 'a' 'c' 'k' 'a' 'g' 'e') MustSpacing Identifier Action0 Import* ('t' 'y' 'p' 'e') MustSpacing Identifier Action1 ('P' 'e' 'g') Spacing Action Action2 Definition+ EndOfFile)> */ | |
758 | func() bool { | |
759 | position0, tokenIndex0, depth0 := position, tokenIndex, depth | |
760 | { | |
761 | position1 := position | |
762 | depth++ | |
763 | if !_rules[ruleSpacing]() { | |
764 | goto l0 | |
765 | } | |
766 | if buffer[position] != rune('p') { | |
767 | goto l0 | |
768 | } | |
769 | position++ | |
770 | if buffer[position] != rune('a') { | |
771 | goto l0 | |
772 | } | |
773 | position++ | |
774 | if buffer[position] != rune('c') { | |
775 | goto l0 | |
776 | } | |
777 | position++ | |
778 | if buffer[position] != rune('k') { | |
779 | goto l0 | |
780 | } | |
781 | position++ | |
782 | if buffer[position] != rune('a') { | |
783 | goto l0 | |
784 | } | |
785 | position++ | |
786 | if buffer[position] != rune('g') { | |
787 | goto l0 | |
788 | } | |
789 | position++ | |
790 | if buffer[position] != rune('e') { | |
791 | goto l0 | |
792 | } | |
793 | position++ | |
794 | if !_rules[ruleMustSpacing]() { | |
795 | goto l0 | |
796 | } | |
797 | if !_rules[ruleIdentifier]() { | |
798 | goto l0 | |
799 | } | |
800 | { | |
801 | add(ruleAction0, position) | |
802 | } | |
803 | l3: | |
804 | { | |
805 | position4, tokenIndex4, depth4 := position, tokenIndex, depth | |
806 | { | |
807 | position5 := position | |
808 | depth++ | |
809 | if buffer[position] != rune('i') { | |
810 | goto l4 | |
811 | } | |
812 | position++ | |
813 | if buffer[position] != rune('m') { | |
814 | goto l4 | |
815 | } | |
816 | position++ | |
817 | if buffer[position] != rune('p') { | |
818 | goto l4 | |
819 | } | |
820 | position++ | |
821 | if buffer[position] != rune('o') { | |
822 | goto l4 | |
823 | } | |
824 | position++ | |
825 | if buffer[position] != rune('r') { | |
826 | goto l4 | |
827 | } | |
828 | position++ | |
829 | if buffer[position] != rune('t') { | |
830 | goto l4 | |
831 | } | |
832 | position++ | |
833 | if !_rules[ruleSpacing]() { | |
834 | goto l4 | |
835 | } | |
836 | if buffer[position] != rune('"') { | |
837 | goto l4 | |
838 | } | |
839 | position++ | |
840 | { | |
841 | position6 := position | |
842 | depth++ | |
843 | { | |
844 | switch buffer[position] { | |
845 | case '-': | |
846 | if buffer[position] != rune('-') { | |
847 | goto l4 | |
848 | } | |
849 | position++ | |
850 | break | |
851 | case '.': | |
852 | if buffer[position] != rune('.') { | |
853 | goto l4 | |
854 | } | |
855 | position++ | |
856 | break | |
857 | case '/': | |
858 | if buffer[position] != rune('/') { | |
859 | goto l4 | |
860 | } | |
861 | position++ | |
862 | break | |
863 | case '_': | |
864 | if buffer[position] != rune('_') { | |
865 | goto l4 | |
866 | } | |
867 | position++ | |
868 | break | |
869 | case 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z': | |
870 | if c := buffer[position]; c < rune('A') || c > rune('Z') { | |
871 | goto l4 | |
872 | } | |
873 | position++ | |
874 | break | |
875 | default: | |
876 | if c := buffer[position]; c < rune('a') || c > rune('z') { | |
877 | goto l4 | |
878 | } | |
879 | position++ | |
880 | break | |
881 | } | |
882 | } | |
883 | ||
884 | l7: | |
885 | { | |
886 | position8, tokenIndex8, depth8 := position, tokenIndex, depth | |
887 | { | |
888 | switch buffer[position] { | |
889 | case '-': | |
890 | if buffer[position] != rune('-') { | |
891 | goto l8 | |
892 | } | |
893 | position++ | |
894 | break | |
895 | case '.': | |
896 | if buffer[position] != rune('.') { | |
897 | goto l8 | |
898 | } | |
899 | position++ | |
900 | break | |
901 | case '/': | |
902 | if buffer[position] != rune('/') { | |
903 | goto l8 | |
904 | } | |
905 | position++ | |
906 | break | |
907 | case '_': | |
908 | if buffer[position] != rune('_') { | |
909 | goto l8 | |
910 | } | |
911 | position++ | |
912 | break | |
913 | case 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z': | |
914 | if c := buffer[position]; c < rune('A') || c > rune('Z') { | |
915 | goto l8 | |
916 | } | |
917 | position++ | |
918 | break | |
919 | default: | |
920 | if c := buffer[position]; c < rune('a') || c > rune('z') { | |
921 | goto l8 | |
922 | } | |
923 | position++ | |
924 | break | |
925 | } | |
926 | } | |
927 | ||
928 | goto l7 | |
929 | l8: | |
930 | position, tokenIndex, depth = position8, tokenIndex8, depth8 | |
931 | } | |
932 | depth-- | |
933 | add(rulePegText, position6) | |
934 | } | |
935 | if buffer[position] != rune('"') { | |
936 | goto l4 | |
937 | } | |
938 | position++ | |
939 | if !_rules[ruleSpacing]() { | |
940 | goto l4 | |
941 | } | |
942 | { | |
943 | add(ruleAction3, position) | |
944 | } | |
945 | depth-- | |
946 | add(ruleImport, position5) | |
947 | } | |
948 | goto l3 | |
949 | l4: | |
950 | position, tokenIndex, depth = position4, tokenIndex4, depth4 | |
951 | } | |
952 | if buffer[position] != rune('t') { | |
953 | goto l0 | |
954 | } | |
955 | position++ | |
956 | if buffer[position] != rune('y') { | |
957 | goto l0 | |
958 | } | |
959 | position++ | |
960 | if buffer[position] != rune('p') { | |
961 | goto l0 | |
962 | } | |
963 | position++ | |
964 | if buffer[position] != rune('e') { | |
965 | goto l0 | |
966 | } | |
967 | position++ | |
968 | if !_rules[ruleMustSpacing]() { | |
969 | goto l0 | |
970 | } | |
971 | if !_rules[ruleIdentifier]() { | |
972 | goto l0 | |
973 | } | |
974 | { | |
975 | add(ruleAction1, position) | |
976 | } | |
977 | if buffer[position] != rune('P') { | |
978 | goto l0 | |
979 | } | |
980 | position++ | |
981 | if buffer[position] != rune('e') { | |
982 | goto l0 | |
983 | } | |
984 | position++ | |
985 | if buffer[position] != rune('g') { | |
986 | goto l0 | |
987 | } | |
988 | position++ | |
989 | if !_rules[ruleSpacing]() { | |
990 | goto l0 | |
991 | } | |
992 | if !_rules[ruleAction]() { | |
993 | goto l0 | |
994 | } | |
995 | { | |
996 | add(ruleAction2, position) | |
997 | } | |
998 | { | |
999 | position16 := position | |
1000 | depth++ | |
1001 | if !_rules[ruleIdentifier]() { | |
1002 | goto l0 | |
1003 | } | |
1004 | { | |
1005 | add(ruleAction4, position) | |
1006 | } | |
1007 | if !_rules[ruleLeftArrow]() { | |
1008 | goto l0 | |
1009 | } | |
1010 | if !_rules[ruleExpression]() { | |
1011 | goto l0 | |
1012 | } | |
1013 | { | |
1014 | add(ruleAction5, position) | |
1015 | } | |
1016 | { | |
1017 | position19, tokenIndex19, depth19 := position, tokenIndex, depth | |
1018 | { | |
1019 | position20, tokenIndex20, depth20 := position, tokenIndex, depth | |
1020 | if !_rules[ruleIdentifier]() { | |
1021 | goto l21 | |
1022 | } | |
1023 | if !_rules[ruleLeftArrow]() { | |
1024 | goto l21 | |
1025 | } | |
1026 | goto l20 | |
1027 | l21: | |
1028 | position, tokenIndex, depth = position20, tokenIndex20, depth20 | |
1029 | { | |
1030 | position22, tokenIndex22, depth22 := position, tokenIndex, depth | |
1031 | if !matchDot() { | |
1032 | goto l22 | |
1033 | } | |
1034 | goto l0 | |
1035 | l22: | |
1036 | position, tokenIndex, depth = position22, tokenIndex22, depth22 | |
1037 | } | |
1038 | } | |
1039 | l20: | |
1040 | position, tokenIndex, depth = position19, tokenIndex19, depth19 | |
1041 | } | |
1042 | depth-- | |
1043 | add(ruleDefinition, position16) | |
1044 | } | |
1045 | l14: | |
1046 | { | |
1047 | position15, tokenIndex15, depth15 := position, tokenIndex, depth | |
1048 | { | |
1049 | position23 := position | |
1050 | depth++ | |
1051 | if !_rules[ruleIdentifier]() { | |
1052 | goto l15 | |
1053 | } | |
1054 | { | |
1055 | add(ruleAction4, position) | |
1056 | } | |
1057 | if !_rules[ruleLeftArrow]() { | |
1058 | goto l15 | |
1059 | } | |
1060 | if !_rules[ruleExpression]() { | |
1061 | goto l15 | |
1062 | } | |
1063 | { | |
1064 | add(ruleAction5, position) | |
1065 | } | |
1066 | { | |
1067 | position26, tokenIndex26, depth26 := position, tokenIndex, depth | |
1068 | { | |
1069 | position27, tokenIndex27, depth27 := position, tokenIndex, depth | |
1070 | if !_rules[ruleIdentifier]() { | |
1071 | goto l28 | |
1072 | } | |
1073 | if !_rules[ruleLeftArrow]() { | |
1074 | goto l28 | |
1075 | } | |
1076 | goto l27 | |
1077 | l28: | |
1078 | position, tokenIndex, depth = position27, tokenIndex27, depth27 | |
1079 | { | |
1080 | position29, tokenIndex29, depth29 := position, tokenIndex, depth | |
1081 | if !matchDot() { | |
1082 | goto l29 | |
1083 | } | |
1084 | goto l15 | |
1085 | l29: | |
1086 | position, tokenIndex, depth = position29, tokenIndex29, depth29 | |
1087 | } | |
1088 | } | |
1089 | l27: | |
1090 | position, tokenIndex, depth = position26, tokenIndex26, depth26 | |
1091 | } | |
1092 | depth-- | |
1093 | add(ruleDefinition, position23) | |
1094 | } | |
1095 | goto l14 | |
1096 | l15: | |
1097 | position, tokenIndex, depth = position15, tokenIndex15, depth15 | |
1098 | } | |
1099 | { | |
1100 | position30 := position | |
1101 | depth++ | |
1102 | { | |
1103 | position31, tokenIndex31, depth31 := position, tokenIndex, depth | |
1104 | if !matchDot() { | |
1105 | goto l31 | |
1106 | } | |
1107 | goto l0 | |
1108 | l31: | |
1109 | position, tokenIndex, depth = position31, tokenIndex31, depth31 | |
1110 | } | |
1111 | depth-- | |
1112 | add(ruleEndOfFile, position30) | |
1113 | } | |
1114 | depth-- | |
1115 | add(ruleGrammar, position1) | |
1116 | } | |
1117 | return true | |
1118 | l0: | |
1119 | position, tokenIndex, depth = position0, tokenIndex0, depth0 | |
1120 | return false | |
1121 | }, | |
1122 | /* 1 Import <- <('i' 'm' 'p' 'o' 'r' 't' Spacing '"' <((&('-') '-') | (&('.') '.') | (&('/') '/') | (&('_') '_') | (&('A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z') [A-Z]) | (&('a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z') [a-z]))+> '"' Spacing Action3)> */ | |
1123 | nil, | |
1124 | /* 2 Definition <- <(Identifier Action4 LeftArrow Expression Action5 &((Identifier LeftArrow) / !.))> */ | |
1125 | nil, | |
1126 | /* 3 Expression <- <((Sequence (Slash Sequence Action6)* (Slash Action7)?) / Action8)> */ | |
1127 | func() bool { | |
1128 | { | |
1129 | position35 := position | |
1130 | depth++ | |
1131 | { | |
1132 | position36, tokenIndex36, depth36 := position, tokenIndex, depth | |
1133 | if !_rules[ruleSequence]() { | |
1134 | goto l37 | |
1135 | } | |
1136 | l38: | |
1137 | { | |
1138 | position39, tokenIndex39, depth39 := position, tokenIndex, depth | |
1139 | if !_rules[ruleSlash]() { | |
1140 | goto l39 | |
1141 | } | |
1142 | if !_rules[ruleSequence]() { | |
1143 | goto l39 | |
1144 | } | |
1145 | { | |
1146 | add(ruleAction6, position) | |
1147 | } | |
1148 | goto l38 | |
1149 | l39: | |
1150 | position, tokenIndex, depth = position39, tokenIndex39, depth39 | |
1151 | } | |
1152 | { | |
1153 | position41, tokenIndex41, depth41 := position, tokenIndex, depth | |
1154 | if !_rules[ruleSlash]() { | |
1155 | goto l41 | |
1156 | } | |
1157 | { | |
1158 | add(ruleAction7, position) | |
1159 | } | |
1160 | goto l42 | |
1161 | l41: | |
1162 | position, tokenIndex, depth = position41, tokenIndex41, depth41 | |
1163 | } | |
1164 | l42: | |
1165 | goto l36 | |
1166 | l37: | |
1167 | position, tokenIndex, depth = position36, tokenIndex36, depth36 | |
1168 | { | |
1169 | add(ruleAction8, position) | |
1170 | } | |
1171 | } | |
1172 | l36: | |
1173 | depth-- | |
1174 | add(ruleExpression, position35) | |
1175 | } | |
1176 | return true | |
1177 | }, | |
1178 | /* 4 Sequence <- <(Prefix (Prefix Action9)*)> */ | |
1179 | func() bool { | |
1180 | position45, tokenIndex45, depth45 := position, tokenIndex, depth | |
1181 | { | |
1182 | position46 := position | |
1183 | depth++ | |
1184 | if !_rules[rulePrefix]() { | |
1185 | goto l45 | |
1186 | } | |
1187 | l47: | |
1188 | { | |
1189 | position48, tokenIndex48, depth48 := position, tokenIndex, depth | |
1190 | if !_rules[rulePrefix]() { | |
1191 | goto l48 | |
1192 | } | |
1193 | { | |
1194 | add(ruleAction9, position) | |
1195 | } | |
1196 | goto l47 | |
1197 | l48: | |
1198 | position, tokenIndex, depth = position48, tokenIndex48, depth48 | |
1199 | } | |
1200 | depth-- | |
1201 | add(ruleSequence, position46) | |
1202 | } | |
1203 | return true | |
1204 | l45: | |
1205 | position, tokenIndex, depth = position45, tokenIndex45, depth45 | |
1206 | return false | |
1207 | }, | |
1208 | /* 5 Prefix <- <((And Action Action10) / (Not Action Action11) / ((&('!') (Not Suffix Action13)) | (&('&') (And Suffix Action12)) | (&('"' | '\'' | '(' | '.' | '<' | 'A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | '[' | '_' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z' | '{') Suffix)))> */ | |
1209 | func() bool { | |
1210 | position50, tokenIndex50, depth50 := position, tokenIndex, depth | |
1211 | { | |
1212 | position51 := position | |
1213 | depth++ | |
1214 | { | |
1215 | position52, tokenIndex52, depth52 := position, tokenIndex, depth | |
1216 | if !_rules[ruleAnd]() { | |
1217 | goto l53 | |
1218 | } | |
1219 | if !_rules[ruleAction]() { | |
1220 | goto l53 | |
1221 | } | |
1222 | { | |
1223 | add(ruleAction10, position) | |
1224 | } | |
1225 | goto l52 | |
1226 | l53: | |
1227 | position, tokenIndex, depth = position52, tokenIndex52, depth52 | |
1228 | if !_rules[ruleNot]() { | |
1229 | goto l55 | |
1230 | } | |
1231 | if !_rules[ruleAction]() { | |
1232 | goto l55 | |
1233 | } | |
1234 | { | |
1235 | add(ruleAction11, position) | |
1236 | } | |
1237 | goto l52 | |
1238 | l55: | |
1239 | position, tokenIndex, depth = position52, tokenIndex52, depth52 | |
1240 | { | |
1241 | switch buffer[position] { | |
1242 | case '!': | |
1243 | if !_rules[ruleNot]() { | |
1244 | goto l50 | |
1245 | } | |
1246 | if !_rules[ruleSuffix]() { | |
1247 | goto l50 | |
1248 | } | |
1249 | { | |
1250 | add(ruleAction13, position) | |
1251 | } | |
1252 | break | |
1253 | case '&': | |
1254 | if !_rules[ruleAnd]() { | |
1255 | goto l50 | |
1256 | } | |
1257 | if !_rules[ruleSuffix]() { | |
1258 | goto l50 | |
1259 | } | |
1260 | { | |
1261 | add(ruleAction12, position) | |
1262 | } | |
1263 | break | |
1264 | default: | |
1265 | if !_rules[ruleSuffix]() { | |
1266 | goto l50 | |
1267 | } | |
1268 | break | |
1269 | } | |
1270 | } | |
1271 | ||
1272 | } | |
1273 | l52: | |
1274 | depth-- | |
1275 | add(rulePrefix, position51) | |
1276 | } | |
1277 | return true | |
1278 | l50: | |
1279 | position, tokenIndex, depth = position50, tokenIndex50, depth50 | |
1280 | return false | |
1281 | }, | |
1282 | /* 6 Suffix <- <(Primary ((&('+') (Plus Action16)) | (&('*') (Star Action15)) | (&('?') (Question Action14)))?)> */ | |
1283 | func() bool { | |
1284 | position60, tokenIndex60, depth60 := position, tokenIndex, depth | |
1285 | { | |
1286 | position61 := position | |
1287 | depth++ | |
1288 | { | |
1289 | position62 := position | |
1290 | depth++ | |
1291 | { | |
1292 | switch buffer[position] { | |
1293 | case '<': | |
1294 | { | |
1295 | position64 := position | |
1296 | depth++ | |
1297 | if buffer[position] != rune('<') { | |
1298 | goto l60 | |
1299 | } | |
1300 | position++ | |
1301 | if !_rules[ruleSpacing]() { | |
1302 | goto l60 | |
1303 | } | |
1304 | depth-- | |
1305 | add(ruleBegin, position64) | |
1306 | } | |
1307 | if !_rules[ruleExpression]() { | |
1308 | goto l60 | |
1309 | } | |
1310 | { | |
1311 | position65 := position | |
1312 | depth++ | |
1313 | if buffer[position] != rune('>') { | |
1314 | goto l60 | |
1315 | } | |
1316 | position++ | |
1317 | if !_rules[ruleSpacing]() { | |
1318 | goto l60 | |
1319 | } | |
1320 | depth-- | |
1321 | add(ruleEnd, position65) | |
1322 | } | |
1323 | { | |
1324 | add(ruleAction20, position) | |
1325 | } | |
1326 | break | |
1327 | case '{': | |
1328 | if !_rules[ruleAction]() { | |
1329 | goto l60 | |
1330 | } | |
1331 | { | |
1332 | add(ruleAction19, position) | |
1333 | } | |
1334 | break | |
1335 | case '.': | |
1336 | { | |
1337 | position68 := position | |
1338 | depth++ | |
1339 | if buffer[position] != rune('.') { | |
1340 | goto l60 | |
1341 | } | |
1342 | position++ | |
1343 | if !_rules[ruleSpacing]() { | |
1344 | goto l60 | |
1345 | } | |
1346 | depth-- | |
1347 | add(ruleDot, position68) | |
1348 | } | |
1349 | { | |
1350 | add(ruleAction18, position) | |
1351 | } | |
1352 | break | |
1353 | case '[': | |
1354 | { | |
1355 | position70 := position | |
1356 | depth++ | |
1357 | { | |
1358 | position71, tokenIndex71, depth71 := position, tokenIndex, depth | |
1359 | if buffer[position] != rune('[') { | |
1360 | goto l72 | |
1361 | } | |
1362 | position++ | |
1363 | if buffer[position] != rune('[') { | |
1364 | goto l72 | |
1365 | } | |
1366 | position++ | |
1367 | { | |
1368 | position73, tokenIndex73, depth73 := position, tokenIndex, depth | |
1369 | { | |
1370 | position75, tokenIndex75, depth75 := position, tokenIndex, depth | |
1371 | if buffer[position] != rune('^') { | |
1372 | goto l76 | |
1373 | } | |
1374 | position++ | |
1375 | if !_rules[ruleDoubleRanges]() { | |
1376 | goto l76 | |
1377 | } | |
1378 | { | |
1379 | add(ruleAction23, position) | |
1380 | } | |
1381 | goto l75 | |
1382 | l76: | |
1383 | position, tokenIndex, depth = position75, tokenIndex75, depth75 | |
1384 | if !_rules[ruleDoubleRanges]() { | |
1385 | goto l73 | |
1386 | } | |
1387 | } | |
1388 | l75: | |
1389 | goto l74 | |
1390 | l73: | |
1391 | position, tokenIndex, depth = position73, tokenIndex73, depth73 | |
1392 | } | |
1393 | l74: | |
1394 | if buffer[position] != rune(']') { | |
1395 | goto l72 | |
1396 | } | |
1397 | position++ | |
1398 | if buffer[position] != rune(']') { | |
1399 | goto l72 | |
1400 | } | |
1401 | position++ | |
1402 | goto l71 | |
1403 | l72: | |
1404 | position, tokenIndex, depth = position71, tokenIndex71, depth71 | |
1405 | if buffer[position] != rune('[') { | |
1406 | goto l60 | |
1407 | } | |
1408 | position++ | |
1409 | { | |
1410 | position78, tokenIndex78, depth78 := position, tokenIndex, depth | |
1411 | { | |
1412 | position80, tokenIndex80, depth80 := position, tokenIndex, depth | |
1413 | if buffer[position] != rune('^') { | |
1414 | goto l81 | |
1415 | } | |
1416 | position++ | |
1417 | if !_rules[ruleRanges]() { | |
1418 | goto l81 | |
1419 | } | |
1420 | { | |
1421 | add(ruleAction24, position) | |
1422 | } | |
1423 | goto l80 | |
1424 | l81: | |
1425 | position, tokenIndex, depth = position80, tokenIndex80, depth80 | |
1426 | if !_rules[ruleRanges]() { | |
1427 | goto l78 | |
1428 | } | |
1429 | } | |
1430 | l80: | |
1431 | goto l79 | |
1432 | l78: | |
1433 | position, tokenIndex, depth = position78, tokenIndex78, depth78 | |
1434 | } | |
1435 | l79: | |
1436 | if buffer[position] != rune(']') { | |
1437 | goto l60 | |
1438 | } | |
1439 | position++ | |
1440 | } | |
1441 | l71: | |
1442 | if !_rules[ruleSpacing]() { | |
1443 | goto l60 | |
1444 | } | |
1445 | depth-- | |
1446 | add(ruleClass, position70) | |
1447 | } | |
1448 | break | |
1449 | case '"', '\'': | |
1450 | { | |
1451 | position83 := position | |
1452 | depth++ | |
1453 | { | |
1454 | position84, tokenIndex84, depth84 := position, tokenIndex, depth | |
1455 | if buffer[position] != rune('\'') { | |
1456 | goto l85 | |
1457 | } | |
1458 | position++ | |
1459 | { | |
1460 | position86, tokenIndex86, depth86 := position, tokenIndex, depth | |
1461 | { | |
1462 | position88, tokenIndex88, depth88 := position, tokenIndex, depth | |
1463 | if buffer[position] != rune('\'') { | |
1464 | goto l88 | |
1465 | } | |
1466 | position++ | |
1467 | goto l86 | |
1468 | l88: | |
1469 | position, tokenIndex, depth = position88, tokenIndex88, depth88 | |
1470 | } | |
1471 | if !_rules[ruleChar]() { | |
1472 | goto l86 | |
1473 | } | |
1474 | goto l87 | |
1475 | l86: | |
1476 | position, tokenIndex, depth = position86, tokenIndex86, depth86 | |
1477 | } | |
1478 | l87: | |
1479 | l89: | |
1480 | { | |
1481 | position90, tokenIndex90, depth90 := position, tokenIndex, depth | |
1482 | { | |
1483 | position91, tokenIndex91, depth91 := position, tokenIndex, depth | |
1484 | if buffer[position] != rune('\'') { | |
1485 | goto l91 | |
1486 | } | |
1487 | position++ | |
1488 | goto l90 | |
1489 | l91: | |
1490 | position, tokenIndex, depth = position91, tokenIndex91, depth91 | |
1491 | } | |
1492 | if !_rules[ruleChar]() { | |
1493 | goto l90 | |
1494 | } | |
1495 | { | |
1496 | add(ruleAction21, position) | |
1497 | } | |
1498 | goto l89 | |
1499 | l90: | |
1500 | position, tokenIndex, depth = position90, tokenIndex90, depth90 | |
1501 | } | |
1502 | if buffer[position] != rune('\'') { | |
1503 | goto l85 | |
1504 | } | |
1505 | position++ | |
1506 | if !_rules[ruleSpacing]() { | |
1507 | goto l85 | |
1508 | } | |
1509 | goto l84 | |
1510 | l85: | |
1511 | position, tokenIndex, depth = position84, tokenIndex84, depth84 | |
1512 | if buffer[position] != rune('"') { | |
1513 | goto l60 | |
1514 | } | |
1515 | position++ | |
1516 | { | |
1517 | position93, tokenIndex93, depth93 := position, tokenIndex, depth | |
1518 | { | |
1519 | position95, tokenIndex95, depth95 := position, tokenIndex, depth | |
1520 | if buffer[position] != rune('"') { | |
1521 | goto l95 | |
1522 | } | |
1523 | position++ | |
1524 | goto l93 | |
1525 | l95: | |
1526 | position, tokenIndex, depth = position95, tokenIndex95, depth95 | |
1527 | } | |
1528 | if !_rules[ruleDoubleChar]() { | |
1529 | goto l93 | |
1530 | } | |
1531 | goto l94 | |
1532 | l93: | |
1533 | position, tokenIndex, depth = position93, tokenIndex93, depth93 | |
1534 | } | |
1535 | l94: | |
1536 | l96: | |
1537 | { | |
1538 | position97, tokenIndex97, depth97 := position, tokenIndex, depth | |
1539 | { | |
1540 | position98, tokenIndex98, depth98 := position, tokenIndex, depth | |
1541 | if buffer[position] != rune('"') { | |
1542 | goto l98 | |
1543 | } | |
1544 | position++ | |
1545 | goto l97 | |
1546 | l98: | |
1547 | position, tokenIndex, depth = position98, tokenIndex98, depth98 | |
1548 | } | |
1549 | if !_rules[ruleDoubleChar]() { | |
1550 | goto l97 | |
1551 | } | |
1552 | { | |
1553 | add(ruleAction22, position) | |
1554 | } | |
1555 | goto l96 | |
1556 | l97: | |
1557 | position, tokenIndex, depth = position97, tokenIndex97, depth97 | |
1558 | } | |
1559 | if buffer[position] != rune('"') { | |
1560 | goto l60 | |
1561 | } | |
1562 | position++ | |
1563 | if !_rules[ruleSpacing]() { | |
1564 | goto l60 | |
1565 | } | |
1566 | } | |
1567 | l84: | |
1568 | depth-- | |
1569 | add(ruleLiteral, position83) | |
1570 | } | |
1571 | break | |
1572 | case '(': | |
1573 | { | |
1574 | position100 := position | |
1575 | depth++ | |
1576 | if buffer[position] != rune('(') { | |
1577 | goto l60 | |
1578 | } | |
1579 | position++ | |
1580 | if !_rules[ruleSpacing]() { | |
1581 | goto l60 | |
1582 | } | |
1583 | depth-- | |
1584 | add(ruleOpen, position100) | |
1585 | } | |
1586 | if !_rules[ruleExpression]() { | |
1587 | goto l60 | |
1588 | } | |
1589 | { | |
1590 | position101 := position | |
1591 | depth++ | |
1592 | if buffer[position] != rune(')') { | |
1593 | goto l60 | |
1594 | } | |
1595 | position++ | |
1596 | if !_rules[ruleSpacing]() { | |
1597 | goto l60 | |
1598 | } | |
1599 | depth-- | |
1600 | add(ruleClose, position101) | |
1601 | } | |
1602 | break | |
1603 | default: | |
1604 | if !_rules[ruleIdentifier]() { | |
1605 | goto l60 | |
1606 | } | |
1607 | { | |
1608 | position102, tokenIndex102, depth102 := position, tokenIndex, depth | |
1609 | if !_rules[ruleLeftArrow]() { | |
1610 | goto l102 | |
1611 | } | |
1612 | goto l60 | |
1613 | l102: | |
1614 | position, tokenIndex, depth = position102, tokenIndex102, depth102 | |
1615 | } | |
1616 | { | |
1617 | add(ruleAction17, position) | |
1618 | } | |
1619 | break | |
1620 | } | |
1621 | } | |
1622 | ||
1623 | depth-- | |
1624 | add(rulePrimary, position62) | |
1625 | } | |
1626 | { | |
1627 | position104, tokenIndex104, depth104 := position, tokenIndex, depth | |
1628 | { | |
1629 | switch buffer[position] { | |
1630 | case '+': | |
1631 | { | |
1632 | position107 := position | |
1633 | depth++ | |
1634 | if buffer[position] != rune('+') { | |
1635 | goto l104 | |
1636 | } | |
1637 | position++ | |
1638 | if !_rules[ruleSpacing]() { | |
1639 | goto l104 | |
1640 | } | |
1641 | depth-- | |
1642 | add(rulePlus, position107) | |
1643 | } | |
1644 | { | |
1645 | add(ruleAction16, position) | |
1646 | } | |
1647 | break | |
1648 | case '*': | |
1649 | { | |
1650 | position109 := position | |
1651 | depth++ | |
1652 | if buffer[position] != rune('*') { | |
1653 | goto l104 | |
1654 | } | |
1655 | position++ | |
1656 | if !_rules[ruleSpacing]() { | |
1657 | goto l104 | |
1658 | } | |
1659 | depth-- | |
1660 | add(ruleStar, position109) | |
1661 | } | |
1662 | { | |
1663 | add(ruleAction15, position) | |
1664 | } | |
1665 | break | |
1666 | default: | |
1667 | { | |
1668 | position111 := position | |
1669 | depth++ | |
1670 | if buffer[position] != rune('?') { | |
1671 | goto l104 | |
1672 | } | |
1673 | position++ | |
1674 | if !_rules[ruleSpacing]() { | |
1675 | goto l104 | |
1676 | } | |
1677 | depth-- | |
1678 | add(ruleQuestion, position111) | |
1679 | } | |
1680 | { | |
1681 | add(ruleAction14, position) | |
1682 | } | |
1683 | break | |
1684 | } | |
1685 | } | |
1686 | ||
1687 | goto l105 | |
1688 | l104: | |
1689 | position, tokenIndex, depth = position104, tokenIndex104, depth104 | |
1690 | } | |
1691 | l105: | |
1692 | depth-- | |
1693 | add(ruleSuffix, position61) | |
1694 | } | |
1695 | return true | |
1696 | l60: | |
1697 | position, tokenIndex, depth = position60, tokenIndex60, depth60 | |
1698 | return false | |
1699 | }, | |
1700 | /* 7 Primary <- <((&('<') (Begin Expression End Action20)) | (&('{') (Action Action19)) | (&('.') (Dot Action18)) | (&('[') Class) | (&('"' | '\'') Literal) | (&('(') (Open Expression Close)) | (&('A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z' | '_' | 'a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z') (Identifier !LeftArrow Action17)))> */ | |
1701 | nil, | |
1702 | /* 8 Identifier <- <(<(IdentStart IdentCont*)> Spacing)> */ | |
1703 | func() bool { | |
1704 | position114, tokenIndex114, depth114 := position, tokenIndex, depth | |
1705 | { | |
1706 | position115 := position | |
1707 | depth++ | |
1708 | { | |
1709 | position116 := position | |
1710 | depth++ | |
1711 | if !_rules[ruleIdentStart]() { | |
1712 | goto l114 | |
1713 | } | |
1714 | l117: | |
1715 | { | |
1716 | position118, tokenIndex118, depth118 := position, tokenIndex, depth | |
1717 | { | |
1718 | position119 := position | |
1719 | depth++ | |
1720 | { | |
1721 | position120, tokenIndex120, depth120 := position, tokenIndex, depth | |
1722 | if !_rules[ruleIdentStart]() { | |
1723 | goto l121 | |
1724 | } | |
1725 | goto l120 | |
1726 | l121: | |
1727 | position, tokenIndex, depth = position120, tokenIndex120, depth120 | |
1728 | if c := buffer[position]; c < rune('0') || c > rune('9') { | |
1729 | goto l118 | |
1730 | } | |
1731 | position++ | |
1732 | } | |
1733 | l120: | |
1734 | depth-- | |
1735 | add(ruleIdentCont, position119) | |
1736 | } | |
1737 | goto l117 | |
1738 | l118: | |
1739 | position, tokenIndex, depth = position118, tokenIndex118, depth118 | |
1740 | } | |
1741 | depth-- | |
1742 | add(rulePegText, position116) | |
1743 | } | |
1744 | if !_rules[ruleSpacing]() { | |
1745 | goto l114 | |
1746 | } | |
1747 | depth-- | |
1748 | add(ruleIdentifier, position115) | |
1749 | } | |
1750 | return true | |
1751 | l114: | |
1752 | position, tokenIndex, depth = position114, tokenIndex114, depth114 | |
1753 | return false | |
1754 | }, | |
1755 | /* 9 IdentStart <- <((&('_') '_') | (&('A' | 'B' | 'C' | 'D' | 'E' | 'F' | 'G' | 'H' | 'I' | 'J' | 'K' | 'L' | 'M' | 'N' | 'O' | 'P' | 'Q' | 'R' | 'S' | 'T' | 'U' | 'V' | 'W' | 'X' | 'Y' | 'Z') [A-Z]) | (&('a' | 'b' | 'c' | 'd' | 'e' | 'f' | 'g' | 'h' | 'i' | 'j' | 'k' | 'l' | 'm' | 'n' | 'o' | 'p' | 'q' | 'r' | 's' | 't' | 'u' | 'v' | 'w' | 'x' | 'y' | 'z') [a-z]))> */ | |
1756 | func() bool { | |
1757 | position122, tokenIndex122, depth122 := position, tokenIndex, depth | |
1758 | { | |
1759 | position123 := position | |
1760 | depth++ | |
1761 | { | |
1762 | switch buffer[position] { | |
1763 | case '_': | |
1764 | if buffer[position] != rune('_') { | |
1765 | goto l122 | |
1766 | } | |
1767 | position++ | |
1768 | break | |
1769 | case 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z': | |
1770 | if c := buffer[position]; c < rune('A') || c > rune('Z') { | |
1771 | goto l122 | |
1772 | } | |
1773 | position++ | |
1774 | break | |
1775 | default: | |
1776 | if c := buffer[position]; c < rune('a') || c > rune('z') { | |
1777 | goto l122 | |
1778 | } | |
1779 | position++ | |
1780 | break | |
1781 | } | |
1782 | } | |
1783 | ||
1784 | depth-- | |
1785 | add(ruleIdentStart, position123) | |
1786 | } | |
1787 | return true | |
1788 | l122: | |
1789 | position, tokenIndex, depth = position122, tokenIndex122, depth122 | |
1790 | return false | |
1791 | }, | |
1792 | /* 10 IdentCont <- <(IdentStart / [0-9])> */ | |
1793 | nil, | |
1794 | /* 11 Literal <- <(('\'' (!'\'' Char)? (!'\'' Char Action21)* '\'' Spacing) / ('"' (!'"' DoubleChar)? (!'"' DoubleChar Action22)* '"' Spacing))> */ | |
1795 | nil, | |
1796 | /* 12 Class <- <((('[' '[' (('^' DoubleRanges Action23) / DoubleRanges)? (']' ']')) / ('[' (('^' Ranges Action24) / Ranges)? ']')) Spacing)> */ | |
1797 | nil, | |
1798 | /* 13 Ranges <- <(!']' Range (!']' Range Action25)*)> */ | |
1799 | func() bool { | |
1800 | position128, tokenIndex128, depth128 := position, tokenIndex, depth | |
1801 | { | |
1802 | position129 := position | |
1803 | depth++ | |
1804 | { | |
1805 | position130, tokenIndex130, depth130 := position, tokenIndex, depth | |
1806 | if buffer[position] != rune(']') { | |
1807 | goto l130 | |
1808 | } | |
1809 | position++ | |
1810 | goto l128 | |
1811 | l130: | |
1812 | position, tokenIndex, depth = position130, tokenIndex130, depth130 | |
1813 | } | |
1814 | if !_rules[ruleRange]() { | |
1815 | goto l128 | |
1816 | } | |
1817 | l131: | |
1818 | { | |
1819 | position132, tokenIndex132, depth132 := position, tokenIndex, depth | |
1820 | { | |
1821 | position133, tokenIndex133, depth133 := position, tokenIndex, depth | |
1822 | if buffer[position] != rune(']') { | |
1823 | goto l133 | |
1824 | } | |
1825 | position++ | |
1826 | goto l132 | |
1827 | l133: | |
1828 | position, tokenIndex, depth = position133, tokenIndex133, depth133 | |
1829 | } | |
1830 | if !_rules[ruleRange]() { | |
1831 | goto l132 | |
1832 | } | |
1833 | { | |
1834 | add(ruleAction25, position) | |
1835 | } | |
1836 | goto l131 | |
1837 | l132: | |
1838 | position, tokenIndex, depth = position132, tokenIndex132, depth132 | |
1839 | } | |
1840 | depth-- | |
1841 | add(ruleRanges, position129) | |
1842 | } | |
1843 | return true | |
1844 | l128: | |
1845 | position, tokenIndex, depth = position128, tokenIndex128, depth128 | |
1846 | return false | |
1847 | }, | |
1848 | /* 14 DoubleRanges <- <(!(']' ']') DoubleRange (!(']' ']') DoubleRange Action26)*)> */ | |
1849 | func() bool { | |
1850 | position135, tokenIndex135, depth135 := position, tokenIndex, depth | |
1851 | { | |
1852 | position136 := position | |
1853 | depth++ | |
1854 | { | |
1855 | position137, tokenIndex137, depth137 := position, tokenIndex, depth | |
1856 | if buffer[position] != rune(']') { | |
1857 | goto l137 | |
1858 | } | |
1859 | position++ | |
1860 | if buffer[position] != rune(']') { | |
1861 | goto l137 | |
1862 | } | |
1863 | position++ | |
1864 | goto l135 | |
1865 | l137: | |
1866 | position, tokenIndex, depth = position137, tokenIndex137, depth137 | |
1867 | } | |
1868 | if !_rules[ruleDoubleRange]() { | |
1869 | goto l135 | |
1870 | } | |
1871 | l138: | |
1872 | { | |
1873 | position139, tokenIndex139, depth139 := position, tokenIndex, depth | |
1874 | { | |
1875 | position140, tokenIndex140, depth140 := position, tokenIndex, depth | |
1876 | if buffer[position] != rune(']') { | |
1877 | goto l140 | |
1878 | } | |
1879 | position++ | |
1880 | if buffer[position] != rune(']') { | |
1881 | goto l140 | |
1882 | } | |
1883 | position++ | |
1884 | goto l139 | |
1885 | l140: | |
1886 | position, tokenIndex, depth = position140, tokenIndex140, depth140 | |
1887 | } | |
1888 | if !_rules[ruleDoubleRange]() { | |
1889 | goto l139 | |
1890 | } | |
1891 | { | |
1892 | add(ruleAction26, position) | |
1893 | } | |
1894 | goto l138 | |
1895 | l139: | |
1896 | position, tokenIndex, depth = position139, tokenIndex139, depth139 | |
1897 | } | |
1898 | depth-- | |
1899 | add(ruleDoubleRanges, position136) | |
1900 | } | |
1901 | return true | |
1902 | l135: | |
1903 | position, tokenIndex, depth = position135, tokenIndex135, depth135 | |
1904 | return false | |
1905 | }, | |
1906 | /* 15 Range <- <((Char '-' Char Action27) / Char)> */ | |
1907 | func() bool { | |
1908 | position142, tokenIndex142, depth142 := position, tokenIndex, depth | |
1909 | { | |
1910 | position143 := position | |
1911 | depth++ | |
1912 | { | |
1913 | position144, tokenIndex144, depth144 := position, tokenIndex, depth | |
1914 | if !_rules[ruleChar]() { | |
1915 | goto l145 | |
1916 | } | |
1917 | if buffer[position] != rune('-') { | |
1918 | goto l145 | |
1919 | } | |
1920 | position++ | |
1921 | if !_rules[ruleChar]() { | |
1922 | goto l145 | |
1923 | } | |
1924 | { | |
1925 | add(ruleAction27, position) | |
1926 | } | |
1927 | goto l144 | |
1928 | l145: | |
1929 | position, tokenIndex, depth = position144, tokenIndex144, depth144 | |
1930 | if !_rules[ruleChar]() { | |
1931 | goto l142 | |
1932 | } | |
1933 | } | |
1934 | l144: | |
1935 | depth-- | |
1936 | add(ruleRange, position143) | |
1937 | } | |
1938 | return true | |
1939 | l142: | |
1940 | position, tokenIndex, depth = position142, tokenIndex142, depth142 | |
1941 | return false | |
1942 | }, | |
1943 | /* 16 DoubleRange <- <((Char '-' Char Action28) / DoubleChar)> */ | |
1944 | func() bool { | |
1945 | position147, tokenIndex147, depth147 := position, tokenIndex, depth | |
1946 | { | |
1947 | position148 := position | |
1948 | depth++ | |
1949 | { | |
1950 | position149, tokenIndex149, depth149 := position, tokenIndex, depth | |
1951 | if !_rules[ruleChar]() { | |
1952 | goto l150 | |
1953 | } | |
1954 | if buffer[position] != rune('-') { | |
1955 | goto l150 | |
1956 | } | |
1957 | position++ | |
1958 | if !_rules[ruleChar]() { | |
1959 | goto l150 | |
1960 | } | |
1961 | { | |
1962 | add(ruleAction28, position) | |
1963 | } | |
1964 | goto l149 | |
1965 | l150: | |
1966 | position, tokenIndex, depth = position149, tokenIndex149, depth149 | |
1967 | if !_rules[ruleDoubleChar]() { | |
1968 | goto l147 | |
1969 | } | |
1970 | } | |
1971 | l149: | |
1972 | depth-- | |
1973 | add(ruleDoubleRange, position148) | |
1974 | } | |
1975 | return true | |
1976 | l147: | |
1977 | position, tokenIndex, depth = position147, tokenIndex147, depth147 | |
1978 | return false | |
1979 | }, | |
1980 | /* 17 Char <- <(Escape / (!'\\' <.> Action29))> */ | |
1981 | func() bool { | |
1982 | position152, tokenIndex152, depth152 := position, tokenIndex, depth | |
1983 | { | |
1984 | position153 := position | |
1985 | depth++ | |
1986 | { | |
1987 | position154, tokenIndex154, depth154 := position, tokenIndex, depth | |
1988 | if !_rules[ruleEscape]() { | |
1989 | goto l155 | |
1990 | } | |
1991 | goto l154 | |
1992 | l155: | |
1993 | position, tokenIndex, depth = position154, tokenIndex154, depth154 | |
1994 | { | |
1995 | position156, tokenIndex156, depth156 := position, tokenIndex, depth | |
1996 | if buffer[position] != rune('\\') { | |
1997 | goto l156 | |
1998 | } | |
1999 | position++ | |
2000 | goto l152 | |
2001 | l156: | |
2002 | position, tokenIndex, depth = position156, tokenIndex156, depth156 | |
2003 | } | |
2004 | { | |
2005 | position157 := position | |
2006 | depth++ | |
2007 | if !matchDot() { | |
2008 | goto l152 | |
2009 | } | |
2010 | depth-- | |
2011 | add(rulePegText, position157) | |
2012 | } | |
2013 | { | |
2014 | add(ruleAction29, position) | |
2015 | } | |
2016 | } | |
2017 | l154: | |
2018 | depth-- | |
2019 | add(ruleChar, position153) | |
2020 | } | |
2021 | return true | |
2022 | l152: | |
2023 | position, tokenIndex, depth = position152, tokenIndex152, depth152 | |
2024 | return false | |
2025 | }, | |
2026 | /* 18 DoubleChar <- <(Escape / (<([a-z] / [A-Z])> Action30) / (!'\\' <.> Action31))> */ | |
2027 | func() bool { | |
2028 | position159, tokenIndex159, depth159 := position, tokenIndex, depth | |
2029 | { | |
2030 | position160 := position | |
2031 | depth++ | |
2032 | { | |
2033 | position161, tokenIndex161, depth161 := position, tokenIndex, depth | |
2034 | if !_rules[ruleEscape]() { | |
2035 | goto l162 | |
2036 | } | |
2037 | goto l161 | |
2038 | l162: | |
2039 | position, tokenIndex, depth = position161, tokenIndex161, depth161 | |
2040 | { | |
2041 | position164 := position | |
2042 | depth++ | |
2043 | { | |
2044 | position165, tokenIndex165, depth165 := position, tokenIndex, depth | |
2045 | if c := buffer[position]; c < rune('a') || c > rune('z') { | |
2046 | goto l166 | |
2047 | } | |
2048 | position++ | |
2049 | goto l165 | |
2050 | l166: | |
2051 | position, tokenIndex, depth = position165, tokenIndex165, depth165 | |
2052 | if c := buffer[position]; c < rune('A') || c > rune('Z') { | |
2053 | goto l163 | |
2054 | } | |
2055 | position++ | |
2056 | } | |
2057 | l165: | |
2058 | depth-- | |
2059 | add(rulePegText, position164) | |
2060 | } | |
2061 | { | |
2062 | add(ruleAction30, position) | |
2063 | } | |
2064 | goto l161 | |
2065 | l163: | |
2066 | position, tokenIndex, depth = position161, tokenIndex161, depth161 | |
2067 | { | |
2068 | position168, tokenIndex168, depth168 := position, tokenIndex, depth | |
2069 | if buffer[position] != rune('\\') { | |
2070 | goto l168 | |
2071 | } | |
2072 | position++ | |
2073 | goto l159 | |
2074 | l168: | |
2075 | position, tokenIndex, depth = position168, tokenIndex168, depth168 | |
2076 | } | |
2077 | { | |
2078 | position169 := position | |
2079 | depth++ | |
2080 | if !matchDot() { | |
2081 | goto l159 | |
2082 | } | |
2083 | depth-- | |
2084 | add(rulePegText, position169) | |
2085 | } | |
2086 | { | |
2087 | add(ruleAction31, position) | |
2088 | } | |
2089 | } | |
2090 | l161: | |
2091 | depth-- | |
2092 | add(ruleDoubleChar, position160) | |
2093 | } | |
2094 | return true | |
2095 | l159: | |
2096 | position, tokenIndex, depth = position159, tokenIndex159, depth159 | |
2097 | return false | |
2098 | }, | |
2099 | /* 19 Escape <- <(('\\' ('a' / 'A') Action32) / ('\\' ('b' / 'B') Action33) / ('\\' ('e' / 'E') Action34) / ('\\' ('f' / 'F') Action35) / ('\\' ('n' / 'N') Action36) / ('\\' ('r' / 'R') Action37) / ('\\' ('t' / 'T') Action38) / ('\\' ('v' / 'V') Action39) / ('\\' '\'' Action40) / ('\\' '"' Action41) / ('\\' '[' Action42) / ('\\' ']' Action43) / ('\\' '-' Action44) / ('\\' ('0' ('x' / 'X')) <((&('A' | 'B' | 'C' | 'D' | 'E' | 'F') [A-F]) | (&('a' | 'b' | 'c' | 'd' | 'e' | 'f') [a-f]) | (&('0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9') [0-9]))+> Action45) / ('\\' <([0-3] [0-7] [0-7])> Action46) / ('\\' <([0-7] [0-7]?)> Action47) / ('\\' '\\' Action48))> */ | |
2100 | func() bool { | |
2101 | position171, tokenIndex171, depth171 := position, tokenIndex, depth | |
2102 | { | |
2103 | position172 := position | |
2104 | depth++ | |
2105 | { | |
2106 | position173, tokenIndex173, depth173 := position, tokenIndex, depth | |
2107 | if buffer[position] != rune('\\') { | |
2108 | goto l174 | |
2109 | } | |
2110 | position++ | |
2111 | { | |
2112 | position175, tokenIndex175, depth175 := position, tokenIndex, depth | |
2113 | if buffer[position] != rune('a') { | |
2114 | goto l176 | |
2115 | } | |
2116 | position++ | |
2117 | goto l175 | |
2118 | l176: | |
2119 | position, tokenIndex, depth = position175, tokenIndex175, depth175 | |
2120 | if buffer[position] != rune('A') { | |
2121 | goto l174 | |
2122 | } | |
2123 | position++ | |
2124 | } | |
2125 | l175: | |
2126 | { | |
2127 | add(ruleAction32, position) | |
2128 | } | |
2129 | goto l173 | |
2130 | l174: | |
2131 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2132 | if buffer[position] != rune('\\') { | |
2133 | goto l178 | |
2134 | } | |
2135 | position++ | |
2136 | { | |
2137 | position179, tokenIndex179, depth179 := position, tokenIndex, depth | |
2138 | if buffer[position] != rune('b') { | |
2139 | goto l180 | |
2140 | } | |
2141 | position++ | |
2142 | goto l179 | |
2143 | l180: | |
2144 | position, tokenIndex, depth = position179, tokenIndex179, depth179 | |
2145 | if buffer[position] != rune('B') { | |
2146 | goto l178 | |
2147 | } | |
2148 | position++ | |
2149 | } | |
2150 | l179: | |
2151 | { | |
2152 | add(ruleAction33, position) | |
2153 | } | |
2154 | goto l173 | |
2155 | l178: | |
2156 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2157 | if buffer[position] != rune('\\') { | |
2158 | goto l182 | |
2159 | } | |
2160 | position++ | |
2161 | { | |
2162 | position183, tokenIndex183, depth183 := position, tokenIndex, depth | |
2163 | if buffer[position] != rune('e') { | |
2164 | goto l184 | |
2165 | } | |
2166 | position++ | |
2167 | goto l183 | |
2168 | l184: | |
2169 | position, tokenIndex, depth = position183, tokenIndex183, depth183 | |
2170 | if buffer[position] != rune('E') { | |
2171 | goto l182 | |
2172 | } | |
2173 | position++ | |
2174 | } | |
2175 | l183: | |
2176 | { | |
2177 | add(ruleAction34, position) | |
2178 | } | |
2179 | goto l173 | |
2180 | l182: | |
2181 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2182 | if buffer[position] != rune('\\') { | |
2183 | goto l186 | |
2184 | } | |
2185 | position++ | |
2186 | { | |
2187 | position187, tokenIndex187, depth187 := position, tokenIndex, depth | |
2188 | if buffer[position] != rune('f') { | |
2189 | goto l188 | |
2190 | } | |
2191 | position++ | |
2192 | goto l187 | |
2193 | l188: | |
2194 | position, tokenIndex, depth = position187, tokenIndex187, depth187 | |
2195 | if buffer[position] != rune('F') { | |
2196 | goto l186 | |
2197 | } | |
2198 | position++ | |
2199 | } | |
2200 | l187: | |
2201 | { | |
2202 | add(ruleAction35, position) | |
2203 | } | |
2204 | goto l173 | |
2205 | l186: | |
2206 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2207 | if buffer[position] != rune('\\') { | |
2208 | goto l190 | |
2209 | } | |
2210 | position++ | |
2211 | { | |
2212 | position191, tokenIndex191, depth191 := position, tokenIndex, depth | |
2213 | if buffer[position] != rune('n') { | |
2214 | goto l192 | |
2215 | } | |
2216 | position++ | |
2217 | goto l191 | |
2218 | l192: | |
2219 | position, tokenIndex, depth = position191, tokenIndex191, depth191 | |
2220 | if buffer[position] != rune('N') { | |
2221 | goto l190 | |
2222 | } | |
2223 | position++ | |
2224 | } | |
2225 | l191: | |
2226 | { | |
2227 | add(ruleAction36, position) | |
2228 | } | |
2229 | goto l173 | |
2230 | l190: | |
2231 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2232 | if buffer[position] != rune('\\') { | |
2233 | goto l194 | |
2234 | } | |
2235 | position++ | |
2236 | { | |
2237 | position195, tokenIndex195, depth195 := position, tokenIndex, depth | |
2238 | if buffer[position] != rune('r') { | |
2239 | goto l196 | |
2240 | } | |
2241 | position++ | |
2242 | goto l195 | |
2243 | l196: | |
2244 | position, tokenIndex, depth = position195, tokenIndex195, depth195 | |
2245 | if buffer[position] != rune('R') { | |
2246 | goto l194 | |
2247 | } | |
2248 | position++ | |
2249 | } | |
2250 | l195: | |
2251 | { | |
2252 | add(ruleAction37, position) | |
2253 | } | |
2254 | goto l173 | |
2255 | l194: | |
2256 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2257 | if buffer[position] != rune('\\') { | |
2258 | goto l198 | |
2259 | } | |
2260 | position++ | |
2261 | { | |
2262 | position199, tokenIndex199, depth199 := position, tokenIndex, depth | |
2263 | if buffer[position] != rune('t') { | |
2264 | goto l200 | |
2265 | } | |
2266 | position++ | |
2267 | goto l199 | |
2268 | l200: | |
2269 | position, tokenIndex, depth = position199, tokenIndex199, depth199 | |
2270 | if buffer[position] != rune('T') { | |
2271 | goto l198 | |
2272 | } | |
2273 | position++ | |
2274 | } | |
2275 | l199: | |
2276 | { | |
2277 | add(ruleAction38, position) | |
2278 | } | |
2279 | goto l173 | |
2280 | l198: | |
2281 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2282 | if buffer[position] != rune('\\') { | |
2283 | goto l202 | |
2284 | } | |
2285 | position++ | |
2286 | { | |
2287 | position203, tokenIndex203, depth203 := position, tokenIndex, depth | |
2288 | if buffer[position] != rune('v') { | |
2289 | goto l204 | |
2290 | } | |
2291 | position++ | |
2292 | goto l203 | |
2293 | l204: | |
2294 | position, tokenIndex, depth = position203, tokenIndex203, depth203 | |
2295 | if buffer[position] != rune('V') { | |
2296 | goto l202 | |
2297 | } | |
2298 | position++ | |
2299 | } | |
2300 | l203: | |
2301 | { | |
2302 | add(ruleAction39, position) | |
2303 | } | |
2304 | goto l173 | |
2305 | l202: | |
2306 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2307 | if buffer[position] != rune('\\') { | |
2308 | goto l206 | |
2309 | } | |
2310 | position++ | |
2311 | if buffer[position] != rune('\'') { | |
2312 | goto l206 | |
2313 | } | |
2314 | position++ | |
2315 | { | |
2316 | add(ruleAction40, position) | |
2317 | } | |
2318 | goto l173 | |
2319 | l206: | |
2320 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2321 | if buffer[position] != rune('\\') { | |
2322 | goto l208 | |
2323 | } | |
2324 | position++ | |
2325 | if buffer[position] != rune('"') { | |
2326 | goto l208 | |
2327 | } | |
2328 | position++ | |
2329 | { | |
2330 | add(ruleAction41, position) | |
2331 | } | |
2332 | goto l173 | |
2333 | l208: | |
2334 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2335 | if buffer[position] != rune('\\') { | |
2336 | goto l210 | |
2337 | } | |
2338 | position++ | |
2339 | if buffer[position] != rune('[') { | |
2340 | goto l210 | |
2341 | } | |
2342 | position++ | |
2343 | { | |
2344 | add(ruleAction42, position) | |
2345 | } | |
2346 | goto l173 | |
2347 | l210: | |
2348 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2349 | if buffer[position] != rune('\\') { | |
2350 | goto l212 | |
2351 | } | |
2352 | position++ | |
2353 | if buffer[position] != rune(']') { | |
2354 | goto l212 | |
2355 | } | |
2356 | position++ | |
2357 | { | |
2358 | add(ruleAction43, position) | |
2359 | } | |
2360 | goto l173 | |
2361 | l212: | |
2362 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2363 | if buffer[position] != rune('\\') { | |
2364 | goto l214 | |
2365 | } | |
2366 | position++ | |
2367 | if buffer[position] != rune('-') { | |
2368 | goto l214 | |
2369 | } | |
2370 | position++ | |
2371 | { | |
2372 | add(ruleAction44, position) | |
2373 | } | |
2374 | goto l173 | |
2375 | l214: | |
2376 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2377 | if buffer[position] != rune('\\') { | |
2378 | goto l216 | |
2379 | } | |
2380 | position++ | |
2381 | if buffer[position] != rune('0') { | |
2382 | goto l216 | |
2383 | } | |
2384 | position++ | |
2385 | { | |
2386 | position217, tokenIndex217, depth217 := position, tokenIndex, depth | |
2387 | if buffer[position] != rune('x') { | |
2388 | goto l218 | |
2389 | } | |
2390 | position++ | |
2391 | goto l217 | |
2392 | l218: | |
2393 | position, tokenIndex, depth = position217, tokenIndex217, depth217 | |
2394 | if buffer[position] != rune('X') { | |
2395 | goto l216 | |
2396 | } | |
2397 | position++ | |
2398 | } | |
2399 | l217: | |
2400 | { | |
2401 | position219 := position | |
2402 | depth++ | |
2403 | { | |
2404 | switch buffer[position] { | |
2405 | case 'A', 'B', 'C', 'D', 'E', 'F': | |
2406 | if c := buffer[position]; c < rune('A') || c > rune('F') { | |
2407 | goto l216 | |
2408 | } | |
2409 | position++ | |
2410 | break | |
2411 | case 'a', 'b', 'c', 'd', 'e', 'f': | |
2412 | if c := buffer[position]; c < rune('a') || c > rune('f') { | |
2413 | goto l216 | |
2414 | } | |
2415 | position++ | |
2416 | break | |
2417 | default: | |
2418 | if c := buffer[position]; c < rune('0') || c > rune('9') { | |
2419 | goto l216 | |
2420 | } | |
2421 | position++ | |
2422 | break | |
2423 | } | |
2424 | } | |
2425 | ||
2426 | l220: | |
2427 | { | |
2428 | position221, tokenIndex221, depth221 := position, tokenIndex, depth | |
2429 | { | |
2430 | switch buffer[position] { | |
2431 | case 'A', 'B', 'C', 'D', 'E', 'F': | |
2432 | if c := buffer[position]; c < rune('A') || c > rune('F') { | |
2433 | goto l221 | |
2434 | } | |
2435 | position++ | |
2436 | break | |
2437 | case 'a', 'b', 'c', 'd', 'e', 'f': | |
2438 | if c := buffer[position]; c < rune('a') || c > rune('f') { | |
2439 | goto l221 | |
2440 | } | |
2441 | position++ | |
2442 | break | |
2443 | default: | |
2444 | if c := buffer[position]; c < rune('0') || c > rune('9') { | |
2445 | goto l221 | |
2446 | } | |
2447 | position++ | |
2448 | break | |
2449 | } | |
2450 | } | |
2451 | ||
2452 | goto l220 | |
2453 | l221: | |
2454 | position, tokenIndex, depth = position221, tokenIndex221, depth221 | |
2455 | } | |
2456 | depth-- | |
2457 | add(rulePegText, position219) | |
2458 | } | |
2459 | { | |
2460 | add(ruleAction45, position) | |
2461 | } | |
2462 | goto l173 | |
2463 | l216: | |
2464 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2465 | if buffer[position] != rune('\\') { | |
2466 | goto l225 | |
2467 | } | |
2468 | position++ | |
2469 | { | |
2470 | position226 := position | |
2471 | depth++ | |
2472 | if c := buffer[position]; c < rune('0') || c > rune('3') { | |
2473 | goto l225 | |
2474 | } | |
2475 | position++ | |
2476 | if c := buffer[position]; c < rune('0') || c > rune('7') { | |
2477 | goto l225 | |
2478 | } | |
2479 | position++ | |
2480 | if c := buffer[position]; c < rune('0') || c > rune('7') { | |
2481 | goto l225 | |
2482 | } | |
2483 | position++ | |
2484 | depth-- | |
2485 | add(rulePegText, position226) | |
2486 | } | |
2487 | { | |
2488 | add(ruleAction46, position) | |
2489 | } | |
2490 | goto l173 | |
2491 | l225: | |
2492 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2493 | if buffer[position] != rune('\\') { | |
2494 | goto l228 | |
2495 | } | |
2496 | position++ | |
2497 | { | |
2498 | position229 := position | |
2499 | depth++ | |
2500 | if c := buffer[position]; c < rune('0') || c > rune('7') { | |
2501 | goto l228 | |
2502 | } | |
2503 | position++ | |
2504 | { | |
2505 | position230, tokenIndex230, depth230 := position, tokenIndex, depth | |
2506 | if c := buffer[position]; c < rune('0') || c > rune('7') { | |
2507 | goto l230 | |
2508 | } | |
2509 | position++ | |
2510 | goto l231 | |
2511 | l230: | |
2512 | position, tokenIndex, depth = position230, tokenIndex230, depth230 | |
2513 | } | |
2514 | l231: | |
2515 | depth-- | |
2516 | add(rulePegText, position229) | |
2517 | } | |
2518 | { | |
2519 | add(ruleAction47, position) | |
2520 | } | |
2521 | goto l173 | |
2522 | l228: | |
2523 | position, tokenIndex, depth = position173, tokenIndex173, depth173 | |
2524 | if buffer[position] != rune('\\') { | |
2525 | goto l171 | |
2526 | } | |
2527 | position++ | |
2528 | if buffer[position] != rune('\\') { | |
2529 | goto l171 | |
2530 | } | |
2531 | position++ | |
2532 | { | |
2533 | add(ruleAction48, position) | |
2534 | } | |
2535 | } | |
2536 | l173: | |
2537 | depth-- | |
2538 | add(ruleEscape, position172) | |
2539 | } | |
2540 | return true | |
2541 | l171: | |
2542 | position, tokenIndex, depth = position171, tokenIndex171, depth171 | |
2543 | return false | |
2544 | }, | |
2545 | /* 20 LeftArrow <- <((('<' '-') / '←') Spacing)> */ | |
2546 | func() bool { | |
2547 | position234, tokenIndex234, depth234 := position, tokenIndex, depth | |
2548 | { | |
2549 | position235 := position | |
2550 | depth++ | |
2551 | { | |
2552 | position236, tokenIndex236, depth236 := position, tokenIndex, depth | |
2553 | if buffer[position] != rune('<') { | |
2554 | goto l237 | |
2555 | } | |
2556 | position++ | |
2557 | if buffer[position] != rune('-') { | |
2558 | goto l237 | |
2559 | } | |
2560 | position++ | |
2561 | goto l236 | |
2562 | l237: | |
2563 | position, tokenIndex, depth = position236, tokenIndex236, depth236 | |
2564 | if buffer[position] != rune('←') { | |
2565 | goto l234 | |
2566 | } | |
2567 | position++ | |
2568 | } | |
2569 | l236: | |
2570 | if !_rules[ruleSpacing]() { | |
2571 | goto l234 | |
2572 | } | |
2573 | depth-- | |
2574 | add(ruleLeftArrow, position235) | |
2575 | } | |
2576 | return true | |
2577 | l234: | |
2578 | position, tokenIndex, depth = position234, tokenIndex234, depth234 | |
2579 | return false | |
2580 | }, | |
2581 | /* 21 Slash <- <('/' Spacing)> */ | |
2582 | func() bool { | |
2583 | position238, tokenIndex238, depth238 := position, tokenIndex, depth | |
2584 | { | |
2585 | position239 := position | |
2586 | depth++ | |
2587 | if buffer[position] != rune('/') { | |
2588 | goto l238 | |
2589 | } | |
2590 | position++ | |
2591 | if !_rules[ruleSpacing]() { | |
2592 | goto l238 | |
2593 | } | |
2594 | depth-- | |
2595 | add(ruleSlash, position239) | |
2596 | } | |
2597 | return true | |
2598 | l238: | |
2599 | position, tokenIndex, depth = position238, tokenIndex238, depth238 | |
2600 | return false | |
2601 | }, | |
2602 | /* 22 And <- <('&' Spacing)> */ | |
2603 | func() bool { | |
2604 | position240, tokenIndex240, depth240 := position, tokenIndex, depth | |
2605 | { | |
2606 | position241 := position | |
2607 | depth++ | |
2608 | if buffer[position] != rune('&') { | |
2609 | goto l240 | |
2610 | } | |
2611 | position++ | |
2612 | if !_rules[ruleSpacing]() { | |
2613 | goto l240 | |
2614 | } | |
2615 | depth-- | |
2616 | add(ruleAnd, position241) | |
2617 | } | |
2618 | return true | |
2619 | l240: | |
2620 | position, tokenIndex, depth = position240, tokenIndex240, depth240 | |
2621 | return false | |
2622 | }, | |
2623 | /* 23 Not <- <('!' Spacing)> */ | |
2624 | func() bool { | |
2625 | position242, tokenIndex242, depth242 := position, tokenIndex, depth | |
2626 | { | |
2627 | position243 := position | |
2628 | depth++ | |
2629 | if buffer[position] != rune('!') { | |
2630 | goto l242 | |
2631 | } | |
2632 | position++ | |
2633 | if !_rules[ruleSpacing]() { | |
2634 | goto l242 | |
2635 | } | |
2636 | depth-- | |
2637 | add(ruleNot, position243) | |
2638 | } | |
2639 | return true | |
2640 | l242: | |
2641 | position, tokenIndex, depth = position242, tokenIndex242, depth242 | |
2642 | return false | |
2643 | }, | |
2644 | /* 24 Question <- <('?' Spacing)> */ | |
2645 | nil, | |
2646 | /* 25 Star <- <('*' Spacing)> */ | |
2647 | nil, | |
2648 | /* 26 Plus <- <('+' Spacing)> */ | |
2649 | nil, | |
2650 | /* 27 Open <- <('(' Spacing)> */ | |
2651 | nil, | |
2652 | /* 28 Close <- <(')' Spacing)> */ | |
2653 | nil, | |
2654 | /* 29 Dot <- <('.' Spacing)> */ | |
2655 | nil, | |
2656 | /* 30 SpaceComment <- <(Space / Comment)> */ | |
2657 | func() bool { | |
2658 | position250, tokenIndex250, depth250 := position, tokenIndex, depth | |
2659 | { | |
2660 | position251 := position | |
2661 | depth++ | |
2662 | { | |
2663 | position252, tokenIndex252, depth252 := position, tokenIndex, depth | |
2664 | { | |
2665 | position254 := position | |
2666 | depth++ | |
2667 | { | |
2668 | switch buffer[position] { | |
2669 | case '\t': | |
2670 | if buffer[position] != rune('\t') { | |
2671 | goto l253 | |
2672 | } | |
2673 | position++ | |
2674 | break | |
2675 | case ' ': | |
2676 | if buffer[position] != rune(' ') { | |
2677 | goto l253 | |
2678 | } | |
2679 | position++ | |
2680 | break | |
2681 | default: | |
2682 | if !_rules[ruleEndOfLine]() { | |
2683 | goto l253 | |
2684 | } | |
2685 | break | |
2686 | } | |
2687 | } | |
2688 | ||
2689 | depth-- | |
2690 | add(ruleSpace, position254) | |
2691 | } | |
2692 | goto l252 | |
2693 | l253: | |
2694 | position, tokenIndex, depth = position252, tokenIndex252, depth252 | |
2695 | { | |
2696 | position256 := position | |
2697 | depth++ | |
2698 | if buffer[position] != rune('#') { | |
2699 | goto l250 | |
2700 | } | |
2701 | position++ | |
2702 | l257: | |
2703 | { | |
2704 | position258, tokenIndex258, depth258 := position, tokenIndex, depth | |
2705 | { | |
2706 | position259, tokenIndex259, depth259 := position, tokenIndex, depth | |
2707 | if !_rules[ruleEndOfLine]() { | |
2708 | goto l259 | |
2709 | } | |
2710 | goto l258 | |
2711 | l259: | |
2712 | position, tokenIndex, depth = position259, tokenIndex259, depth259 | |
2713 | } | |
2714 | if !matchDot() { | |
2715 | goto l258 | |
2716 | } | |
2717 | goto l257 | |
2718 | l258: | |
2719 | position, tokenIndex, depth = position258, tokenIndex258, depth258 | |
2720 | } | |
2721 | if !_rules[ruleEndOfLine]() { | |
2722 | goto l250 | |
2723 | } | |
2724 | depth-- | |
2725 | add(ruleComment, position256) | |
2726 | } | |
2727 | } | |
2728 | l252: | |
2729 | depth-- | |
2730 | add(ruleSpaceComment, position251) | |
2731 | } | |
2732 | return true | |
2733 | l250: | |
2734 | position, tokenIndex, depth = position250, tokenIndex250, depth250 | |
2735 | return false | |
2736 | }, | |
2737 | /* 31 Spacing <- <SpaceComment*> */ | |
2738 | func() bool { | |
2739 | { | |
2740 | position261 := position | |
2741 | depth++ | |
2742 | l262: | |
2743 | { | |
2744 | position263, tokenIndex263, depth263 := position, tokenIndex, depth | |
2745 | if !_rules[ruleSpaceComment]() { | |
2746 | goto l263 | |
2747 | } | |
2748 | goto l262 | |
2749 | l263: | |
2750 | position, tokenIndex, depth = position263, tokenIndex263, depth263 | |
2751 | } | |
2752 | depth-- | |
2753 | add(ruleSpacing, position261) | |
2754 | } | |
2755 | return true | |
2756 | }, | |
2757 | /* 32 MustSpacing <- <SpaceComment+> */ | |
2758 | func() bool { | |
2759 | position264, tokenIndex264, depth264 := position, tokenIndex, depth | |
2760 | { | |
2761 | position265 := position | |
2762 | depth++ | |
2763 | if !_rules[ruleSpaceComment]() { | |
2764 | goto l264 | |
2765 | } | |
2766 | l266: | |
2767 | { | |
2768 | position267, tokenIndex267, depth267 := position, tokenIndex, depth | |
2769 | if !_rules[ruleSpaceComment]() { | |
2770 | goto l267 | |
2771 | } | |
2772 | goto l266 | |
2773 | l267: | |
2774 | position, tokenIndex, depth = position267, tokenIndex267, depth267 | |
2775 | } | |
2776 | depth-- | |
2777 | add(ruleMustSpacing, position265) | |
2778 | } | |
2779 | return true | |
2780 | l264: | |
2781 | position, tokenIndex, depth = position264, tokenIndex264, depth264 | |
2782 | return false | |
2783 | }, | |
2784 | /* 33 Comment <- <('#' (!EndOfLine .)* EndOfLine)> */ | |
2785 | nil, | |
2786 | /* 34 Space <- <((&('\t') '\t') | (&(' ') ' ') | (&('\n' | '\r') EndOfLine))> */ | |
2787 | nil, | |
2788 | /* 35 EndOfLine <- <(('\r' '\n') / '\n' / '\r')> */ | |
2789 | func() bool { | |
2790 | position270, tokenIndex270, depth270 := position, tokenIndex, depth | |
2791 | { | |
2792 | position271 := position | |
2793 | depth++ | |
2794 | { | |
2795 | position272, tokenIndex272, depth272 := position, tokenIndex, depth | |
2796 | if buffer[position] != rune('\r') { | |
2797 | goto l273 | |
2798 | } | |
2799 | position++ | |
2800 | if buffer[position] != rune('\n') { | |
2801 | goto l273 | |
2802 | } | |
2803 | position++ | |
2804 | goto l272 | |
2805 | l273: | |
2806 | position, tokenIndex, depth = position272, tokenIndex272, depth272 | |
2807 | if buffer[position] != rune('\n') { | |
2808 | goto l274 | |
2809 | } | |
2810 | position++ | |
2811 | goto l272 | |
2812 | l274: | |
2813 | position, tokenIndex, depth = position272, tokenIndex272, depth272 | |
2814 | if buffer[position] != rune('\r') { | |
2815 | goto l270 | |
2816 | } | |
2817 | position++ | |
2818 | } | |
2819 | l272: | |
2820 | depth-- | |
2821 | add(ruleEndOfLine, position271) | |
2822 | } | |
2823 | return true | |
2824 | l270: | |
2825 | position, tokenIndex, depth = position270, tokenIndex270, depth270 | |
2826 | return false | |
2827 | }, | |
2828 | /* 36 EndOfFile <- <!.> */ | |
2829 | nil, | |
2830 | /* 37 Action <- <('{' <ActionBody*> '}' Spacing)> */ | |
2831 | func() bool { | |
2832 | position276, tokenIndex276, depth276 := position, tokenIndex, depth | |
2833 | { | |
2834 | position277 := position | |
2835 | depth++ | |
2836 | if buffer[position] != rune('{') { | |
2837 | goto l276 | |
2838 | } | |
2839 | position++ | |
2840 | { | |
2841 | position278 := position | |
2842 | depth++ | |
2843 | l279: | |
2844 | { | |
2845 | position280, tokenIndex280, depth280 := position, tokenIndex, depth | |
2846 | if !_rules[ruleActionBody]() { | |
2847 | goto l280 | |
2848 | } | |
2849 | goto l279 | |
2850 | l280: | |
2851 | position, tokenIndex, depth = position280, tokenIndex280, depth280 | |
2852 | } | |
2853 | depth-- | |
2854 | add(rulePegText, position278) | |
2855 | } | |
2856 | if buffer[position] != rune('}') { | |
2857 | goto l276 | |
2858 | } | |
2859 | position++ | |
2860 | if !_rules[ruleSpacing]() { | |
2861 | goto l276 | |
2862 | } | |
2863 | depth-- | |
2864 | add(ruleAction, position277) | |
2865 | } | |
2866 | return true | |
2867 | l276: | |
2868 | position, tokenIndex, depth = position276, tokenIndex276, depth276 | |
2869 | return false | |
2870 | }, | |
2871 | /* 38 ActionBody <- <((!('{' / '}') .) / ('{' ActionBody* '}'))> */ | |
2872 | func() bool { | |
2873 | position281, tokenIndex281, depth281 := position, tokenIndex, depth | |
2874 | { | |
2875 | position282 := position | |
2876 | depth++ | |
2877 | { | |
2878 | position283, tokenIndex283, depth283 := position, tokenIndex, depth | |
2879 | { | |
2880 | position285, tokenIndex285, depth285 := position, tokenIndex, depth | |
2881 | { | |
2882 | position286, tokenIndex286, depth286 := position, tokenIndex, depth | |
2883 | if buffer[position] != rune('{') { | |
2884 | goto l287 | |
2885 | } | |
2886 | position++ | |
2887 | goto l286 | |
2888 | l287: | |
2889 | position, tokenIndex, depth = position286, tokenIndex286, depth286 | |
2890 | if buffer[position] != rune('}') { | |
2891 | goto l285 | |
2892 | } | |
2893 | position++ | |
2894 | } | |
2895 | l286: | |
2896 | goto l284 | |
2897 | l285: | |
2898 | position, tokenIndex, depth = position285, tokenIndex285, depth285 | |
2899 | } | |
2900 | if !matchDot() { | |
2901 | goto l284 | |
2902 | } | |
2903 | goto l283 | |
2904 | l284: | |
2905 | position, tokenIndex, depth = position283, tokenIndex283, depth283 | |
2906 | if buffer[position] != rune('{') { | |
2907 | goto l281 | |
2908 | } | |
2909 | position++ | |
2910 | l288: | |
2911 | { | |
2912 | position289, tokenIndex289, depth289 := position, tokenIndex, depth | |
2913 | if !_rules[ruleActionBody]() { | |
2914 | goto l289 | |
2915 | } | |
2916 | goto l288 | |
2917 | l289: | |
2918 | position, tokenIndex, depth = position289, tokenIndex289, depth289 | |
2919 | } | |
2920 | if buffer[position] != rune('}') { | |
2921 | goto l281 | |
2922 | } | |
2923 | position++ | |
2924 | } | |
2925 | l283: | |
2926 | depth-- | |
2927 | add(ruleActionBody, position282) | |
2928 | } | |
2929 | return true | |
2930 | l281: | |
2931 | position, tokenIndex, depth = position281, tokenIndex281, depth281 | |
2932 | return false | |
2933 | }, | |
2934 | /* 39 Begin <- <('<' Spacing)> */ | |
2935 | nil, | |
2936 | /* 40 End <- <('>' Spacing)> */ | |
2937 | nil, | |
2938 | /* 42 Action0 <- <{ p.AddPackage(text) }> */ | |
2939 | nil, | |
2940 | /* 43 Action1 <- <{ p.AddPeg(text) }> */ | |
2941 | nil, | |
2942 | /* 44 Action2 <- <{ p.AddState(text) }> */ | |
2943 | nil, | |
2944 | nil, | |
2945 | /* 46 Action3 <- <{ p.AddImport(text) }> */ | |
2946 | nil, | |
2947 | /* 47 Action4 <- <{ p.AddRule(text) }> */ | |
2948 | nil, | |
2949 | /* 48 Action5 <- <{ p.AddExpression() }> */ | |
2950 | nil, | |
2951 | /* 49 Action6 <- <{ p.AddAlternate() }> */ | |
2952 | nil, | |
2953 | /* 50 Action7 <- <{ p.AddNil(); p.AddAlternate() }> */ | |
2954 | nil, | |
2955 | /* 51 Action8 <- <{ p.AddNil() }> */ | |
2956 | nil, | |
2957 | /* 52 Action9 <- <{ p.AddSequence() }> */ | |
2958 | nil, | |
2959 | /* 53 Action10 <- <{ p.AddPredicate(text) }> */ | |
2960 | nil, | |
2961 | /* 54 Action11 <- <{ p.AddStateChange(text) }> */ | |
2962 | nil, | |
2963 | /* 55 Action12 <- <{ p.AddPeekFor() }> */ | |
2964 | nil, | |
2965 | /* 56 Action13 <- <{ p.AddPeekNot() }> */ | |
2966 | nil, | |
2967 | /* 57 Action14 <- <{ p.AddQuery() }> */ | |
2968 | nil, | |
2969 | /* 58 Action15 <- <{ p.AddStar() }> */ | |
2970 | nil, | |
2971 | /* 59 Action16 <- <{ p.AddPlus() }> */ | |
2972 | nil, | |
2973 | /* 60 Action17 <- <{ p.AddName(text) }> */ | |
2974 | nil, | |
2975 | /* 61 Action18 <- <{ p.AddDot() }> */ | |
2976 | nil, | |
2977 | /* 62 Action19 <- <{ p.AddAction(text) }> */ | |
2978 | nil, | |
2979 | /* 63 Action20 <- <{ p.AddPush() }> */ | |
2980 | nil, | |
2981 | /* 64 Action21 <- <{ p.AddSequence() }> */ | |
2982 | nil, | |
2983 | /* 65 Action22 <- <{ p.AddSequence() }> */ | |
2984 | nil, | |
2985 | /* 66 Action23 <- <{ p.AddPeekNot(); p.AddDot(); p.AddSequence() }> */ | |
2986 | nil, | |
2987 | /* 67 Action24 <- <{ p.AddPeekNot(); p.AddDot(); p.AddSequence() }> */ | |
2988 | nil, | |
2989 | /* 68 Action25 <- <{ p.AddAlternate() }> */ | |
2990 | nil, | |
2991 | /* 69 Action26 <- <{ p.AddAlternate() }> */ | |
2992 | nil, | |
2993 | /* 70 Action27 <- <{ p.AddRange() }> */ | |
2994 | nil, | |
2995 | /* 71 Action28 <- <{ p.AddDoubleRange() }> */ | |
2996 | nil, | |
2997 | /* 72 Action29 <- <{ p.AddCharacter(text) }> */ | |
2998 | nil, | |
2999 | /* 73 Action30 <- <{ p.AddDoubleCharacter(text) }> */ | |
3000 | nil, | |
3001 | /* 74 Action31 <- <{ p.AddCharacter(text) }> */ | |
3002 | nil, | |
3003 | /* 75 Action32 <- <{ p.AddCharacter("\a") }> */ | |
3004 | nil, | |
3005 | /* 76 Action33 <- <{ p.AddCharacter("\b") }> */ | |
3006 | nil, | |
3007 | /* 77 Action34 <- <{ p.AddCharacter("\x1B") }> */ | |
3008 | nil, | |
3009 | /* 78 Action35 <- <{ p.AddCharacter("\f") }> */ | |
3010 | nil, | |
3011 | /* 79 Action36 <- <{ p.AddCharacter("\n") }> */ | |
3012 | nil, | |
3013 | /* 80 Action37 <- <{ p.AddCharacter("\r") }> */ | |
3014 | nil, | |
3015 | /* 81 Action38 <- <{ p.AddCharacter("\t") }> */ | |
3016 | nil, | |
3017 | /* 82 Action39 <- <{ p.AddCharacter("\v") }> */ | |
3018 | nil, | |
3019 | /* 83 Action40 <- <{ p.AddCharacter("'") }> */ | |
3020 | nil, | |
3021 | /* 84 Action41 <- <{ p.AddCharacter("\"") }> */ | |
3022 | nil, | |
3023 | /* 85 Action42 <- <{ p.AddCharacter("[") }> */ | |
3024 | nil, | |
3025 | /* 86 Action43 <- <{ p.AddCharacter("]") }> */ | |
3026 | nil, | |
3027 | /* 87 Action44 <- <{ p.AddCharacter("-") }> */ | |
3028 | nil, | |
3029 | /* 88 Action45 <- <{ p.AddHexaCharacter(text) }> */ | |
3030 | nil, | |
3031 | /* 89 Action46 <- <{ p.AddOctalCharacter(text) }> */ | |
3032 | nil, | |
3033 | /* 90 Action47 <- <{ p.AddOctalCharacter(text) }> */ | |
3034 | nil, | |
3035 | /* 91 Action48 <- <{ p.AddCharacter("\\") }> */ | |
3036 | nil, | |
3037 | } | |
3038 | p.rules = _rules | |
3039 | } |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | c: c.peg.go main.go | |
5 | go build | |
6 | ||
7 | c.peg.go: c.peg | |
8 | ../../peg -switch -inline c.peg | |
9 | ||
10 | clean: | |
11 | rm -f c c.peg.go |
0 | #=========================================================================== | |
1 | # | |
2 | # Parsing Expression Grammar of C for Mouse 1.1 - 1.5. | |
3 | # Based on standard ISO/IEC 9899.1999:TC2, without preprocessor. | |
4 | # Requires semantics class to process Typedefs. | |
5 | # | |
6 | #--------------------------------------------------------------------------- | |
7 | # | |
8 | # Copyright (C) 2007, 2009, 2010 by Roman R Redziejowski (www.romanredz.se). | |
9 | # | |
10 | # The author gives unlimited permission to copy and distribute | |
11 | # this file, with or without modifications, as long as this notice | |
12 | # is preserved, and any changes are properly documented. | |
13 | # | |
14 | # This file is distributed in the hope that it will be useful, | |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
17 | # | |
18 | #--------------------------------------------------------------------------- | |
19 | # | |
20 | # Latest update 2010-11-19 | |
21 | # | |
22 | #--------------------------------------------------------------------------- | |
23 | # | |
24 | # Modifications to the standard grammar: | |
25 | # | |
26 | # Defined # as start of line comment. | |
27 | # Added FunctionSpecifier "_stdcall". | |
28 | # Added TypeQualifier "__declspec()". | |
29 | # Added TypeSpecifier "__attribute__()". | |
30 | # The scope of TypedefNames is not implemented. | |
31 | # | |
32 | #--------------------------------------------------------------------------- | |
33 | # | |
34 | # Implementation of typedefs. | |
35 | # | |
36 | # A TypedefName is an Identifier that has been declared as such | |
37 | # by a previous typedef declaration. It can be used as TypeSpecifier | |
38 | # in DeclarationSpecifiers and SpecifierQualifierList. | |
39 | # Recognizing it as such is essential for correct parsing. | |
40 | # In other contexts, TypedefName is treated as an ordinary Identifier. | |
41 | # | |
42 | # According to 6.7.2, comment 2, of the Standard, TypedefName can appear | |
43 | # in DeclarationSpecifiers or SpecifierQualifierList at most once, | |
44 | # and then as the only TypeSpecifier. To make sure that an Identifer | |
45 | # is recognized as TypedefName only in these contexts, definitions | |
46 | # of these items are changed as follows: | |
47 | # | |
48 | # - TypedefName is removed as an alternative of TypeSpecifier. | |
49 | # | |
50 | # - DeclarationSpecifiers and SpecifierQualifierList are redefined | |
51 | # to allow either single TypedefName or one or more TypeSpecifiers. | |
52 | # | |
53 | # The semantics class, via semantic actions, maintains a table of TypedefNames. | |
54 | # | |
55 | # The rule defining TypedefName as Identifier has a semantic action | |
56 | # that returns true iff the Identifier is in the table. | |
57 | # That means TypedefName is accepted iff it is in the table. | |
58 | # | |
59 | # According to 6.7.7, comment 3, of the Standard, | |
60 | # in a Declaration whose StorageClassSpecifier is TYPEDEF, | |
61 | # each Declarator defines an Identifier to be a TypedefName. | |
62 | # These Identifiers are entered into the table as follows. | |
63 | # | |
64 | # - Each Identifier has itself as semantic value. | |
65 | # | |
66 | # - Each DirectDeclarator starts with either Identifier | |
67 | # or Declarator in parentheses. | |
68 | # Its semantic value is either that Identifier, | |
69 | # or the Identifier obtained as semantic value of that Declarator. | |
70 | # | |
71 | # - Each Declarator has as semantic value the Identifier | |
72 | # appearing in its DirectDeclarator, | |
73 | # | |
74 | # - Each InitDeclarator has as semantic value the Identifier | |
75 | # appearing in its Declarator. | |
76 | # | |
77 | # - InitDeclaratorList has as semantic value | |
78 | # the list of Identifiers appearing in its InitDeclarators. | |
79 | # | |
80 | # - DeclarationSpecifiers has semantic value "typedef" | |
81 | # if any of the specifiers is "typedef" or null otherwise. | |
82 | # | |
83 | # - Declaration has a semantic action that enters Identifiers | |
84 | # delivered by InitDeclaratorList into typedef table | |
85 | # if DeclarationSpecifiers indicate "typedef". | |
86 | # | |
87 | # | |
88 | #--------------------------------------------------------------------------- | |
89 | # | |
90 | # Change log | |
91 | # 2009-07-13 Posted on Internet. | |
92 | # 2010-11-19 Removed superfluous '?' after 'Spacing'. | |
93 | # | |
94 | # | |
95 | #--------------------------------------------------------------------------- | |
96 | # | |
97 | # 2013-02-21 Modified to work with github.com/pointlander/peg | |
98 | # | |
99 | #=========================================================================== | |
100 | ||
101 | ||
102 | #------------------------------------------------------------------------- | |
103 | # A.2.4 External definitions | |
104 | #------------------------------------------------------------------------- | |
105 | ||
106 | package main | |
107 | ||
108 | type C Peg { | |
109 | ||
110 | } | |
111 | ||
112 | TranslationUnit <- Spacing ExternalDeclaration+ EOT | |
113 | ||
114 | ExternalDeclaration <- FunctionDefinition / Declaration | |
115 | ||
116 | FunctionDefinition <- DeclarationSpecifiers Declarator DeclarationList? CompoundStatement | |
117 | ||
118 | DeclarationList <- Declaration+ | |
119 | ||
120 | ||
121 | #------------------------------------------------------------------------- | |
122 | # A.2.2 Declarations | |
123 | #------------------------------------------------------------------------- | |
124 | ||
125 | Declaration <- DeclarationSpecifiers InitDeclaratorList? SEMI #{} | |
126 | ||
127 | DeclarationSpecifiers | |
128 | <- (( StorageClassSpecifier | |
129 | / TypeQualifier | |
130 | / FunctionSpecifier | |
131 | )* | |
132 | TypedefName | |
133 | ( StorageClassSpecifier | |
134 | / TypeQualifier | |
135 | / FunctionSpecifier | |
136 | )* | |
137 | ) #{DeclarationSpecifiers} | |
138 | / ( StorageClassSpecifier | |
139 | / TypeSpecifier | |
140 | / TypeQualifier | |
141 | / FunctionSpecifier | |
142 | )+ #{DeclarationSpecifiers} | |
143 | ||
144 | InitDeclaratorList <- InitDeclarator (COMMA InitDeclarator)* #{} | |
145 | ||
146 | InitDeclarator <- Declarator (EQU Initializer)? #{} | |
147 | ||
148 | StorageClassSpecifier | |
149 | <- TYPEDEF | |
150 | / EXTERN | |
151 | / STATIC | |
152 | / AUTO | |
153 | / REGISTER | |
154 | / ATTRIBUTE LPAR LPAR (!RPAR .)* RPAR RPAR | |
155 | ||
156 | TypeSpecifier | |
157 | <- VOID | |
158 | / CHAR | |
159 | / SHORT | |
160 | / INT | |
161 | / LONG | |
162 | / FLOAT | |
163 | / DOUBLE | |
164 | / SIGNED | |
165 | / UNSIGNED | |
166 | / BOOL | |
167 | / COMPLEX | |
168 | / StructOrUnionSpecifier | |
169 | / EnumSpecifier | |
170 | ||
171 | StructOrUnionSpecifier | |
172 | <- StructOrUnion | |
173 | ( Identifier? LWING StructDeclaration+ RWING | |
174 | / Identifier | |
175 | ) | |
176 | ||
177 | StructOrUnion <- STRUCT / UNION | |
178 | ||
179 | StructDeclaration <- SpecifierQualifierList StructDeclaratorList SEMI | |
180 | ||
181 | SpecifierQualifierList | |
182 | <- ( TypeQualifier* | |
183 | TypedefName | |
184 | TypeQualifier* | |
185 | ) | |
186 | / ( TypeSpecifier | |
187 | / TypeQualifier | |
188 | )+ | |
189 | ||
190 | StructDeclaratorList <- StructDeclarator (COMMA StructDeclarator)* | |
191 | ||
192 | StructDeclarator | |
193 | <- Declarator? COLON ConstantExpression | |
194 | / Declarator | |
195 | ||
196 | EnumSpecifier | |
197 | <- ENUM | |
198 | ( Identifier? LWING EnumeratorList COMMA? RWING | |
199 | / Identifier | |
200 | ) | |
201 | ||
202 | EnumeratorList <- Enumerator (COMMA Enumerator)* | |
203 | ||
204 | Enumerator <- EnumerationConstant (EQU ConstantExpression)? | |
205 | ||
206 | TypeQualifier | |
207 | <- CONST | |
208 | / RESTRICT | |
209 | / VOLATILE | |
210 | / DECLSPEC LPAR Identifier RPAR | |
211 | ||
212 | FunctionSpecifier <- INLINE / STDCALL | |
213 | ||
214 | Declarator <- Pointer? DirectDeclarator #{} | |
215 | ||
216 | DirectDeclarator | |
217 | <- ( Identifier | |
218 | / LPAR Declarator RPAR | |
219 | ) | |
220 | ( LBRK TypeQualifier* AssignmentExpression? RBRK | |
221 | / LBRK STATIC TypeQualifier* AssignmentExpression RBRK | |
222 | / LBRK TypeQualifier+ STATIC AssignmentExpression RBRK | |
223 | / LBRK TypeQualifier* STAR RBRK | |
224 | / LPAR ParameterTypeList RPAR | |
225 | / LPAR IdentifierList? RPAR | |
226 | )* #{} | |
227 | ||
228 | Pointer <- ( STAR TypeQualifier* )+ | |
229 | ||
230 | ParameterTypeList <- ParameterList (COMMA ELLIPSIS)? | |
231 | ||
232 | ParameterList <- ParameterDeclaration (COMMA ParameterDeclaration)* | |
233 | ||
234 | ParameterDeclaration | |
235 | <- DeclarationSpecifiers | |
236 | ( Declarator | |
237 | / AbstractDeclarator | |
238 | )? | |
239 | ||
240 | IdentifierList <- Identifier (COMMA Identifier)* | |
241 | ||
242 | TypeName <- SpecifierQualifierList AbstractDeclarator? | |
243 | ||
244 | AbstractDeclarator | |
245 | <- Pointer? DirectAbstractDeclarator | |
246 | / Pointer | |
247 | ||
248 | DirectAbstractDeclarator | |
249 | <- ( LPAR AbstractDeclarator RPAR | |
250 | / LBRK (AssignmentExpression / STAR)? RBRK | |
251 | / LPAR ParameterTypeList? RPAR | |
252 | ) | |
253 | ( LBRK (AssignmentExpression / STAR)? RBRK | |
254 | / LPAR ParameterTypeList? RPAR | |
255 | )* | |
256 | ||
257 | TypedefName <-Identifier #{&TypedefName} | |
258 | ||
259 | Initializer | |
260 | <- AssignmentExpression | |
261 | / LWING InitializerList COMMA? RWING | |
262 | ||
263 | InitializerList <- Designation? Initializer (COMMA Designation? Initializer)* | |
264 | ||
265 | Designation <- Designator+ EQU | |
266 | ||
267 | Designator | |
268 | <- LBRK ConstantExpression RBRK | |
269 | / DOT Identifier | |
270 | ||
271 | ||
272 | #------------------------------------------------------------------------- | |
273 | # A.2.3 Statements | |
274 | #------------------------------------------------------------------------- | |
275 | ||
276 | Statement | |
277 | <- LabeledStatement | |
278 | / CompoundStatement | |
279 | / ExpressionStatement | |
280 | / SelectionStatement | |
281 | / IterationStatement | |
282 | / JumpStatement | |
283 | ||
284 | LabeledStatement | |
285 | <- Identifier COLON Statement | |
286 | / CASE ConstantExpression COLON Statement | |
287 | / DEFAULT COLON Statement | |
288 | ||
289 | CompoundStatement <- LWING ( Declaration / Statement )* RWING | |
290 | ||
291 | ExpressionStatement <- Expression? SEMI | |
292 | ||
293 | SelectionStatement | |
294 | <- IF LPAR Expression RPAR Statement (ELSE Statement)? | |
295 | / SWITCH LPAR Expression RPAR Statement | |
296 | ||
297 | IterationStatement | |
298 | <- WHILE LPAR Expression RPAR Statement | |
299 | / DO Statement WHILE LPAR Expression RPAR SEMI | |
300 | / FOR LPAR Expression? SEMI Expression? SEMI Expression? RPAR Statement | |
301 | / FOR LPAR Declaration Expression? SEMI Expression? RPAR Statement | |
302 | ||
303 | JumpStatement | |
304 | <- GOTO Identifier SEMI | |
305 | / CONTINUE SEMI | |
306 | / BREAK SEMI | |
307 | / RETURN Expression? SEMI | |
308 | ||
309 | ||
310 | #------------------------------------------------------------------------- | |
311 | # A.2.1 Expressions | |
312 | #------------------------------------------------------------------------- | |
313 | ||
314 | PrimaryExpression | |
315 | <- Identifier | |
316 | / Constant | |
317 | / StringLiteral | |
318 | / LPAR Expression RPAR | |
319 | ||
320 | PostfixExpression | |
321 | <- ( PrimaryExpression | |
322 | / LPAR TypeName RPAR LWING InitializerList COMMA? RWING | |
323 | ) | |
324 | ( LBRK Expression RBRK | |
325 | / LPAR ArgumentExpressionList? RPAR | |
326 | / DOT Identifier | |
327 | / PTR Identifier | |
328 | / INC | |
329 | / DEC | |
330 | )* | |
331 | ||
332 | ArgumentExpressionList <- AssignmentExpression (COMMA AssignmentExpression)* | |
333 | ||
334 | UnaryExpression | |
335 | <- PostfixExpression | |
336 | / INC UnaryExpression | |
337 | / DEC UnaryExpression | |
338 | / UnaryOperator CastExpression | |
339 | / SIZEOF (UnaryExpression / LPAR TypeName RPAR ) | |
340 | ||
341 | UnaryOperator | |
342 | <- AND | |
343 | / STAR | |
344 | / PLUS | |
345 | / MINUS | |
346 | / TILDA | |
347 | / BANG | |
348 | ||
349 | CastExpression <- (LPAR TypeName RPAR)* UnaryExpression | |
350 | ||
351 | MultiplicativeExpression <- CastExpression ((STAR / DIV / MOD) CastExpression)* | |
352 | ||
353 | AdditiveExpression <- MultiplicativeExpression ((PLUS / MINUS) MultiplicativeExpression)* | |
354 | ||
355 | ShiftExpression <- AdditiveExpression ((LEFT / RIGHT) AdditiveExpression)* | |
356 | ||
357 | RelationalExpression <- ShiftExpression ((LE / GE / LT / GT) ShiftExpression)* | |
358 | ||
359 | EqualityExpression <- RelationalExpression ((EQUEQU / BANGEQU) RelationalExpression)* | |
360 | ||
361 | ANDExpression <- EqualityExpression (AND EqualityExpression)* | |
362 | ||
363 | ExclusiveORExpression <- ANDExpression (HAT ANDExpression)* | |
364 | ||
365 | InclusiveORExpression <- ExclusiveORExpression (OR ExclusiveORExpression)* | |
366 | ||
367 | LogicalANDExpression <- InclusiveORExpression (ANDAND InclusiveORExpression)* | |
368 | ||
369 | LogicalORExpression <- LogicalANDExpression (OROR LogicalANDExpression)* | |
370 | ||
371 | ConditionalExpression <- LogicalORExpression (QUERY Expression COLON LogicalORExpression)* | |
372 | ||
373 | AssignmentExpression | |
374 | <- UnaryExpression AssignmentOperator AssignmentExpression | |
375 | / ConditionalExpression | |
376 | ||
377 | AssignmentOperator | |
378 | <- EQU | |
379 | / STAREQU | |
380 | / DIVEQU | |
381 | / MODEQU | |
382 | / PLUSEQU | |
383 | / MINUSEQU | |
384 | / LEFTEQU | |
385 | / RIGHTEQU | |
386 | / ANDEQU | |
387 | / HATEQU | |
388 | / OREQU | |
389 | ||
390 | Expression <- AssignmentExpression (COMMA AssignmentExpression)* | |
391 | ||
392 | ConstantExpression <- ConditionalExpression | |
393 | ||
394 | ||
395 | #------------------------------------------------------------------------- | |
396 | # A.1.1 Lexical elements | |
397 | # Tokens are: Keyword, Identifier, Constant, StringLiteral, Punctuator. | |
398 | # Tokens are separated by Spacing. | |
399 | #------------------------------------------------------------------------- | |
400 | ||
401 | Spacing | |
402 | <- ( WhiteSpace | |
403 | / LongComment | |
404 | / LineComment | |
405 | / Pragma | |
406 | )* | |
407 | ||
408 | WhiteSpace <- [ \n\r\t] # 7.4.1.10 [\u000B\u000C] | |
409 | ||
410 | LongComment <- '/*' (!'*/'.)* '*/' # 6.4.9 | |
411 | ||
412 | LineComment <- '//' (!'\n' .)* # 6.4.9 | |
413 | ||
414 | Pragma <- '#' (!'\n' .)* # Treat pragma as comment | |
415 | ||
416 | ||
417 | #------------------------------------------------------------------------- | |
418 | # A.1.2 Keywords | |
419 | #------------------------------------------------------------------------- | |
420 | ||
421 | AUTO <- 'auto' !IdChar Spacing | |
422 | BREAK <- 'break' !IdChar Spacing | |
423 | CASE <- 'case' !IdChar Spacing | |
424 | CHAR <- 'char' !IdChar Spacing | |
425 | CONST <- 'const' !IdChar Spacing | |
426 | CONTINUE <- 'continue' !IdChar Spacing | |
427 | DEFAULT <- 'default' !IdChar Spacing | |
428 | DOUBLE <- 'double' !IdChar Spacing | |
429 | DO <- 'do' !IdChar Spacing | |
430 | ELSE <- 'else' !IdChar Spacing | |
431 | ENUM <- 'enum' !IdChar Spacing | |
432 | EXTERN <- 'extern' !IdChar Spacing | |
433 | FLOAT <- 'float' !IdChar Spacing | |
434 | FOR <- 'for' !IdChar Spacing | |
435 | GOTO <- 'goto' !IdChar Spacing | |
436 | IF <- 'if' !IdChar Spacing | |
437 | INT <- 'int' !IdChar Spacing | |
438 | INLINE <- 'inline' !IdChar Spacing | |
439 | LONG <- 'long' !IdChar Spacing | |
440 | REGISTER <- 'register' !IdChar Spacing | |
441 | RESTRICT <- 'restrict' !IdChar Spacing | |
442 | RETURN <- 'return' !IdChar Spacing | |
443 | SHORT <- 'short' !IdChar Spacing | |
444 | SIGNED <- 'signed' !IdChar Spacing | |
445 | SIZEOF <- 'sizeof' !IdChar Spacing | |
446 | STATIC <- 'static' !IdChar Spacing | |
447 | STRUCT <- 'struct' !IdChar Spacing | |
448 | SWITCH <- 'switch' !IdChar Spacing | |
449 | TYPEDEF <- 'typedef' !IdChar Spacing | |
450 | UNION <- 'union' !IdChar Spacing | |
451 | UNSIGNED <- 'unsigned' !IdChar Spacing | |
452 | VOID <- 'void' !IdChar Spacing | |
453 | VOLATILE <- 'volatile' !IdChar Spacing | |
454 | WHILE <- 'while' !IdChar Spacing | |
455 | BOOL <- '_Bool' !IdChar Spacing | |
456 | COMPLEX <- '_Complex' !IdChar Spacing | |
457 | STDCALL <- '_stdcall' !IdChar Spacing | |
458 | DECLSPEC <- '__declspec' !IdChar Spacing | |
459 | ATTRIBUTE <- '__attribute__' !IdChar Spacing | |
460 | ||
461 | Keyword | |
462 | <- ( 'auto' | |
463 | / 'break' | |
464 | / 'case' | |
465 | / 'char' | |
466 | / 'const' | |
467 | / 'continue' | |
468 | / 'default' | |
469 | / 'double' | |
470 | / 'do' | |
471 | / 'else' | |
472 | / 'enum' | |
473 | / 'extern' | |
474 | / 'float' | |
475 | / 'for' | |
476 | / 'goto' | |
477 | / 'if' | |
478 | / 'int' | |
479 | / 'inline' | |
480 | / 'long' | |
481 | / 'register' | |
482 | / 'restrict' | |
483 | / 'return' | |
484 | / 'short' | |
485 | / 'signed' | |
486 | / 'sizeof' | |
487 | / 'static' | |
488 | / 'struct' | |
489 | / 'switch' | |
490 | / 'typedef' | |
491 | / 'union' | |
492 | / 'unsigned' | |
493 | / 'void' | |
494 | / 'volatile' | |
495 | / 'while' | |
496 | / '_Bool' | |
497 | / '_Complex' | |
498 | / '_Imaginary' | |
499 | / '_stdcall' | |
500 | / '__declspec' | |
501 | / '__attribute__' | |
502 | ) | |
503 | !IdChar | |
504 | ||
505 | ||
506 | #------------------------------------------------------------------------- | |
507 | # A.1.3 Identifiers | |
508 | # The standard does not explicitly state that identifiers must be | |
509 | # distinct from keywords, but it seems so. | |
510 | #------------------------------------------------------------------------- | |
511 | ||
512 | Identifier <- !Keyword IdNondigit IdChar* Spacing #{} | |
513 | ||
514 | IdNondigit | |
515 | <- [a-z] / [A-Z] / [_] | |
516 | / UniversalCharacter | |
517 | ||
518 | IdChar | |
519 | <- [a-z] / [A-Z] / [0-9] / [_] | |
520 | / UniversalCharacter | |
521 | ||
522 | ||
523 | #------------------------------------------------------------------------- | |
524 | # A.1.4 Universal character names | |
525 | #------------------------------------------------------------------------- | |
526 | ||
527 | UniversalCharacter | |
528 | <- '\\u' HexQuad | |
529 | / '\\U' HexQuad HexQuad | |
530 | ||
531 | HexQuad <- HexDigit HexDigit HexDigit HexDigit | |
532 | ||
533 | ||
534 | #------------------------------------------------------------------------- | |
535 | # A.1.5 Constants | |
536 | #------------------------------------------------------------------------- | |
537 | ||
538 | Constant | |
539 | <- FloatConstant | |
540 | / IntegerConstant # Note: can be a prefix of Float Constant! | |
541 | / EnumerationConstant | |
542 | / CharacterConstant | |
543 | ||
544 | IntegerConstant | |
545 | <- ( DecimalConstant | |
546 | / HexConstant | |
547 | / OctalConstant | |
548 | ) | |
549 | IntegerSuffix? Spacing | |
550 | ||
551 | DecimalConstant <- [1-9][0-9]* | |
552 | ||
553 | OctalConstant <- '0' [0-7]* | |
554 | ||
555 | HexConstant <- HexPrefix HexDigit+ | |
556 | ||
557 | HexPrefix <- '0x' / '0X' | |
558 | ||
559 | HexDigit <- [a-f] / [A-F] / [0-9] | |
560 | ||
561 | IntegerSuffix | |
562 | <- [uU] Lsuffix? | |
563 | / Lsuffix [uU]? | |
564 | ||
565 | Lsuffix | |
566 | <- 'll' | |
567 | / 'LL' | |
568 | / [lL] | |
569 | ||
570 | FloatConstant | |
571 | <- ( DecimalFloatConstant | |
572 | / HexFloatConstant | |
573 | ) | |
574 | FloatSuffix? Spacing | |
575 | ||
576 | DecimalFloatConstant | |
577 | <- Fraction Exponent? | |
578 | / [0-9]+ Exponent | |
579 | ||
580 | HexFloatConstant | |
581 | <- HexPrefix HexFraction BinaryExponent? | |
582 | / HexPrefix HexDigit+ BinaryExponent | |
583 | ||
584 | Fraction | |
585 | <- [0-9]* '.' [0-9]+ | |
586 | / [0-9]+ '.' | |
587 | ||
588 | HexFraction | |
589 | <- HexDigit* '.' HexDigit+ | |
590 | / HexDigit+ '.' | |
591 | ||
592 | Exponent <- [eE][+\-]? [0-9]+ | |
593 | ||
594 | BinaryExponent <- [pP][+\-]? [0-9]+ | |
595 | ||
596 | FloatSuffix <- [flFL] | |
597 | ||
598 | EnumerationConstant <- Identifier | |
599 | ||
600 | CharacterConstant <- 'L'? ['] Char* ['] Spacing | |
601 | ||
602 | Char <- Escape / !['\n\\] . | |
603 | ||
604 | Escape | |
605 | <- SimpleEscape | |
606 | / OctalEscape | |
607 | / HexEscape | |
608 | / UniversalCharacter | |
609 | ||
610 | SimpleEscape <- '\\' ['\"?\\abfnrtv] | |
611 | OctalEscape <- '\\' [0-7][0-7]?[0-7]? | |
612 | HexEscape <- '\\x' HexDigit+ | |
613 | ||
614 | ||
615 | #------------------------------------------------------------------------- | |
616 | # A.1.6 String Literals | |
617 | #------------------------------------------------------------------------- | |
618 | ||
619 | StringLiteral <- 'L'? (["] StringChar* ["] Spacing)+ | |
620 | ||
621 | StringChar <- Escape / ![\"\n\\] . | |
622 | ||
623 | ||
624 | #------------------------------------------------------------------------- | |
625 | # A.1.7 Punctuators | |
626 | #------------------------------------------------------------------------- | |
627 | ||
628 | LBRK <- '[' Spacing | |
629 | RBRK <- ']' Spacing | |
630 | LPAR <- '(' Spacing | |
631 | RPAR <- ')' Spacing | |
632 | LWING <- '{' Spacing | |
633 | RWING <- '}' Spacing | |
634 | DOT <- '.' Spacing | |
635 | PTR <- '->' Spacing | |
636 | INC <- '++' Spacing | |
637 | DEC <- '--' Spacing | |
638 | AND <- '&' ![&] Spacing | |
639 | STAR <- '*' ![=] Spacing | |
640 | PLUS <- '+' ![+=] Spacing | |
641 | MINUS <- '-' ![\-=>] Spacing | |
642 | TILDA <- '~' Spacing | |
643 | BANG <- '!' ![=] Spacing | |
644 | DIV <- '/' ![=] Spacing | |
645 | MOD <- '%' ![=>] Spacing | |
646 | LEFT <- '<<' ![=] Spacing | |
647 | RIGHT <- '>>' ![=] Spacing | |
648 | LT <- '<' ![=] Spacing | |
649 | GT <- '>' ![=] Spacing | |
650 | LE <- '<=' Spacing | |
651 | GE <- '>=' Spacing | |
652 | EQUEQU <- '==' Spacing | |
653 | BANGEQU <- '!=' Spacing | |
654 | HAT <- '^' ![=] Spacing | |
655 | OR <- '|' ![=] Spacing | |
656 | ANDAND <- '&&' Spacing | |
657 | OROR <- '||' Spacing | |
658 | QUERY <- '?' Spacing | |
659 | COLON <- ':' ![>] Spacing | |
660 | SEMI <- ';' Spacing | |
661 | ELLIPSIS <- '...' Spacing | |
662 | EQU <- '=' !"=" Spacing | |
663 | STAREQU <- '*=' Spacing | |
664 | DIVEQU <- '/=' Spacing | |
665 | MODEQU <- '%=' Spacing | |
666 | PLUSEQU <- '+=' Spacing | |
667 | MINUSEQU <- '-=' Spacing | |
668 | LEFTEQU <- '<<=' Spacing | |
669 | RIGHTEQU <- '>>=' Spacing | |
670 | ANDEQU <- '&=' Spacing | |
671 | HATEQU <- '^=' Spacing | |
672 | OREQU <- '|=' Spacing | |
673 | COMMA <- ',' Spacing | |
674 | ||
675 | EOT <- !. |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "fmt" | |
8 | "io/ioutil" | |
9 | "log" | |
10 | "os" | |
11 | "strings" | |
12 | ) | |
13 | ||
14 | func main() { | |
15 | if len(os.Args) < 2 { | |
16 | fmt.Printf("%v FILE\n", os.Args[0]) | |
17 | os.Exit(1) | |
18 | } | |
19 | ||
20 | var walk func(name string) | |
21 | walk = func(name string) { | |
22 | fileInfo, err := os.Stat(name) | |
23 | if err != nil { | |
24 | log.Fatal(err) | |
25 | } | |
26 | ||
27 | if fileInfo.Mode() & (os.ModeNamedPipe | os.ModeSocket | os.ModeDevice) != 0 { | |
28 | /* will lock up if opened */ | |
29 | } else if fileInfo.IsDir() { | |
30 | fmt.Printf("directory %v\n", name) | |
31 | ||
32 | file, err := os.Open(name) | |
33 | if err != nil { | |
34 | log.Fatal(err) | |
35 | } | |
36 | ||
37 | files, err := file.Readdir(-1) | |
38 | if err != nil { | |
39 | log.Fatal(err) | |
40 | } | |
41 | file.Close() | |
42 | ||
43 | for _, f := range files { | |
44 | if !strings.HasSuffix(name, "/") { | |
45 | name += "/" | |
46 | } | |
47 | walk(name + f.Name()) | |
48 | } | |
49 | } else if strings.HasSuffix(name, ".c") { | |
50 | fmt.Printf("parse %v\n", name) | |
51 | ||
52 | file, err := os.Open(name) | |
53 | if err != nil { | |
54 | log.Fatal(err) | |
55 | } | |
56 | ||
57 | buffer, err := ioutil.ReadAll(file) | |
58 | if err != nil { | |
59 | log.Fatal(err) | |
60 | } | |
61 | file.Close() | |
62 | ||
63 | clang := &C{Buffer: string(buffer)} | |
64 | clang.Init() | |
65 | if err := clang.Parse(); err != nil { | |
66 | log.Fatal(err) | |
67 | } | |
68 | } | |
69 | } | |
70 | walk(os.Args[1]) | |
71 | } |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | calculator: calculator.peg.go calculator.go main.go | |
5 | go build | |
6 | ||
7 | calculator.peg.go: calculator.peg | |
8 | ../../peg -switch -inline calculator.peg | |
9 | ||
10 | clean: | |
11 | rm -f calculator calculator.peg.go |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "math/big" | |
8 | ) | |
9 | ||
10 | type Type uint8 | |
11 | ||
12 | const ( | |
13 | TypeNumber Type = iota | |
14 | TypeNegation | |
15 | TypeAdd | |
16 | TypeSubtract | |
17 | TypeMultiply | |
18 | TypeDivide | |
19 | TypeModulus | |
20 | TypeExponentiation | |
21 | ) | |
22 | ||
23 | type ByteCode struct { | |
24 | T Type | |
25 | Value *big.Int | |
26 | } | |
27 | ||
28 | func (code *ByteCode) String() string { | |
29 | switch code.T { | |
30 | case TypeNumber: | |
31 | return code.Value.String() | |
32 | case TypeAdd: | |
33 | return "+" | |
34 | case TypeNegation, TypeSubtract: | |
35 | return "-" | |
36 | case TypeMultiply: | |
37 | return "*" | |
38 | case TypeDivide: | |
39 | return "/" | |
40 | case TypeModulus: | |
41 | return "%" | |
42 | case TypeExponentiation: | |
43 | return "^" | |
44 | } | |
45 | return "" | |
46 | } | |
47 | ||
48 | type Expression struct { | |
49 | Code []ByteCode | |
50 | Top int | |
51 | } | |
52 | ||
53 | func (e *Expression) Init(expression string) { | |
54 | e.Code = make([]ByteCode, len(expression)) | |
55 | } | |
56 | ||
57 | func (e *Expression) AddOperator(operator Type) { | |
58 | code, top := e.Code, e.Top | |
59 | e.Top++ | |
60 | code[top].T = operator | |
61 | } | |
62 | ||
63 | func (e *Expression) AddValue(value string) { | |
64 | code, top := e.Code, e.Top | |
65 | e.Top++ | |
66 | code[top].Value = new(big.Int) | |
67 | code[top].Value.SetString(value, 10) | |
68 | } | |
69 | ||
70 | func (e *Expression) Evaluate() *big.Int { | |
71 | stack, top := make([]big.Int, len(e.Code)), 0 | |
72 | for _, code := range e.Code[0:e.Top] { | |
73 | switch code.T { | |
74 | case TypeNumber: | |
75 | stack[top].Set(code.Value) | |
76 | top++ | |
77 | continue | |
78 | case TypeNegation: | |
79 | a := &stack[top-1] | |
80 | a.Neg(a) | |
81 | continue | |
82 | } | |
83 | a, b := &stack[top-2], &stack[top-1] | |
84 | top-- | |
85 | switch code.T { | |
86 | case TypeAdd: | |
87 | a.Add(a, b) | |
88 | case TypeSubtract: | |
89 | a.Sub(a, b) | |
90 | case TypeMultiply: | |
91 | a.Mul(a, b) | |
92 | case TypeDivide: | |
93 | a.Div(a, b) | |
94 | case TypeModulus: | |
95 | a.Mod(a, b) | |
96 | case TypeExponentiation: | |
97 | a.Exp(a, b, nil) | |
98 | } | |
99 | } | |
100 | return &stack[0] | |
101 | } |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | type Calculator Peg { | |
7 | Expression | |
8 | } | |
9 | ||
10 | e <- sp e1 !. | |
11 | e1 <- e2 ( add e2 { p.AddOperator(TypeAdd) } | |
12 | / minus e2 { p.AddOperator(TypeSubtract) } | |
13 | )* | |
14 | e2 <- e3 ( multiply e3 { p.AddOperator(TypeMultiply) } | |
15 | / divide e3 { p.AddOperator(TypeDivide) } | |
16 | / modulus e3 { p.AddOperator(TypeModulus) } | |
17 | )* | |
18 | e3 <- e4 ( exponentiation e4 { p.AddOperator(TypeExponentiation) } | |
19 | )* | |
20 | e4 <- minus value { p.AddOperator(TypeNegation) } | |
21 | / value | |
22 | value <- < [0-9]+ > sp { p.AddValue(buffer[begin:end]) } | |
23 | / open e1 close | |
24 | add <- '+' sp | |
25 | minus <- '-' sp | |
26 | multiply <- '*' sp | |
27 | divide <- '/' sp | |
28 | modulus <- '%' sp | |
29 | exponentiation <- '^' sp | |
30 | open <- '(' sp | |
31 | close <- ')' sp | |
32 | sp <- ( ' ' / '\t' )* |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "fmt" | |
8 | "log" | |
9 | "os" | |
10 | ) | |
11 | ||
12 | func main() { | |
13 | if len(os.Args) < 2 { | |
14 | name := os.Args[0] | |
15 | fmt.Printf("Usage: %v \"EXPRESSION\"\n", name) | |
16 | fmt.Printf("Example: %v \"( 1 - -3 ) / 3 + 2 * ( 3 + -4 ) + 3 %% 2^2\"\n =2\n", name) | |
17 | os.Exit(1) | |
18 | } | |
19 | expression := os.Args[1] | |
20 | calc := &Calculator{Buffer: expression} | |
21 | calc.Init() | |
22 | calc.Expression.Init(expression) | |
23 | if err := calc.Parse(); err != nil { | |
24 | log.Fatal(err) | |
25 | } | |
26 | calc.Execute() | |
27 | fmt.Printf("= %v\n", calc.Evaluate()) | |
28 | } |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | fexl: fexl.peg.go main.go | |
5 | go build | |
6 | ||
7 | fexl.peg.go: fexl.peg | |
8 | ../../peg -switch -inline fexl.peg | |
9 | ||
10 | clean: | |
11 | rm -f fexl fexl.peg.go |
0 | Copyright 2011 Patrick Chkoreff | |
1 | ||
2 | Licensed under the Apache License, Version 2.0 (the "License"); | |
3 | you may not use this file except in compliance with the License. | |
4 | You may obtain a copy of the License at | |
5 | ||
6 | http://www.apache.org/licenses/LICENSE-2.0 | |
7 | ||
8 | Unless required by applicable law or agreed to in writing, software | |
9 | distributed under the License is distributed on an "AS IS" BASIS, | |
10 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
11 | See the License for the specific language governing permissions | |
12 | and limitations under the License. |
0 | Fexl (Function EXpression Language) http://fexl.com | |
1 | ||
2 | AUTHOR | |
3 | ||
4 | Patrick Chkoreff wrote this software. Please see the NOTICE file for terms of | |
5 | use. | |
6 | ||
7 | ||
8 | CREDITS | |
9 | ||
10 | I thank Moses Schönfinkel, who in 1924 wrote a paper titled "On the building | |
11 | blocks of mathematical logic". I found this paper in "From Frege to Gödel, A | |
12 | Source Book in Mathematical Logic, 1879-1931". | |
13 | ||
14 | Mr. Schönfinkel observes that all computable functions can be defined in terms | |
15 | of just two primitive functions C and S applied together in various | |
16 | combinations. This is a profound and magnificent insight for which I am very | |
17 | grateful. | |
18 | ||
19 | The C function is governed by the rule ((C x) y) = x. This is known as the | |
20 | "constancy function", or "Konstanzfunktion" in the original German. | |
21 | ||
22 | The S function is governed by the rule (((S x) y) z) = ((x z) (y z)). This is | |
23 | known as the "fusion function", or "Verschmelzungfunktion" in the original | |
24 | German. | |
25 | ||
26 | I also thank Jørgen Steensgaard-Madsen, who in 1989 wrote a paper titled | |
27 | "Typed Representation of Objects by Functions". I found this paper in the | |
28 | "ACM Transactions on Programming Languages and Systems, January 1989, Volume | |
29 | 11 Number 1". | |
30 | ||
31 | Mr. Steensgaard-Madsen observes that all of what we ordinarily understand as | |
32 | "data" can be represented as pure functions. Even a piece of data as humble | |
33 | as a single bit is in essence just a function. | |
34 | ||
35 | ||
36 | HOW TO INSTALL | |
37 | ||
38 | Go into the source code directory and run this command: | |
39 | ||
40 | ./build install | |
41 | ||
42 | You may be prompted for your sudo (superuser) password. | |
43 | ||
44 | That builds the program locally in ../bin, then copies it to the /usr/bin | |
45 | directory. If you need to install it in a different place, change the | |
46 | install_location variable inside the build script. | |
47 | ||
48 | ||
49 | HOW TO BUILD LOCALLY | |
50 | ||
51 | If you wish to enhance or test the program, you might prefer to build it | |
52 | locally in the ../bin directory and run it from there, without installing into | |
53 | /usr/bin. You do that with this command: | |
54 | ||
55 | ./build | |
56 | ||
57 | ||
58 | HOW TO RUN | |
59 | ||
60 | To run a fexl program which is read from standard input: | |
61 | ||
62 | fexl | |
63 | ||
64 | To run a fexl program which is read from a file named "script": | |
65 | ||
66 | fexl script | |
67 | ||
68 | You may also use the "shebang" method to create an executable fexl file. For | |
69 | example, create a file named "script" and put this on the first line: | |
70 | ||
71 | #!/usr/bin/fexl | |
72 | ||
73 | Then make your script executable with: | |
74 | ||
75 | chmod +x script | |
76 | ||
77 | Now you can run your script directly this way: | |
78 | ||
79 | ./script |
0 | #!../bin/fexl | |
1 | # ^^^ use that line for the locally built version | |
2 | ||
3 | #!/usr/bin/fexl | |
4 | # ^^^ use that line for the installed version | |
5 | ||
6 | ||
7 | # NOTE: If you run ./try.fxl, it will go through a bunch of tests, including | |
8 | # one at the end where it asks you to type lines of text and terminate with | |
9 | # Ctrl-D. If you'd like to run the test without having to type anything, and | |
10 | # compare it with the reference output, do this: | |
11 | # | |
12 | # cat try.fxl | ../bin/fexl | cmp - out | |
13 | # | |
14 | # That should run quietly with exit code 0. | |
15 | ||
16 | ||
17 | ##### | |
18 | ||
19 | # This function halts by simply consuming all arguments given to it. | |
20 | \halt == (\_ halt) | |
21 | ||
22 | # Useful: | |
23 | \string_from = (\x | |
24 | string_type x x; | |
25 | long_type x (long_string x); | |
26 | double_type x (double_string x); | |
27 | x) | |
28 | ||
29 | \print = (\item string_put (string_from item)) | |
30 | \nl = (print " | |
31 | ") | |
32 | ||
33 | \T = (\T\F T) | |
34 | \F = (\T\F F) | |
35 | ||
36 | \string_eq=(\x\y string_compare x y F T F) | |
37 | ||
38 | \long_le = (\x\y long_compare x y T T F) | |
39 | \long_lt = (\x\y long_compare x y T F F) | |
40 | \long_ge = (\x\y long_compare x y F T T) | |
41 | \long_gt = (\x\y long_compare x y F F T) | |
42 | \long_ne = (\x\y long_compare x y T F T) | |
43 | \long_min = (\x\y long_compare x y x x y) | |
44 | ||
45 | ### List functions | |
46 | ||
47 | # "end" is the empty list. | |
48 | \end = (\end\item end) | |
49 | ||
50 | # The "item" (cons) list constructor is built-in, but could be defined thus: | |
51 | # \item = (\head\tail \end\item item head tail) | |
52 | ||
53 | # Return the first N items of the list. | |
54 | \list_prefix == (\list\N | |
55 | long_le N 0 end; | |
56 | list end \head\tail | |
57 | \N = (long_sub N 1) | |
58 | item head; list_prefix tail N | |
59 | ) | |
60 | ||
61 | # Return the item at position N in the list, or default if no such item. | |
62 | \list_at == (\list\N\default | |
63 | list default \head\tail | |
64 | long_compare N 0 default head | |
65 | \N = (long_sub N 1) | |
66 | list_at tail N default | |
67 | ) | |
68 | ||
69 | \list_map == (\next\fun\list | |
70 | list next \head\tail fun head; list_map next fun tail) | |
71 | ||
72 | \list_do = (list_map I) | |
73 | ||
74 | \list_print = (\fun list_do \x string_put; fun x) | |
75 | ||
76 | # We don't use char_put because of buffering problems. | |
77 | \chars_print = (list_print long_char) | |
78 | ||
79 | \bits_print = (list_print \x x "1" "0") | |
80 | ||
81 | # Reverse a list. | |
82 | \reverse=(\list | |
83 | \reverse==(\list\result list result \h\t reverse t (item h result)) | |
84 | reverse list end | |
85 | ) | |
86 | ||
87 | ######## | |
88 | ||
89 | \test_hello_world== | |
90 | ( | |
91 | print "hello world" nl; | |
92 | ) | |
93 | ||
94 | ######## | |
95 | ||
96 | \test_cat== | |
97 | ( | |
98 | print "=== Enter lines of text and I'll echo them. Press Ctrl-D to stop";nl; | |
99 | ||
100 | \long_lt = (\x\y long_compare x y T F F) | |
101 | ||
102 | # The cat program echoes the input to the output. | |
103 | \cat == (char_get \ch long_lt ch 0 I; char_put ch; cat) | |
104 | cat | |
105 | ) | |
106 | ||
107 | ######## | |
108 | ||
109 | \test_string_slice== | |
110 | ( | |
111 | print (string_slice "abcde" 0 1); nl; | |
112 | print (string_slice "abcde" 0 2); nl; | |
113 | print (string_slice "abcde" 0 3); nl; | |
114 | print (string_slice "abcde" 0 4); nl; | |
115 | print (string_slice "abcde" 0 5); nl; | |
116 | print (string_slice "abcde" 0 6); nl; | |
117 | print (string_slice "abcde" 0 700); nl; | |
118 | print (string_slice "a" 0 0); nl; | |
119 | print (string_slice "a" 0 1); nl; | |
120 | print (string_slice "a" 0 2); nl; | |
121 | print (string_slice "a" -1 0); nl; | |
122 | print "=====";nl; | |
123 | print (string_slice "a" 0 1); nl; | |
124 | print (string_slice "a" -1 2); nl; | |
125 | print (string_slice "a" -2 3); nl; | |
126 | print (string_slice "a" -2 4); nl; | |
127 | print (string_slice "a" -2 0); nl; | |
128 | print (string_slice "abcde" 0 5); nl; | |
129 | print (string_slice "abcde" -1 5); nl; | |
130 | print (string_slice "abcde" -2 5); nl; | |
131 | print (string_slice "abcde" -3 5); nl; | |
132 | print (string_slice "abcde" -4 5); nl; | |
133 | print (string_slice "abcde" -5 5); nl; | |
134 | print (string_slice "abcde" -5 6); nl; | |
135 | print (string_slice "abcde" -5 7); nl; | |
136 | print (string_slice "abcde" -5 8); nl; | |
137 | print (string_slice "abcde" -5 9); nl; | |
138 | print (string_slice "abcde" -5 10); nl; | |
139 | print (string_slice "abcde" -5 11); nl; | |
140 | print "=====";nl; | |
141 | print (string_slice "" 0 0); nl; | |
142 | print (string_slice "" 0 800); nl; | |
143 | print (string_slice "" -30 800); nl; | |
144 | #string_put (string_from (string_slice "a" 0 1));nl; | |
145 | #string_put (string_from (string_slice "a" 0 1));nl; | |
146 | #string_put (string_from (string_slice "a" 0 1));nl; | |
147 | #string_put (string_from (string_slice "a" 0 1));nl; | |
148 | ||
149 | #string_put (string_slice "a" 0 0) | |
150 | ) | |
151 | ||
152 | ######## | |
153 | ||
154 | \test_write_binary == | |
155 | ( | |
156 | # Writing binary | |
157 | ||
158 | \string_3014 = | |
159 | ( | |
160 | string_append (long_char 03); | |
161 | string_append (long_char 00); | |
162 | string_append (long_char 01); | |
163 | string_append (long_char 04); | |
164 | "" | |
165 | ) | |
166 | ||
167 | string_put string_3014; | |
168 | ) | |
169 | ||
170 | ######## | |
171 | ||
172 | \test_string_len== | |
173 | ( | |
174 | print (string_len ""); nl; | |
175 | print (string_len "a"); nl; | |
176 | print (string_len "ab"); nl; | |
177 | print (string_len "12345678901234567890123456789012"); nl; | |
178 | ) | |
179 | ||
180 | ######## | |
181 | ||
182 | \test_string_at== | |
183 | ( | |
184 | print (string_at "abc" -1); nl; | |
185 | print (string_at "abc" 0); nl; | |
186 | print (string_at "abc" 1); nl; | |
187 | print (string_at "abc" 2); nl; | |
188 | print (string_at "abc" 3); nl; | |
189 | ) | |
190 | ||
191 | ######## | |
192 | ||
193 | \test_string_compare== | |
194 | ( | |
195 | \string_014 = | |
196 | ( | |
197 | string_append (long_char 00); | |
198 | string_append (long_char 01); | |
199 | string_append (long_char 04); | |
200 | "" | |
201 | ) | |
202 | ||
203 | \string_041 = | |
204 | ( | |
205 | string_append (long_char 00); | |
206 | string_append (long_char 04); | |
207 | string_append (long_char 01); | |
208 | "" | |
209 | ) | |
210 | ||
211 | \string_0142 = (string_append string_014; long_char 02); | |
212 | ||
213 | \do_compare=(\x\y\expect | |
214 | \result = (string_compare x y "LT" "EQ" "GT") | |
215 | print "string_compare "; print x; print " "; print y; print " "; | |
216 | print result; print " "; | |
217 | print (string_eq result expect "GOOD" "BAD"); | |
218 | nl; | |
219 | ) | |
220 | ||
221 | do_compare string_0142 string_014 "GT"; | |
222 | do_compare string_014 string_0142 "LT"; | |
223 | do_compare string_014 string_014 "EQ"; | |
224 | do_compare string_014 string_041 "LT"; | |
225 | do_compare string_041 string_014 "GT"; | |
226 | do_compare string_041 string_0142 "GT"; | |
227 | ) | |
228 | ||
229 | ######## | |
230 | \test_string_common == | |
231 | ( | |
232 | \string_eq=(\x\y string_compare x y F T F) | |
233 | \long_eq=(\x\y long_compare x y F T F) | |
234 | ||
235 | \check = (\value\expect | |
236 | \halt == (\_ halt) | |
237 | \ok = (long_eq value expect) | |
238 | print " "; print (ok "GOOD" "BAD");nl; | |
239 | ok I halt | |
240 | ) | |
241 | ||
242 | \test_string_common = (\x\y\expect | |
243 | \len = (string_common x y) | |
244 | print "string_common ";print x; print " "; print y; print " = "; print len; | |
245 | check len expect; | |
246 | ) | |
247 | ||
248 | test_string_common "" "" 0; | |
249 | test_string_common "" "a" 0; | |
250 | test_string_common "a" "a" 1; | |
251 | test_string_common "a" "ab" 1; | |
252 | test_string_common "ab" "a" 1; | |
253 | test_string_common "ab" "ab" 2; | |
254 | test_string_common "abc" "abd" 2; | |
255 | test_string_common "aac" "abd" 1; | |
256 | test_string_common "abd" "abd" 3; | |
257 | test_string_common "cbd" "abd" 0; | |
258 | test_string_common "x" "" 0; | |
259 | ) | |
260 | ||
261 | ######## | |
262 | ||
263 | \test_long_add== | |
264 | ( | |
265 | \x=(long_add 37 23) | |
266 | print "The value of x is "; print x; print "."; nl; | |
267 | ) | |
268 | ||
269 | ######## | |
270 | \test_procedural== | |
271 | ( | |
272 | # Make some abbreviations. | |
273 | \add=double_add | |
274 | \sub=double_sub | |
275 | \mul=double_mul | |
276 | \div=double_div | |
277 | ||
278 | ||
279 | print ~@ | |
280 | === | |
281 | Here we demonstrate an ordinary "procedural" style of programming. This works | |
282 | because definitions are NOT recursive by default. If you want a recursive | |
283 | definition, you must use "==" instead of just "=". | |
284 | ||
285 | @; | |
286 | ||
287 | \show=(\name\value print name; print " = "; print value; nl;) | |
288 | ||
289 | \x=3.0 | |
290 | \y=4.0 | |
291 | \x=(add x x) | |
292 | \y=(mul y x) | |
293 | show "x" x; show "y" y; | |
294 | \x=(div x; mul y 4.0) | |
295 | show "x" x; show "y" y; | |
296 | ||
297 | \z=(mul x; mul y; add 1.0 y) | |
298 | show "x" x; show "y" y; show "z" z; | |
299 | \z=(div z 5.0) | |
300 | show "z" z; | |
301 | ) | |
302 | ||
303 | \test_eager== | |
304 | ( | |
305 | \long_le = (\x\y long_compare x y T T F) | |
306 | ||
307 | \sum == (\total\count | |
308 | long_le count 0 total; | |
309 | ||
310 | # This form evaluates eagerly: | |
311 | \total = (long_add total count) | |
312 | ||
313 | # Or if you prefer, you can use "?" to force eager evaluation like this: | |
314 | #? (long_add total count) \total | |
315 | ||
316 | sum total (long_sub count 1)) | |
317 | ||
318 | \sum = (sum 0) | |
319 | ||
320 | \count = 100000 | |
321 | print "The sum of 1 .. ";print count; print " is "; print (sum count);nl; | |
322 | ) | |
323 | ||
324 | \test_double_compare == | |
325 | ( | |
326 | \do_compare=(\x\y\expect | |
327 | \result = (double_compare x y "LT" "EQ" "GT") | |
328 | print "double_compare "; print x; print " "; print y; print " "; | |
329 | print result; print " "; | |
330 | print (string_eq result expect "GOOD" "BAD"); | |
331 | nl; | |
332 | ) | |
333 | do_compare 23.0 23.0 "EQ" | |
334 | do_compare 23.0 24.0 "LT" | |
335 | do_compare 23.1 23.2 "LT" | |
336 | do_compare 24.0 23.0 "GT" | |
337 | do_compare 24.0 240.0 "LT" | |
338 | do_compare -1.0 4.0 "LT" | |
339 | do_compare 4.0 -1.0 "GT" | |
340 | do_compare -1.0 -1.0 "EQ" | |
341 | ) | |
342 | ||
343 | ####### Some tests with arbitrary precision arithmetic. | |
344 | ||
345 | \module_test_arithmetic == | |
346 | ( | |
347 | ||
348 | # These put a binary digit 0 or 1 on the front of a list. | |
349 | \d0 = (item F) | |
350 | \d1 = (item T) | |
351 | ||
352 | # the natural numbers 0 and 1 | |
353 | \nat_0 = end | |
354 | \nat_1 = (d1 nat_0) | |
355 | ||
356 | # (nat_2x x) is twice x. | |
357 | \nat_2x=(\x x nat_0 \_\_ d0 x) | |
358 | ||
359 | # (nat_2x1 x) is twice x plus 1. | |
360 | \nat_2x1=d1 | |
361 | ||
362 | # (nat_eq0 x) is true iff x = 0 | |
363 | \nat_eq0=(\x x T \_\_ F) | |
364 | ||
365 | # (nat_inc x) is x+1. (x incremented by 1). Both x and the result are of | |
366 | # type nat. | |
367 | \nat_inc==(\x x nat_1 \b\n b (d0; nat_inc n) (d1 n)) | |
368 | ||
369 | # (nat_dec x) is x-1 if x > 0, or 0 if x = 0. (x decremented by 1) Both x | |
370 | # and the result are of type nat. | |
371 | \nat_dec==(\x x nat_0 \b\n b (nat_eq0 n nat_0 (d0 n)) (d1; nat_dec n)) | |
372 | ||
373 | # (nat_add x y) is x+y. (the sum of x and y) The x, y, and result are of | |
374 | # type nat. | |
375 | \nat_add == (\x\y x y \bx\nx y x \by\ny | |
376 | \sum=(nat_add nx ny) | |
377 | bx | |
378 | (by (d0; nat_inc sum) (d1 sum)) | |
379 | (item by sum) | |
380 | ) | |
381 | ||
382 | # (nat_mul x y) is x*y. (the product of x and y) The x, y, and result are | |
383 | # of type nat. | |
384 | \nat_mul == (\x\y x nat_0 \bx\nx y nat_0 \by\ny | |
385 | bx | |
386 | (by (d1; nat_add nx (nat_mul ny x)) (d0; nat_mul ny x)) | |
387 | (by (d0; nat_mul nx y) (d0; d0; nat_mul nx ny)) | |
388 | ) | |
389 | ||
390 | # (int_ge0 x) is true if int x >= 0. | |
391 | \int_ge0=(\x x T \s\_ s) | |
392 | ||
393 | # (int_abs x) is the absolute value of int x. The result is a nat. | |
394 | \int_abs=(\x x nat_0 \_\n n) | |
395 | ||
396 | \int_0 = end | |
397 | \int_1 = (d1; d1; int_0) | |
398 | ||
399 | # (nat_int x) is nat x converted to the int +x. | |
400 | \nat_int=(\x nat_eq0 x int_0; d1 x) | |
401 | # (nat_neg x) is nat x converted to the int -x. | |
402 | \nat_neg=(\x nat_eq0 x int_0; d0 x) | |
403 | ||
404 | # (int_2x x) is twice x. | |
405 | \int_2x=(\x x int_0 \b\n item b; d0; n) | |
406 | ||
407 | # (int_inc x) is int x+1. | |
408 | \int_inc=(\x x int_1 \b\n b (d1; nat_inc n) (nat_neg (nat_dec n))) | |
409 | ||
410 | # (int_dec x) is int x-1. | |
411 | \int_dec=(\x x (d0; nat_1) \b\n b (nat_int (nat_dec n)) (d0; nat_inc n)) | |
412 | ||
413 | # (nat_sub x y) is x-y. (x minus y) The x, y are of type nat, but the | |
414 | # result is of type int because the result might be negative. | |
415 | \nat_sub==(\x\y x (nat_neg y) \bx\nx y (nat_int x) \by\ny | |
416 | \z = (int_2x (nat_sub nx ny)) | |
417 | bx (by I int_inc) (by int_dec I) z | |
418 | ) | |
419 | ||
420 | # (nat_div x y) divides x by y. It yields a pair <q,r>, where q is the | |
421 | # quotient and r is the remainder. | |
422 | # | |
423 | # The result satisfies the equation x = q*y + r, 0 <= r < y. | |
424 | # | |
425 | # NOTE: If you divide by zero, the function yields the pair <0,0>. | |
426 | ||
427 | \nat_div==(\x\y\return | |
428 | x (return nat_0 nat_0) \bx\nx | |
429 | y (return nat_0 nat_0) \by\ny | |
430 | by | |
431 | ( | |
432 | # divide by odd | |
433 | nat_div nx y \q\r | |
434 | \r=(bx nat_2x1 nat_2x r) | |
435 | \d=(nat_sub r y) | |
436 | int_ge0 d | |
437 | (return (nat_2x1 q) (int_abs d)) | |
438 | (return (nat_2x q) r) | |
439 | ) | |
440 | ( | |
441 | # divide by even | |
442 | nat_div nx ny \q\r | |
443 | return q (bx nat_2x1 nat_2x r) | |
444 | ) | |
445 | ) | |
446 | ||
447 | \nat_compare == (\x\y \lt\eq\gt | |
448 | x (y eq \_\_ lt) \bx\nx | |
449 | y gt \by\ny | |
450 | nat_compare nx ny | |
451 | lt | |
452 | (bx (by eq gt) (by lt eq)) | |
453 | gt | |
454 | ) | |
455 | ||
456 | \nat_le = (\x\y nat_compare x y T T F) | |
457 | \nat_ge = (\x\y nat_compare x y F T T) | |
458 | ||
459 | \nat_2 = (d0 nat_1) | |
460 | \nat_5 = (d1 nat_2) | |
461 | \nat_10 = (d0 nat_5) | |
462 | ||
463 | \nat_div10 = (\x nat_div x nat_10) | |
464 | ||
465 | # Convert a nat into a machine long value, ignoring any overflow. | |
466 | \nat_long = | |
467 | ( | |
468 | \nat_long == (\sum\pow\bits | |
469 | bits sum \bit\bits | |
470 | \sum = (bit (long_add pow) I sum) | |
471 | \pow = (long_mul 2 pow) | |
472 | nat_long sum pow bits | |
473 | ) | |
474 | ||
475 | nat_long 0 1 | |
476 | ) | |
477 | ||
478 | # (nat_base_10_lo n) is the list of ASCII decimal digits for n starting | |
479 | # with the least significant digit. | |
480 | \nat_base_10_lo == (\x | |
481 | nat_div10 x \q\r | |
482 | \ch = (long_add 48; nat_long r); | |
483 | item ch; | |
484 | nat_eq0 q end; | |
485 | nat_base_10_lo q | |
486 | ) | |
487 | ||
488 | # (nat_base_10 n) is the list of ASCII decimal digits for n starting | |
489 | # with the most significant digit. | |
490 | \nat_base_10=(\n reverse; nat_base_10_lo n) | |
491 | ||
492 | \nat_print = (\x chars_print (nat_base_10 x)) | |
493 | \nat_print_lo = (\x chars_print (nat_base_10_lo x)) | |
494 | ||
495 | # for testing: | |
496 | # show in reverse decimal | |
497 | #\nat_print = nat_print_lo | |
498 | # show in binary | |
499 | #\nat_print = bits_print | |
500 | ||
501 | \int_base_10 = (\x | |
502 | int_ge0 x | |
503 | (nat_base_10; int_abs x) | |
504 | (item 45; nat_base_10; int_abs x) | |
505 | ) | |
506 | ||
507 | \int_print = (\x chars_print (int_base_10 x)) | |
508 | ||
509 | # LATER maybe char constants? e.g. '0' == 48 '-' == 45 | |
510 | # This would be handled in the standard resolution context. It would not be | |
511 | # part of the grammar. The symbol "'0'" would simply be resolved to the long | |
512 | # value 48. | |
513 | ||
514 | ###### | |
515 | ||
516 | \nat_2 = (d0 nat_1) | |
517 | \nat_3 = (d1 nat_1) | |
518 | \nat_4 = (d0 nat_2) | |
519 | \nat_5 = (d1 nat_2) | |
520 | \nat_6 = (d0 nat_3) | |
521 | \nat_7 = (d1 nat_3) | |
522 | \nat_8 = (d0 nat_4) | |
523 | \nat_9 = (d1 nat_4) | |
524 | \nat_10 = (d0 nat_5) | |
525 | \nat_11 = (d1 nat_5) | |
526 | \nat_12 = (d0 nat_6) | |
527 | \nat_13 = (d1 nat_6) | |
528 | \nat_14 = (d0 nat_7) | |
529 | \nat_15 = (d1 nat_7) | |
530 | \nat_16 = (d0 nat_8) | |
531 | \nat_17 = (d1 nat_8) | |
532 | \nat_18 = (d0 nat_9) | |
533 | \nat_19 = (d1 nat_9) | |
534 | \nat_32 = (d0 nat_16) | |
535 | \nat_20 = (d0 nat_10) | |
536 | \nat_24 = (d0 nat_12) | |
537 | \nat_31 = (d1 nat_15) | |
538 | \nat_48 = (d0 nat_24) | |
539 | \nat_49 = (d1 nat_24) | |
540 | ||
541 | #### | |
542 | ||
543 | \test_fibonacci == | |
544 | ( | |
545 | ||
546 | # This lets you use either built-in arithmetic or arbitrary-precision | |
547 | # arithmetic. | |
548 | ||
549 | \test_case == | |
550 | ( | |
551 | \if_show_all | |
552 | \number_type | |
553 | \num_rounds | |
554 | ||
555 | if_show_all | |
556 | ( | |
557 | print "Print the first ";print num_rounds; print " Fibonacci numbers "; | |
558 | print "using number type ";print number_type;nl; | |
559 | ) | |
560 | ( | |
561 | print "Print the Fibonacci number at position ";print num_rounds; | |
562 | print " using number type ";print number_type;nl; | |
563 | ) | |
564 | ||
565 | \choose = | |
566 | ( | |
567 | \return | |
568 | \case = (string_eq number_type) | |
569 | case "double" (return print double_add 1.0); | |
570 | case "nat" (return nat_print nat_add nat_1); | |
571 | halt | |
572 | ) | |
573 | ||
574 | choose \num_print \num_add \num_1 | |
575 | ||
576 | \nums_print = (list_do \x num_print x; nl) | |
577 | ||
578 | # Produces the infinite list of all Fibonacci numbers. | |
579 | \fibonacci = | |
580 | ( | |
581 | \1 | |
582 | \add | |
583 | ||
584 | \fibonacci == (\x\y | |
585 | item x; | |
586 | \z = (add x y) | |
587 | fibonacci y z | |
588 | ) | |
589 | ||
590 | fibonacci 1 1 | |
591 | ) | |
592 | ||
593 | \fibonacci = (fibonacci num_1 num_add) | |
594 | ||
595 | if_show_all | |
596 | (nums_print; list_prefix fibonacci num_rounds) | |
597 | (num_print; list_at fibonacci (long_sub num_rounds 1) num_1) | |
598 | nl; | |
599 | ) | |
600 | ||
601 | #test_case T "nat" 200; | |
602 | #test_case T "nat" 2000; | |
603 | #test_case T "nat" 1; | |
604 | #test_case T "nat" 2; | |
605 | #test_case T "nat" 3; | |
606 | #test_case F "nat" 4; | |
607 | #test_case F "double" 4; | |
608 | #test_case F "nat" 1000; | |
609 | #test_case F "nat" 100; | |
610 | #test_case T "nat" 100; | |
611 | #test_case F "double" 1000; | |
612 | #test_case F "nat" 10000; | |
613 | #test_case T "nat" 100; | |
614 | #test_case T "nat" 10; | |
615 | #test_case F "nat" 500; | |
616 | ||
617 | #test_case T "double" 200; | |
618 | #test_case T "nat" 200; | |
619 | #test_case F "nat" 200; | |
620 | #test_case F "nat" 2000; | |
621 | ||
622 | test_case T "nat" 300; | |
623 | test_case F "nat" 1600; # 10.208s | |
624 | ) | |
625 | ||
626 | #### | |
627 | \test_binary_counter == | |
628 | ( | |
629 | ||
630 | \loop == | |
631 | ( | |
632 | \count | |
633 | \num | |
634 | long_le count 0 I; | |
635 | print (nat_long num); print " "; | |
636 | bits_print num; | |
637 | nl; | |
638 | \count = (long_sub count 1) | |
639 | \num = (nat_inc num) | |
640 | loop count num | |
641 | ) | |
642 | ||
643 | loop 50 nat_0 | |
644 | ) | |
645 | ||
646 | \test_divide== | |
647 | ( | |
648 | # LATER automatically check the constraints | |
649 | \test_div = (\x\y | |
650 | nat_div x y \q\r | |
651 | print "test_div";nl; | |
652 | \show=(\key\val print key;print " = "; nat_print val; nl;) | |
653 | show "x" x; | |
654 | show "y" y; | |
655 | show "q" q; | |
656 | show "r" r; | |
657 | nl; | |
658 | ) | |
659 | ||
660 | test_div nat_0 nat_0; | |
661 | test_div nat_0 nat_1; | |
662 | test_div nat_1 nat_0; | |
663 | test_div nat_1 nat_1; | |
664 | test_div nat_2 nat_1; | |
665 | ||
666 | test_div nat_0 nat_2; | |
667 | test_div nat_1 nat_2; | |
668 | test_div nat_2 nat_2; | |
669 | test_div nat_3 nat_2; | |
670 | test_div nat_4 nat_2; | |
671 | ||
672 | test_div nat_0 nat_3; | |
673 | test_div nat_1 nat_3; | |
674 | test_div nat_2 nat_3; | |
675 | test_div nat_3 nat_3; | |
676 | test_div nat_4 nat_3; | |
677 | test_div nat_5 nat_3; | |
678 | test_div nat_6 nat_3; | |
679 | test_div nat_7 nat_3; | |
680 | test_div nat_8 nat_3; | |
681 | test_div nat_9 nat_3; | |
682 | test_div nat_10 nat_3; | |
683 | test_div nat_11 nat_3; | |
684 | test_div nat_12 nat_3; | |
685 | ||
686 | test_div nat_0 nat_4; | |
687 | test_div nat_1 nat_4; | |
688 | test_div nat_2 nat_4; | |
689 | test_div nat_3 nat_4; | |
690 | test_div nat_4 nat_4; | |
691 | test_div nat_5 nat_4; | |
692 | test_div nat_6 nat_4; | |
693 | test_div nat_7 nat_4; | |
694 | test_div nat_8 nat_4; | |
695 | test_div nat_9 nat_4; | |
696 | test_div nat_10 nat_4; | |
697 | test_div nat_11 nat_4; | |
698 | test_div nat_12 nat_4; | |
699 | test_div nat_12 nat_4; | |
700 | ||
701 | test_div nat_0 nat_5; | |
702 | test_div nat_1 nat_5; | |
703 | test_div nat_2 nat_5; | |
704 | test_div nat_3 nat_5; | |
705 | test_div nat_4 nat_5; | |
706 | test_div nat_5 nat_5; | |
707 | test_div nat_6 nat_5; | |
708 | test_div nat_7 nat_5; | |
709 | test_div nat_8 nat_5; | |
710 | test_div nat_9 nat_5; | |
711 | test_div nat_10 nat_5; | |
712 | test_div nat_11 nat_5; | |
713 | test_div nat_12 nat_5; | |
714 | test_div nat_13 nat_5; | |
715 | test_div nat_14 nat_5; | |
716 | test_div nat_15 nat_5; | |
717 | test_div nat_16 nat_5; | |
718 | test_div nat_17 nat_5; | |
719 | test_div nat_18 nat_5; | |
720 | test_div nat_19 nat_5; | |
721 | ||
722 | \big_test = | |
723 | ( | |
724 | \next | |
725 | \x = (nat_mul nat_31 nat_19) | |
726 | \churn = (\x nat_add nat_17; nat_mul x x) | |
727 | \x = (churn x) | |
728 | \x = (churn x) | |
729 | \x = (churn x) | |
730 | \x = (churn x) | |
731 | \x = (churn x) | |
732 | \x = (churn x) | |
733 | \y =nat_10 | |
734 | \y=(nat_mul y y) | |
735 | ||
736 | test_div x y; | |
737 | test_div (churn x) (churn; churn; churn; churn; churn; churn y); | |
738 | next | |
739 | ) | |
740 | ||
741 | big_test | |
742 | #big_test; | |
743 | #big_test; | |
744 | #big_test; | |
745 | #big_test; | |
746 | ) | |
747 | ||
748 | \test_sub == | |
749 | ( | |
750 | \test_sub = (\x\y | |
751 | \z = (nat_sub x y) | |
752 | print "== test_sub: "; | |
753 | nat_print x; | |
754 | print " - "; | |
755 | nat_print y; | |
756 | print " = "; | |
757 | int_print z;nl; | |
758 | ) | |
759 | ||
760 | test_sub nat_0 nat_0 | |
761 | test_sub nat_1 nat_0 | |
762 | test_sub nat_2 nat_0 | |
763 | test_sub nat_3 nat_0 | |
764 | test_sub nat_4 nat_0 | |
765 | ||
766 | test_sub nat_1 nat_1 | |
767 | test_sub nat_0 nat_1 | |
768 | ||
769 | test_sub nat_0 nat_2 | |
770 | test_sub nat_1 nat_2 | |
771 | test_sub nat_2 nat_2 | |
772 | test_sub nat_3 nat_2 | |
773 | test_sub nat_4 nat_2 | |
774 | ||
775 | test_sub nat_0 nat_3 | |
776 | test_sub nat_1 nat_3 | |
777 | test_sub nat_2 nat_3 | |
778 | test_sub nat_3 nat_3 | |
779 | test_sub nat_4 nat_3 | |
780 | test_sub nat_5 nat_3 | |
781 | test_sub nat_6 nat_3 | |
782 | ||
783 | test_sub nat_0 nat_4 | |
784 | test_sub nat_1 nat_4 | |
785 | test_sub nat_2 nat_4 | |
786 | test_sub nat_3 nat_4 | |
787 | test_sub nat_4 nat_4 | |
788 | test_sub nat_5 nat_4 | |
789 | test_sub nat_6 nat_4 | |
790 | test_sub nat_7 nat_4 | |
791 | ||
792 | test_sub nat_0 nat_5 | |
793 | test_sub nat_1 nat_5 | |
794 | test_sub nat_2 nat_5 | |
795 | test_sub nat_3 nat_5 | |
796 | test_sub nat_4 nat_5 | |
797 | test_sub nat_5 nat_5 | |
798 | test_sub nat_6 nat_5 | |
799 | test_sub nat_7 nat_5 | |
800 | test_sub nat_8 nat_5 | |
801 | test_sub nat_9 nat_5 | |
802 | ||
803 | test_sub nat_3 nat_19 | |
804 | test_sub nat_19 nat_19 | |
805 | test_sub nat_49 nat_19 | |
806 | test_sub nat_48 nat_19 | |
807 | ) | |
808 | ||
809 | \return return test_fibonacci test_binary_counter test_divide | |
810 | test_sub | |
811 | ) | |
812 | ||
813 | module_test_arithmetic | |
814 | \test_fibonacci \test_binary_counter \test_divide \test_sub | |
815 | ||
816 | ######## | |
817 | ||
818 | # Choose your test(s) to run down here. Comment the ones don't want to run. | |
819 | ||
820 | \test_string_type== | |
821 | ( | |
822 | \test_case=(\x\expect | |
823 | \result = (string_type x "yes" "no") | |
824 | print "string_type "; print result; | |
825 | print " ["; | |
826 | print (string_eq result expect "GOOD" "BAD"); | |
827 | print "]"; | |
828 | nl; | |
829 | ) | |
830 | ||
831 | test_case 4 "no" | |
832 | test_case 2.3 "no" | |
833 | test_case (\x\y y x) "no" | |
834 | test_case C "no" | |
835 | test_case (string_append "hello " "world") "yes" | |
836 | test_case ((\x\y y x) "hi" I) "yes" | |
837 | test_case "hey!" "yes" | |
838 | ) | |
839 | ||
840 | \test_double_type== | |
841 | ( | |
842 | \test_case=(\x\expect | |
843 | \result = (double_type x "yes" "no") | |
844 | print "double_type "; print result; | |
845 | print " ["; | |
846 | print (string_eq result expect "GOOD" "BAD"); | |
847 | print "]"; | |
848 | nl; | |
849 | ) | |
850 | ||
851 | test_case 4 "no" | |
852 | test_case 2.3 "yes" | |
853 | test_case (\x\y y x) "no" | |
854 | test_case C "no" | |
855 | test_case (string_append "hello " "world") "no" | |
856 | test_case ((\x\y y x) (double_add 4.2 2.6) I) "yes" | |
857 | test_case "hey!" "no" | |
858 | ) | |
859 | ||
860 | \test_long_type== | |
861 | ( | |
862 | \test_case=(\x\expect | |
863 | \result = (long_type x "yes" "no") | |
864 | print "long_type "; print result; | |
865 | print " ["; | |
866 | print (string_eq result expect "GOOD" "BAD"); | |
867 | print "]"; | |
868 | nl; | |
869 | ) | |
870 | ||
871 | test_case 4 "yes" | |
872 | test_case 2.3 "no" | |
873 | test_case (\x\y y x) "no" | |
874 | test_case C "no" | |
875 | test_case (string_append "hello " "world") "no" | |
876 | test_case ((\x\y y x) (long_add 4 2) I) "yes" | |
877 | test_case "hey!" "no" | |
878 | ) | |
879 | ||
880 | \test_string_long == | |
881 | ( | |
882 | \test_case=(\x\expect | |
883 | \quote = ~@ "@ | |
884 | \result = (string_long x "no" \n string_append "yes " (long_string n)) | |
885 | print "string_long "; | |
886 | string_put quote; string_put x; string_put quote | |
887 | print " : "; print result; | |
888 | print " ["; | |
889 | print (string_eq result expect "GOOD" "BAD"); | |
890 | print "]"; | |
891 | nl; | |
892 | ) | |
893 | ||
894 | test_case "0" "yes 0" | |
895 | test_case "1" "yes 1" | |
896 | test_case "-1" "yes -1" | |
897 | test_case "123" "yes 123" | |
898 | test_case "-123" "yes -123" | |
899 | test_case "x123" "no" | |
900 | test_case "1x23" "no" | |
901 | test_case "" "no" | |
902 | test_case " 456 " "no" | |
903 | test_case "456 " "no" | |
904 | test_case "1.6" "no" | |
905 | test_case "0." "no" | |
906 | ) | |
907 | ||
908 | \test_string_double == | |
909 | ( | |
910 | \test_case=(\x\expect | |
911 | \quote = ~@ "@ | |
912 | \result = (string_double x "no" \n string_append "yes " (double_string n)) | |
913 | print "string_double "; | |
914 | string_put quote; string_put x; string_put quote | |
915 | print " : "; print result; | |
916 | print " ["; | |
917 | print (string_eq result expect "GOOD" "BAD"); | |
918 | print "]"; | |
919 | nl; | |
920 | ) | |
921 | ||
922 | test_case "0" "yes 0" | |
923 | test_case "1" "yes 1" | |
924 | test_case "-1" "yes -1" | |
925 | test_case "123" "yes 123" | |
926 | test_case "-123" "yes -123" | |
927 | test_case "x123" "no" | |
928 | test_case "1x23" "no" | |
929 | test_case "" "no" | |
930 | test_case " 456 " "no" | |
931 | test_case " 456.78 " "no" | |
932 | test_case "456.78" "yes 456.78" | |
933 | test_case "456 " "no" | |
934 | test_case "1.6" "yes 1.6" | |
935 | test_case "0." "yes 0" | |
936 | test_case "-0" "yes -0" | |
937 | test_case "-0.0" "yes -0" | |
938 | test_case "-0.0123" "yes -0.0123" | |
939 | ) | |
940 | ||
941 | \test_long_double == | |
942 | ( | |
943 | \test_case = ( | |
944 | \x | |
945 | \y = (long_double x) | |
946 | ||
947 | \x_str = (long_string x) | |
948 | \y_str = (double_string y) | |
949 | ||
950 | print "long x = "; string_put x_str; | |
951 | print " double y = "; string_put y_str;nl; | |
952 | ) | |
953 | ||
954 | test_case 4 | |
955 | test_case 0 | |
956 | test_case -1 | |
957 | test_case -37 | |
958 | test_case 126478 | |
959 | ) | |
960 | ||
961 | \test_double_long == | |
962 | ( | |
963 | \test_case = ( | |
964 | \x | |
965 | \y = (double_long x) | |
966 | ||
967 | \x_str = (double_string x) | |
968 | \y_str = (long_string y) | |
969 | ||
970 | print "double x = "; string_put x_str; | |
971 | print " long y = "; string_put y_str;nl; | |
972 | ) | |
973 | ||
974 | test_case 4.0 | |
975 | test_case 0.0 | |
976 | test_case -1.0 | |
977 | test_case -37.0 | |
978 | test_case 126478.0 | |
979 | test_case 4.3 | |
980 | test_case 0.3 | |
981 | test_case -1.3 | |
982 | test_case -37.3 | |
983 | test_case 126478.3 | |
984 | test_case 4.9 | |
985 | test_case 0.9 | |
986 | test_case -1.9 | |
987 | test_case -37.9 | |
988 | test_case 126478.9 | |
989 | test_case -126478.9 | |
990 | ) | |
991 | ||
992 | #### | |
993 | ||
994 | test_string_type | |
995 | test_double_type | |
996 | test_long_type | |
997 | ||
998 | test_long_double | |
999 | test_double_long | |
1000 | ||
1001 | test_string_long | |
1002 | test_string_double | |
1003 | ||
1004 | test_hello_world | |
1005 | test_string_slice | |
1006 | test_write_binary | |
1007 | test_string_len | |
1008 | test_string_at | |
1009 | test_string_compare | |
1010 | test_string_common | |
1011 | test_long_add | |
1012 | test_double_compare | |
1013 | test_procedural | |
1014 | test_eager | |
1015 | ||
1016 | test_binary_counter; | |
1017 | test_divide; | |
1018 | test_sub; | |
1019 | test_fibonacci | |
1020 | test_cat | |
1021 | ||
1022 | \\Extra stuff down here becomes input | |
1023 | to the test_cat function. |
0 | package main | |
1 | ||
2 | type Fexl Peg { | |
3 | ||
4 | } | |
5 | ||
6 | Fexl <- ws Expression+ Input? !. | |
7 | ||
8 | Input <- '\\\\' .* | |
9 | ||
10 | Expression <- Comment / ';' ws Expression* / Definition / Argument / Term | |
11 | ||
12 | Comment <- '#' (![\n\r] .)* ws | |
13 | ||
14 | Definition <- '\\' Symbol '=' ws Term / Recursive | |
15 | ||
16 | Recursive <- '\\' Symbol '==' ws Term | |
17 | ||
18 | Argument <- '\\' Symbol | |
19 | ||
20 | Term <- open Expression+ close / Symbol | |
21 | ||
22 | Symbol <- (String / (![ \t\n\r\\()"~;=] .)+) ws | |
23 | ||
24 | String <- '"' (!'"' .)* '"' / Complex | |
25 | ||
26 | Complex <- tilde '@' (!'@' .)* '@' | |
27 | ||
28 | tilde <- '~' | |
29 | ||
30 | open <- '(' ws | |
31 | ||
32 | close <- ')' ws | |
33 | ||
34 | ws <- [ \t\n\r]* |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "log" | |
8 | "io/ioutil" | |
9 | ) | |
10 | ||
11 | func main() { | |
12 | buffer, err := ioutil.ReadFile("doc/try.fxl") | |
13 | if err != nil { | |
14 | log.Fatal(err) | |
15 | } | |
16 | ||
17 | fexl := &Fexl{Buffer: string(buffer)} | |
18 | fexl.Init() | |
19 | ||
20 | if err := fexl.Parse(); err != nil { | |
21 | log.Fatal(err) | |
22 | } | |
23 | fexl.Highlighter() | |
24 | } |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | java: java_1_7.peg.go main.go | |
5 | go build | |
6 | ||
7 | java_1_7.peg.go: java_1_7.peg | |
8 | ../../peg -switch -inline java_1_7.peg | |
9 | ||
10 | clean: | |
11 | rm -f java java_1_7.peg.go |
0 | #=========================================================================== | |
1 | # | |
2 | # Parsing Expression Grammar for Java 1.7 for Mouse 1.1 - 1.5. | |
3 | # Based on Chapters 3 and 18 of Java Language Specification, Third Edition, | |
4 | # at http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html, | |
5 | # and description of Java SE 7 enhancements in | |
6 | # http://download.java.net/jdk7/docs/technotes/guides/language/enhancements.html. | |
7 | # | |
8 | #--------------------------------------------------------------------------- | |
9 | # | |
10 | # Copyright (C) 2006, 2009, 2010, 2011 | |
11 | # by Roman R Redziejowski(www.romanredz.se). | |
12 | # | |
13 | # The author gives unlimited permission to copy and distribute | |
14 | # this file, with or without modifications, as long as this notice | |
15 | # is preserved, and any changes are properly documented. | |
16 | # | |
17 | # This file is distributed in the hope that it will be useful, | |
18 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
19 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | |
20 | # | |
21 | #--------------------------------------------------------------------------- | |
22 | # | |
23 | # Latest update 2011-07-21 | |
24 | # | |
25 | #--------------------------------------------------------------------------- | |
26 | # | |
27 | # Change log | |
28 | # 2006-12-06 Posted on Internet. | |
29 | # 2009-04-04 Modified to conform to Mouse syntax: | |
30 | # Underscore removed from names | |
31 | # \f in Space replaced by Unicode for FormFeed. | |
32 | # 2009-07-10 Unused rule THREADSAFE removed. | |
33 | # 2009-07-10 Copying and distribution conditions relaxed by the author. | |
34 | # 2010-07-01 Updated Mouse version in the comment. | |
35 | # 2010-09-15 Updated comment on Java release. | |
36 | # 2010-09-18 Updated list of reserved words ("keywords") according to | |
37 | # JLS 3.9: added "const" and "goto", removed "threadsafe". | |
38 | # 2010-09-18 Removed superfluous "?" everywhere after "Spacing". | |
39 | # 2010-10-05 Removed erroneous "TypeArguments?" from "EnumConstant". | |
40 | # See JLS 8.9, JLS 18.1. | |
41 | # NB. "Annotations" are optional, but not shown as such in JLS. | |
42 | # 2010-10-20 Corrected "FormalParameterList" according to JLS 8.4.1. | |
43 | # NB. "VariableModifiers" in "FormalParameter" and "LastFormalParameter" | |
44 | # are optional, but not shown as such in JLS. | |
45 | # 2010-10-20 Corrected "Annotation" according to JLS 9.7. | |
46 | # Is incorrect in JLS 18.1 (does not allow list of value pairs). | |
47 | # 2010-10-20 Corrected "LocalVariableDeclarationStatement". | |
48 | # Is incorrect in JLS 18.1: only FINAL allowed as "VariableModifier". | |
49 | # Is incorrect in JLS 14.4: "VariableModifiers" not shown as optional. | |
50 | # 2010-10-20 Corrected "AnnotationTypeElementRest": added SEMI as last alternative. | |
51 | # See JLS 9.6. NB. Missing in JLS 18.1. | |
52 | # 2010-10-20 Moved "Identifier" from "AnnotationTypeElementRest" to | |
53 | # "AnnotationMethodRest". Was incorrect in JLS 18.1. | |
54 | # 2010-10-21 Inverted order of alternatives in "HexSignificand". | |
55 | # 2010-10-24 Corrected previous correction: moved SEMI from | |
56 | # "AnnotationTypeElementRest" to "AnnotationTypeElementDeclaration". | |
57 | # 2010-10-25 Repeated "u" allowed in UnicodeEscape (JLS 3.3). | |
58 | # Line terminators not allowed in StringLiteral (JLS 3.10.5). | |
59 | # (Found thanks to Java PEG for Parboiled, which in turn credits | |
60 | # Reinier Zwitserloot for finding it.) | |
61 | # 2011-07-19 Added SEMI after "VariableDeclarators" in "MemberDecl" (JLS 8.3). | |
62 | # 2011-07-21 Corrected "ArrayInitializer" to allow for "{,}" (JLS 10.6). | |
63 | # | |
64 | #--------------------------------------------------------------------------- | |
65 | # | |
66 | # Changes for Java 1.7 | |
67 | # 2011-07-18 Implemented Binary Literals: added "BinaryNumeral". | |
68 | # 2011-07-19 Implemented Underscores in Numerical Literals: | |
69 | # Added "Digits" and "HexDigits". Removed "Digit". | |
70 | # Modified "DecimalNumeral", "HexNumeral", "BinaryNumeral", | |
71 | # "OctalNumeral", "DecimalFloat", "Exponent", | |
72 | # "HexSignificand", and "BinaryExponent". | |
73 | # 2011-07-20 Implemented Type Inference for Generic Instance Creation: | |
74 | # Added "Diamond". | |
75 | # Modified "ClassCreatorRest" by adding "Diamond?". | |
76 | # 2011-07-20 Implemented try-with-resources Statement: | |
77 | # Added try-with-resources as an alternative of "Statement". | |
78 | # Added "Resource". (Based on comments to JavacParser). | |
79 | # 2011-07-20 Implemented catching of multiple exceptions: | |
80 | # Modified "Catch" to allow multiple exception types. | |
81 | # Based on a pure guess. | |
82 | # | |
83 | #--------------------------------------------------------------------------- | |
84 | # | |
85 | # 2013-02-16 Modified to work with github.com/pointlander/peg | |
86 | # | |
87 | #=========================================================================== | |
88 | ||
89 | #------------------------------------------------------------------------- | |
90 | # Compilation Unit | |
91 | #------------------------------------------------------------------------- | |
92 | ||
93 | package main | |
94 | ||
95 | type Java Peg { | |
96 | ||
97 | } | |
98 | ||
99 | CompilationUnit <- Spacing PackageDeclaration? ImportDeclaration* TypeDeclaration* EOT | |
100 | PackageDeclaration <- Annotation* PACKAGE QualifiedIdentifier SEMI | |
101 | ImportDeclaration <- IMPORT STATIC? QualifiedIdentifier (DOT STAR)? SEMI | |
102 | ||
103 | TypeDeclaration <- Modifier* (ClassDeclaration | |
104 | / EnumDeclaration | |
105 | / InterfaceDeclaration | |
106 | / AnnotationTypeDeclaration) | |
107 | / SEMI | |
108 | ||
109 | #------------------------------------------------------------------------- | |
110 | # Class Declaration | |
111 | #------------------------------------------------------------------------- | |
112 | ||
113 | ClassDeclaration <- CLASS Identifier TypeParameters? (EXTENDS ClassType)? (IMPLEMENTS ClassTypeList)? ClassBody | |
114 | ||
115 | ClassBody <- LWING ClassBodyDeclaration* RWING | |
116 | ||
117 | ClassBodyDeclaration | |
118 | <- SEMI | |
119 | / STATIC? Block # Static or Instance Initializer | |
120 | / Modifier* MemberDecl # ClassMemberDeclaration | |
121 | ||
122 | MemberDecl | |
123 | <- TypeParameters GenericMethodOrConstructorRest # Generic Method or Constructor | |
124 | / Type Identifier MethodDeclaratorRest # Method | |
125 | / Type VariableDeclarators SEMI # Field | |
126 | / VOID Identifier VoidMethodDeclaratorRest # Void method | |
127 | / Identifier ConstructorDeclaratorRest # Constructor | |
128 | / InterfaceDeclaration # Interface | |
129 | / ClassDeclaration # Class | |
130 | / EnumDeclaration # Enum | |
131 | / AnnotationTypeDeclaration # Annotation | |
132 | ||
133 | GenericMethodOrConstructorRest | |
134 | <- (Type / VOID) Identifier MethodDeclaratorRest | |
135 | / Identifier ConstructorDeclaratorRest | |
136 | ||
137 | MethodDeclaratorRest | |
138 | <- FormalParameters Dim* (THROWS ClassTypeList)? (MethodBody / SEMI) | |
139 | ||
140 | VoidMethodDeclaratorRest | |
141 | <- FormalParameters (THROWS ClassTypeList)? (MethodBody / SEMI) | |
142 | ||
143 | ConstructorDeclaratorRest | |
144 | <- FormalParameters (THROWS ClassTypeList)? MethodBody | |
145 | ||
146 | MethodBody | |
147 | <- Block | |
148 | ||
149 | #------------------------------------------------------------------------- | |
150 | # Interface Declaration | |
151 | #------------------------------------------------------------------------- | |
152 | ||
153 | InterfaceDeclaration | |
154 | <- INTERFACE Identifier TypeParameters? (EXTENDS ClassTypeList)? InterfaceBody | |
155 | ||
156 | InterfaceBody | |
157 | <- LWING InterfaceBodyDeclaration* RWING | |
158 | ||
159 | InterfaceBodyDeclaration | |
160 | <- Modifier* InterfaceMemberDecl | |
161 | / SEMI | |
162 | ||
163 | InterfaceMemberDecl | |
164 | <- InterfaceMethodOrFieldDecl | |
165 | / InterfaceGenericMethodDecl | |
166 | / VOID Identifier VoidInterfaceMethodDeclaratorRest | |
167 | / InterfaceDeclaration | |
168 | / AnnotationTypeDeclaration | |
169 | / ClassDeclaration | |
170 | / EnumDeclaration | |
171 | ||
172 | InterfaceMethodOrFieldDecl | |
173 | <- Type Identifier InterfaceMethodOrFieldRest | |
174 | ||
175 | InterfaceMethodOrFieldRest | |
176 | <- ConstantDeclaratorsRest SEMI | |
177 | / InterfaceMethodDeclaratorRest | |
178 | ||
179 | InterfaceMethodDeclaratorRest | |
180 | <- FormalParameters Dim* (THROWS ClassTypeList)? SEM | |
181 | ||
182 | InterfaceGenericMethodDecl | |
183 | <- TypeParameters (Type / VOID) Identifier InterfaceMethodDeclaratorRest | |
184 | ||
185 | VoidInterfaceMethodDeclaratorRest | |
186 | <- FormalParameters (THROWS ClassTypeList)? SEMI | |
187 | ||
188 | ConstantDeclaratorsRest | |
189 | <- ConstantDeclaratorRest (COMMA ConstantDeclarator)* | |
190 | ||
191 | ConstantDeclarator | |
192 | <- Identifier ConstantDeclaratorRest | |
193 | ||
194 | ConstantDeclaratorRest | |
195 | <- Dim* EQU VariableInitializer | |
196 | ||
197 | #------------------------------------------------------------------------- | |
198 | # Enum Declaration | |
199 | #------------------------------------------------------------------------- | |
200 | ||
201 | EnumDeclaration | |
202 | <- ENUM Identifier (IMPLEMENTS ClassTypeList)? EnumBody | |
203 | ||
204 | EnumBody | |
205 | <- LWING EnumConstants? COMMA? EnumBodyDeclarations? RWING | |
206 | ||
207 | EnumConstants | |
208 | <- EnumConstant (COMMA EnumConstant)* | |
209 | ||
210 | EnumConstant | |
211 | <- Annotation* Identifier Arguments? ClassBody? | |
212 | ||
213 | EnumBodyDeclarations | |
214 | <- SEMI ClassBodyDeclaration* | |
215 | ||
216 | #------------------------------------------------------------------------- | |
217 | # Variable Declarations | |
218 | #------------------------------------------------------------------------- | |
219 | ||
220 | LocalVariableDeclarationStatement | |
221 | <- (FINAL / Annotation)* Type VariableDeclarators SEMI | |
222 | ||
223 | VariableDeclarators | |
224 | <- VariableDeclarator (COMMA VariableDeclarator)* | |
225 | ||
226 | VariableDeclarator | |
227 | <- Identifier Dim* (EQU VariableInitializer)? | |
228 | ||
229 | #------------------------------------------------------------------------- | |
230 | # Formal Parameters | |
231 | #------------------------------------------------------------------------- | |
232 | ||
233 | FormalParameters | |
234 | <- LPAR FormalParameterList? RPAR | |
235 | ||
236 | FormalParameter | |
237 | <- (FINAL / Annotation)* Type VariableDeclaratorId | |
238 | ||
239 | LastFormalParameter | |
240 | <- (FINAL / Annotation)* Type ELLIPSIS VariableDeclaratorId | |
241 | ||
242 | FormalParameterList | |
243 | <- FormalParameter (COMMA FormalParameter)* (COMMA LastFormalParameter)? | |
244 | / LastFormalParameter | |
245 | ||
246 | VariableDeclaratorId | |
247 | <- Identifier Dim* | |
248 | ||
249 | #------------------------------------------------------------------------- | |
250 | # Statements | |
251 | #------------------------------------------------------------------------- | |
252 | ||
253 | Block | |
254 | <- LWING BlockStatements RWING | |
255 | ||
256 | BlockStatements | |
257 | <- BlockStatement* | |
258 | ||
259 | BlockStatement | |
260 | <- LocalVariableDeclarationStatement | |
261 | / Modifier* | |
262 | ( ClassDeclaration | |
263 | / EnumDeclaration | |
264 | ) | |
265 | / Statement | |
266 | ||
267 | Statement | |
268 | <- Block | |
269 | / ASSERT Expression (COLON Expression)? SEMI | |
270 | / IF ParExpression Statement (ELSE Statement)? | |
271 | / FOR LPAR ForInit? SEMI Expression? SEMI ForUpdate? RPAR Statement | |
272 | / FOR LPAR FormalParameter COLON Expression RPAR Statement | |
273 | / WHILE ParExpression Statement | |
274 | / DO Statement WHILE ParExpression SEMI | |
275 | / TRY LPAR Resource (SEMI Resource)* SEMI? RPAR Block Catch* Finally? | |
276 | / TRY Block (Catch+ Finally? / Finally) | |
277 | / SWITCH ParExpression LWING SwitchBlockStatementGroups RWING | |
278 | / SYNCHRONIZED ParExpression Block | |
279 | / RETURN Expression? SEMI | |
280 | / THROW Expression SEMI | |
281 | / BREAK Identifier? SEMI | |
282 | / CONTINUE Identifier? SEMI | |
283 | / SEMI | |
284 | / StatementExpression SEMI | |
285 | / Identifier COLON Statement | |
286 | ||
287 | Resource | |
288 | <- Modifier* Type VariableDeclaratorId EQU Expression | |
289 | ||
290 | Catch | |
291 | <- CATCH LPAR (FINAL / Annotation)* Type (OR Type)* VariableDeclaratorId RPAR Block | |
292 | ||
293 | Finally | |
294 | <- FINALLY Block | |
295 | ||
296 | SwitchBlockStatementGroups | |
297 | <- SwitchBlockStatementGroup* | |
298 | ||
299 | SwitchBlockStatementGroup | |
300 | <- SwitchLabel BlockStatements | |
301 | ||
302 | SwitchLabel | |
303 | <- CASE ConstantExpression COLON | |
304 | / CASE EnumConstantName COLON | |
305 | / DEFAULT COLON | |
306 | ||
307 | ForInit | |
308 | <- (FINAL / Annotation)* Type VariableDeclarators | |
309 | / StatementExpression (COMMA StatementExpression)* | |
310 | ||
311 | ForUpdate | |
312 | <- StatementExpression (COMMA StatementExpression)* | |
313 | ||
314 | EnumConstantName | |
315 | <- Identifier | |
316 | ||
317 | #------------------------------------------------------------------------- | |
318 | # Expressions | |
319 | #------------------------------------------------------------------------- | |
320 | ||
321 | StatementExpression | |
322 | <- Expression | |
323 | ||
324 | # This is more generous than definition in section 14.8, which allows only | |
325 | # specific forms of Expression. | |
326 | ||
327 | ||
328 | ConstantExpression | |
329 | <- Expression | |
330 | ||
331 | Expression | |
332 | <- ConditionalExpression (AssignmentOperator ConditionalExpression)* | |
333 | ||
334 | # This definition is part of the modification in JLS Chapter 18 | |
335 | # to minimize look ahead. In JLS Chapter 15.27, Expression is defined | |
336 | # as AssignmentExpression, which is effectively defined as | |
337 | # (LeftHandSide AssignmentOperator)* ConditionalExpression. | |
338 | # The above is obtained by allowing ANY ConditionalExpression | |
339 | # as LeftHandSide, which results in accepting statements like 5 = a. | |
340 | ||
341 | ||
342 | AssignmentOperator | |
343 | <- EQU | |
344 | / PLUSEQU | |
345 | / MINUSEQU | |
346 | / STAREQU | |
347 | / DIVEQU | |
348 | / ANDEQU | |
349 | / OREQU | |
350 | / HATEQU | |
351 | / MODEQU | |
352 | / SLEQU | |
353 | / SREQU | |
354 | / BSREQU | |
355 | ||
356 | ConditionalExpression | |
357 | <- ConditionalOrExpression (QUERY Expression COLON ConditionalOrExpression)* | |
358 | ||
359 | ConditionalOrExpression | |
360 | <- ConditionalAndExpression (OROR ConditionalAndExpression)* | |
361 | ||
362 | ConditionalAndExpression | |
363 | <- InclusiveOrExpression (ANDAND InclusiveOrExpression)* | |
364 | ||
365 | InclusiveOrExpression | |
366 | <- ExclusiveOrExpression (OR ExclusiveOrExpression)* | |
367 | ||
368 | ExclusiveOrExpression | |
369 | <- AndExpression (HAT AndExpression)* | |
370 | ||
371 | AndExpression | |
372 | <- EqualityExpression (AND EqualityExpression)* | |
373 | ||
374 | EqualityExpression | |
375 | <- RelationalExpression ((EQUAL / NOTEQUAL) RelationalExpression)* | |
376 | ||
377 | RelationalExpression | |
378 | <- ShiftExpression ((LE / GE / LT / GT) ShiftExpression / INSTANCEOF ReferenceType)* | |
379 | ||
380 | ShiftExpression | |
381 | <- AdditiveExpression ((SL / SR / BSR) AdditiveExpression)* | |
382 | ||
383 | AdditiveExpression | |
384 | <- MultiplicativeExpression ((PLUS / MINUS) MultiplicativeExpression)* | |
385 | ||
386 | MultiplicativeExpression | |
387 | <- UnaryExpression ((STAR / DIV / MOD) UnaryExpression)* | |
388 | ||
389 | UnaryExpression | |
390 | <- PrefixOp UnaryExpression | |
391 | / LPAR Type RPAR UnaryExpression | |
392 | / Primary (Selector)* (PostfixOp)* | |
393 | ||
394 | Primary | |
395 | <- ParExpression | |
396 | / NonWildcardTypeArguments (ExplicitGenericInvocationSuffix / THIS Arguments) | |
397 | / THIS Arguments? | |
398 | / SUPER SuperSuffix | |
399 | / Literal | |
400 | / NEW Creator | |
401 | / QualifiedIdentifier IdentifierSuffix? | |
402 | / BasicType Dim* DOT CLASS | |
403 | / VOID DOT CLASS | |
404 | ||
405 | IdentifierSuffix | |
406 | <- LBRK ( RBRK Dim* DOT CLASS / Expression RBRK) | |
407 | / Arguments | |
408 | / DOT | |
409 | ( CLASS | |
410 | / ExplicitGenericInvocation | |
411 | / THIS | |
412 | / SUPER Arguments | |
413 | / NEW NonWildcardTypeArguments? InnerCreator | |
414 | ) | |
415 | ||
416 | ExplicitGenericInvocation | |
417 | <- NonWildcardTypeArguments ExplicitGenericInvocationSuffix | |
418 | ||
419 | NonWildcardTypeArguments | |
420 | <- LPOINT ReferenceType (COMMA ReferenceType)* RPOINT | |
421 | ||
422 | ExplicitGenericInvocationSuffix | |
423 | <- SUPER SuperSuffix | |
424 | / Identifier Arguments | |
425 | ||
426 | PrefixOp | |
427 | <- INC | |
428 | / DEC | |
429 | / BANG | |
430 | / TILDA | |
431 | / PLUS | |
432 | / MINUS | |
433 | ||
434 | PostfixOp | |
435 | <- INC | |
436 | / DEC | |
437 | ||
438 | Selector | |
439 | <- DOT Identifier Arguments? | |
440 | / DOT ExplicitGenericInvocation | |
441 | / DOT THIS | |
442 | / DOT SUPER SuperSuffix | |
443 | / DOT NEW NonWildcardTypeArguments? InnerCreator | |
444 | / DimExpr | |
445 | ||
446 | SuperSuffix | |
447 | <- Arguments | |
448 | / DOT Identifier Arguments? | |
449 | ||
450 | BasicType | |
451 | <- ( 'byte' | |
452 | / 'short' | |
453 | / 'char' | |
454 | / 'int' | |
455 | / 'long' | |
456 | / 'float' | |
457 | / 'double' | |
458 | / 'boolean' | |
459 | ) !LetterOrDigit Spacing | |
460 | ||
461 | Arguments | |
462 | <- LPAR (Expression (COMMA Expression)*)? RPAR | |
463 | ||
464 | Creator | |
465 | <- NonWildcardTypeArguments? CreatedName ClassCreatorRest | |
466 | / NonWildcardTypeArguments? (ClassType / BasicType) ArrayCreatorRest | |
467 | ||
468 | CreatedName | |
469 | <- Identifier NonWildcardTypeArguments? (DOT Identifier NonWildcardTypeArguments?)* | |
470 | ||
471 | InnerCreator | |
472 | <- Identifier ClassCreatorRest | |
473 | ||
474 | ArrayCreatorRest | |
475 | <- LBRK ( RBRK Dim* ArrayInitializer / Expression RBRK DimExpr* Dim* ) | |
476 | ||
477 | # This is more generous than JLS 15.10. According to that definition, | |
478 | # BasicType must be followed by at least one DimExpr or by ArrayInitializer. | |
479 | ||
480 | ||
481 | ClassCreatorRest | |
482 | <- Diamond? Arguments ClassBody? | |
483 | ||
484 | Diamond | |
485 | <- LPOINT RPOINT | |
486 | ||
487 | ArrayInitializer | |
488 | <- LWING (VariableInitializer (COMMA VariableInitializer)*)? COMMA? RWING | |
489 | ||
490 | VariableInitializer | |
491 | <- ArrayInitializer | |
492 | / Expression | |
493 | ||
494 | ParExpression | |
495 | <- LPAR Expression RPAR | |
496 | ||
497 | QualifiedIdentifier | |
498 | <- Identifier (DOT Identifier)* | |
499 | ||
500 | Dim | |
501 | <- LBRK RBRK | |
502 | ||
503 | DimExpr | |
504 | <- LBRK Expression RBRK | |
505 | ||
506 | #------------------------------------------------------------------------- | |
507 | # Types and Modifiers | |
508 | #------------------------------------------------------------------------- | |
509 | ||
510 | Type | |
511 | <- (BasicType / ClassType) Dim* | |
512 | ||
513 | ReferenceType | |
514 | <- BasicType Dim+ | |
515 | / ClassType Dim* | |
516 | ||
517 | ClassType | |
518 | <- Identifier TypeArguments? (DOT Identifier TypeArguments?)* | |
519 | ||
520 | ClassTypeList | |
521 | <- ClassType (COMMA ClassType)* | |
522 | ||
523 | TypeArguments | |
524 | <- LPOINT TypeArgument (COMMA TypeArgument)* RPOINT | |
525 | ||
526 | TypeArgument | |
527 | <- ReferenceType | |
528 | / QUERY ((EXTENDS / SUPER) ReferenceType)? | |
529 | ||
530 | TypeParameters | |
531 | <- LPOINT TypeParameter (COMMA TypeParameter)* RPOINT | |
532 | ||
533 | TypeParameter | |
534 | <- Identifier (EXTENDS Bound)? | |
535 | ||
536 | Bound | |
537 | <- ClassType (AND ClassType)* | |
538 | ||
539 | Modifier | |
540 | <- Annotation | |
541 | / ( 'public' | |
542 | / 'protected' | |
543 | / 'private' | |
544 | / 'static' | |
545 | / 'abstract' | |
546 | / 'final' | |
547 | / 'native' | |
548 | / 'synchronized' | |
549 | / 'transient' | |
550 | / 'volatile' | |
551 | / 'strictfp' | |
552 | ) !LetterOrDigit Spacing | |
553 | ||
554 | # This common definition of Modifier is part of the modification | |
555 | # in JLS Chapter 18 to minimize look ahead. The main body of JLS has | |
556 | # different lists of modifiers for different language elements. | |
557 | ||
558 | #------------------------------------------------------------------------- | |
559 | # Annotations | |
560 | #------------------------------------------------------------------------- | |
561 | ||
562 | AnnotationTypeDeclaration | |
563 | <- AT INTERFACE Identifier AnnotationTypeBody | |
564 | ||
565 | AnnotationTypeBody | |
566 | <- LWING AnnotationTypeElementDeclaration* RWING | |
567 | ||
568 | AnnotationTypeElementDeclaration | |
569 | <- Modifier* AnnotationTypeElementRest | |
570 | / SEMI | |
571 | ||
572 | AnnotationTypeElementRest | |
573 | <- Type AnnotationMethodOrConstantRest SEMI | |
574 | / ClassDeclaration | |
575 | / EnumDeclaration | |
576 | / InterfaceDeclaration | |
577 | / AnnotationTypeDeclaration | |
578 | ||
579 | AnnotationMethodOrConstantRest | |
580 | <- AnnotationMethodRest | |
581 | / AnnotationConstantRest | |
582 | ||
583 | AnnotationMethodRest | |
584 | <- Identifier LPAR RPAR DefaultValue? | |
585 | ||
586 | AnnotationConstantRest | |
587 | <- VariableDeclarators | |
588 | ||
589 | DefaultValue | |
590 | <- DEFAULT ElementValue | |
591 | ||
592 | Annotation | |
593 | <- NormalAnnotation | |
594 | / SingleElementAnnotation | |
595 | / MarkerAnnotation | |
596 | ||
597 | NormalAnnotation | |
598 | <- AT QualifiedIdentifier LPAR ElementValuePairs? RPAR | |
599 | ||
600 | SingleElementAnnotation | |
601 | <- AT QualifiedIdentifier LPAR ElementValue RPAR | |
602 | ||
603 | MarkerAnnotation | |
604 | <- AT QualifiedIdentifier | |
605 | ||
606 | ElementValuePairs | |
607 | <- ElementValuePair (COMMA ElementValuePair)* | |
608 | ||
609 | ElementValuePair | |
610 | <- Identifier EQU ElementValue | |
611 | ||
612 | ElementValue | |
613 | <- ConditionalExpression | |
614 | / Annotation | |
615 | / ElementValueArrayInitializer | |
616 | ||
617 | ElementValueArrayInitializer | |
618 | <- LWING ElementValues? COMMA? RWING | |
619 | ||
620 | ElementValues | |
621 | <- ElementValue (COMMA ElementValue)* | |
622 | ||
623 | ||
624 | #========================================================================= | |
625 | # Lexical Structure | |
626 | #========================================================================= | |
627 | #------------------------------------------------------------------------- | |
628 | # JLS 3.6-7 Spacing | |
629 | #------------------------------------------------------------------------- | |
630 | ||
631 | Spacing | |
632 | <- ( [ \t\r\n]+ # WhiteSpace [ \t\r\n\u000C]+ | |
633 | / '/*' (!'*/' .)* '*/' # TraditionalComment | |
634 | / '//' (![\r\n] .)* [\r\n] # EndOfLineComment | |
635 | )* | |
636 | ||
637 | #------------------------------------------------------------------------- | |
638 | # JLS 3.8 Identifiers | |
639 | #------------------------------------------------------------------------- | |
640 | ||
641 | Identifier <- !Keyword Letter LetterOrDigit* Spacing | |
642 | ||
643 | Letter <- [a-z] / [A-Z] / [_$] | |
644 | ||
645 | LetterOrDigit <- [a-z] / [A-Z] / [0-9] / [_$] | |
646 | ||
647 | # These are traditional definitions of letters and digits. | |
648 | # JLS defines letters and digits as Unicode characters recognized | |
649 | # as such by special Java procedures, which is difficult | |
650 | # to express in terms of Parsing Expressions. | |
651 | ||
652 | #------------------------------------------------------------------------- | |
653 | # JLS 3.9 Keywords | |
654 | # More precisely: reserved words. According to JLS, "true", "false", | |
655 | # and "null" are technically not keywords - but still must not appear | |
656 | # as identifiers. Keywords "const" and "goto" are not used; JLS explains | |
657 | # the reason. | |
658 | #------------------------------------------------------------------------- | |
659 | ||
660 | Keyword | |
661 | <- ( 'abstract' | |
662 | / 'assert' | |
663 | / 'boolean' | |
664 | / 'break' | |
665 | / 'byte' | |
666 | / 'case' | |
667 | / 'catch' | |
668 | / 'char' | |
669 | / 'class' | |
670 | / 'const' | |
671 | / 'continue' | |
672 | / 'default' | |
673 | / 'double' | |
674 | / 'do' | |
675 | / 'else' | |
676 | / 'enum' | |
677 | / 'extends' | |
678 | / 'false' | |
679 | / 'finally' | |
680 | / 'final' | |
681 | / 'float' | |
682 | / 'for' | |
683 | / 'goto' | |
684 | / 'if' | |
685 | / 'implements' | |
686 | / 'import' | |
687 | / 'interface' | |
688 | / 'int' | |
689 | / 'instanceof' | |
690 | / 'long' | |
691 | / 'native' | |
692 | / 'new' | |
693 | / 'null' | |
694 | / 'package' | |
695 | / 'private' | |
696 | / 'protected' | |
697 | / 'public' | |
698 | / 'return' | |
699 | / 'short' | |
700 | / 'static' | |
701 | / 'strictfp' | |
702 | / 'super' | |
703 | / 'switch' | |
704 | / 'synchronized' | |
705 | / 'this' | |
706 | / 'throws' | |
707 | / 'throw' | |
708 | / 'transient' | |
709 | / 'true' | |
710 | / 'try' | |
711 | / 'void' | |
712 | / 'volatile' | |
713 | / 'while' | |
714 | ) !LetterOrDigit | |
715 | ||
716 | ASSERT <- 'assert' !LetterOrDigit Spacing | |
717 | BREAK <- 'break' !LetterOrDigit Spacing | |
718 | CASE <- 'case' !LetterOrDigit Spacing | |
719 | CATCH <- 'catch' !LetterOrDigit Spacing | |
720 | CLASS <- 'class' !LetterOrDigit Spacing | |
721 | CONTINUE <- 'continue' !LetterOrDigit Spacing | |
722 | DEFAULT <- 'default' !LetterOrDigit Spacing | |
723 | DO <- 'do' !LetterOrDigit Spacing | |
724 | ELSE <- 'else' !LetterOrDigit Spacing | |
725 | ENUM <- 'enum' !LetterOrDigit Spacing | |
726 | EXTENDS <- 'extends' !LetterOrDigit Spacing | |
727 | FINALLY <- 'finally' !LetterOrDigit Spacing | |
728 | FINAL <- 'final' !LetterOrDigit Spacing | |
729 | FOR <- 'for' !LetterOrDigit Spacing | |
730 | IF <- 'if' !LetterOrDigit Spacing | |
731 | IMPLEMENTS <- 'implements' !LetterOrDigit Spacing | |
732 | IMPORT <- 'import' !LetterOrDigit Spacing | |
733 | INTERFACE <- 'interface' !LetterOrDigit Spacing | |
734 | INSTANCEOF <- 'instanceof' !LetterOrDigit Spacing | |
735 | NEW <- 'new' !LetterOrDigit Spacing | |
736 | PACKAGE <- 'package' !LetterOrDigit Spacing | |
737 | RETURN <- 'return' !LetterOrDigit Spacing | |
738 | STATIC <- 'static' !LetterOrDigit Spacing | |
739 | SUPER <- 'super' !LetterOrDigit Spacing | |
740 | SWITCH <- 'switch' !LetterOrDigit Spacing | |
741 | SYNCHRONIZED <- 'synchronized' !LetterOrDigit Spacing | |
742 | THIS <- 'this' !LetterOrDigit Spacing | |
743 | THROWS <- 'throws' !LetterOrDigit Spacing | |
744 | THROW <- 'throw' !LetterOrDigit Spacing | |
745 | TRY <- 'try' !LetterOrDigit Spacing | |
746 | VOID <- 'void' !LetterOrDigit Spacing | |
747 | WHILE <- 'while' !LetterOrDigit Spacing | |
748 | ||
749 | #------------------------------------------------------------------------- | |
750 | # JLS 3.10 Literals | |
751 | #------------------------------------------------------------------------- | |
752 | ||
753 | Literal | |
754 | <- ( FloatLiteral | |
755 | / IntegerLiteral # May be a prefix of FloatLiteral | |
756 | / CharLiteral | |
757 | / StringLiteral | |
758 | / 'true' !LetterOrDigit | |
759 | / 'false' !LetterOrDigit | |
760 | / 'null' !LetterOrDigit | |
761 | ) Spacing | |
762 | ||
763 | IntegerLiteral | |
764 | <- ( HexNumeral | |
765 | / BinaryNumeral | |
766 | / OctalNumeral # May be a prefix of HexNumeral or BinaryNumeral | |
767 | / DecimalNumeral # May be a prefix of OctalNumeral | |
768 | ) [lL]? | |
769 | ||
770 | DecimalNumeral <- '0' / [1-9] ([_]* [0-9])* | |
771 | ||
772 | HexNumeral <- ('0x' / '0X') HexDigits | |
773 | ||
774 | BinaryNumeral <- ('0b' / '0B') [01] ([_]* [01])* | |
775 | ||
776 | OctalNumeral <- '0' ([_]* [0-7])+ | |
777 | ||
778 | FloatLiteral <- HexFloat / DecimalFloat | |
779 | ||
780 | DecimalFloat | |
781 | <- Digits '.' Digits? Exponent? [fFdD]? | |
782 | / '.' Digits Exponent? [fFdD]? | |
783 | / Digits Exponent [fFdD]? | |
784 | / Digits Exponent? [fFdD] | |
785 | ||
786 | Exponent <- [eE] [+\-]? Digits | |
787 | ||
788 | HexFloat <- HexSignificand BinaryExponent [fFdD]? | |
789 | ||
790 | HexSignificand | |
791 | <- ('0x' / '0X') HexDigits? '.' HexDigits | |
792 | / HexNumeral '.'? # May be a prefix of above | |
793 | ||
794 | BinaryExponent <- [pP] [+\-]? Digits | |
795 | ||
796 | Digits <- [0-9]([_]*[0-9])* | |
797 | ||
798 | HexDigits <- HexDigit ([_]*HexDigit)* | |
799 | ||
800 | HexDigit <- [a-f] / [A-F] / [0-9] | |
801 | ||
802 | CharLiteral <- ['] (Escape / !['\\] .) ['] | |
803 | ||
804 | StringLiteral <- '\"' (Escape / !["\\\n\r] .)* '\"' | |
805 | ||
806 | Escape <- '\\' ([btnfr"'\\] / OctalEscape / UnicodeEscape) | |
807 | ||
808 | OctalEscape | |
809 | <- [0-3][0-7][0-7] | |
810 | / [0-7][0-7] | |
811 | / [0-7] | |
812 | ||
813 | UnicodeEscape | |
814 | <- 'u'+ HexDigit HexDigit HexDigit HexDigit | |
815 | ||
816 | #------------------------------------------------------------------------- | |
817 | # JLS 3.11-12 Separators, Operators | |
818 | #------------------------------------------------------------------------- | |
819 | ||
820 | AT <- '@' Spacing | |
821 | AND <- '&'![=&] Spacing | |
822 | ANDAND <- '&&' Spacing | |
823 | ANDEQU <- '&=' Spacing | |
824 | BANG <- '!' !'=' Spacing | |
825 | BSR <- '>>>' !'=' Spacing | |
826 | BSREQU <- '>>>=' Spacing | |
827 | COLON <- ':' Spacing | |
828 | COMMA <- ',' Spacing | |
829 | DEC <- '--' Spacing | |
830 | DIV <- '/' !'=' Spacing | |
831 | DIVEQU <- '/=' Spacing | |
832 | DOT <- '.' Spacing | |
833 | ELLIPSIS <- '...' Spacing | |
834 | EQU <- '=' !'=' Spacing | |
835 | EQUAL <- '==' Spacing | |
836 | GE <- '>=' Spacing | |
837 | GT <- '>'![=>] Spacing | |
838 | HAT <- '^' !'=' Spacing | |
839 | HATEQU <- '^=' Spacing | |
840 | INC <- '++' Spacing | |
841 | LBRK <- '[' Spacing | |
842 | LE <- '<=' Spacing | |
843 | LPAR <- '(' Spacing | |
844 | LPOINT <- '<' Spacing | |
845 | LT <- '<' ![=<] Spacing | |
846 | LWING <- '{' Spacing | |
847 | MINUS <- '-' ![=\-] Spacing | |
848 | MINUSEQU <- '-=' Spacing | |
849 | MOD <- '%' !'=' Spacing | |
850 | MODEQU <- '%=' Spacing | |
851 | NOTEQUAL <- '!=' Spacing | |
852 | OR <- '|' ![=|] Spacing | |
853 | OREQU <- '|=' Spacing | |
854 | OROR <- '||' Spacing | |
855 | PLUS <- '+' ![=+] Spacing | |
856 | PLUSEQU <- '+=' Spacing | |
857 | QUERY <- '?' Spacing | |
858 | RBRK <- ']' Spacing | |
859 | RPAR <- ')' Spacing | |
860 | RPOINT <- '>' Spacing | |
861 | RWING <- '}' Spacing | |
862 | SEMI <- ';' Spacing | |
863 | SL <- '<<' !'=' Spacing | |
864 | SLEQU <- '<<=' Spacing | |
865 | SR <- '>>' ![=>] Spacing | |
866 | SREQU <- '>>=' Spacing | |
867 | STAR <- '*' !'=' Spacing | |
868 | STAREQU <- '*=' Spacing | |
869 | TILDA <- '~' Spacing | |
870 | ||
871 | EOT <- !. |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "fmt" | |
8 | "io/ioutil" | |
9 | "log" | |
10 | "os" | |
11 | "strings" | |
12 | ) | |
13 | ||
14 | func main() { | |
15 | if len(os.Args) < 2 { | |
16 | fmt.Printf("%v FILE\n", os.Args[0]) | |
17 | os.Exit(1) | |
18 | } | |
19 | ||
20 | var walk func(name string) | |
21 | walk = func(name string) { | |
22 | fileInfo, err := os.Stat(name) | |
23 | if err != nil { | |
24 | log.Fatal(err) | |
25 | } | |
26 | ||
27 | if fileInfo.Mode() & (os.ModeNamedPipe | os.ModeSocket | os.ModeDevice) != 0 { | |
28 | /* will lock up if opened */ | |
29 | } else if fileInfo.IsDir() { | |
30 | fmt.Printf("directory %v\n", name) | |
31 | ||
32 | file, err := os.Open(name) | |
33 | if err != nil { | |
34 | log.Fatal(err) | |
35 | } | |
36 | ||
37 | files, err := file.Readdir(-1) | |
38 | if err != nil { | |
39 | log.Fatal(err) | |
40 | } | |
41 | file.Close() | |
42 | ||
43 | for _, f := range files { | |
44 | if !strings.HasSuffix(name, "/") { | |
45 | name += "/" | |
46 | } | |
47 | walk(name + f.Name()) | |
48 | } | |
49 | } else if strings.HasSuffix(name, ".java") { | |
50 | fmt.Printf("parse %v\n", name) | |
51 | ||
52 | file, err := os.Open(name) | |
53 | if err != nil { | |
54 | log.Fatal(err) | |
55 | } | |
56 | ||
57 | buffer, err := ioutil.ReadAll(file) | |
58 | if err != nil { | |
59 | log.Fatal(err) | |
60 | } | |
61 | file.Close() | |
62 | ||
63 | java := &Java{Buffer: string(buffer)} | |
64 | java.Init() | |
65 | if err := java.Parse(); err != nil { | |
66 | log.Fatal(err) | |
67 | } | |
68 | } | |
69 | } | |
70 | walk(os.Args[1]) | |
71 | } |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | long_test: long.peg.go main.go | |
5 | go build | |
6 | ||
7 | long.peg.go: long.peg | |
8 | peg -switch -inline long.peg | |
9 | ||
10 | clean: | |
11 | rm -f long_test long.peg.go |
0 | # Copyright 2010 The Go Authors. All rights reserved. | |
1 | # Use of this source code is governed by a BSD-style | |
2 | # license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | type Long Peg { | |
7 | ||
8 | } | |
9 | ||
10 | String <- '\"' (!'\"' .)* '\"' !. |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "fmt" | |
8 | "log" | |
9 | ) | |
10 | ||
11 | func main() { | |
12 | expression := "" | |
13 | long := &Long{Buffer: "\"" + expression + "\""} | |
14 | long.Init() | |
15 | for c := 0; c < 100000; c++ { | |
16 | if err := long.Parse(); err != nil { | |
17 | fmt.Printf("%v\n", c) | |
18 | log.Fatal(err) | |
19 | } | |
20 | long.Reset() | |
21 | expression = expression + "X" | |
22 | long.Buffer = "\"" + expression + "\"" | |
23 | } | |
24 | } |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "flag" | |
8 | "fmt" | |
9 | "io/ioutil" | |
10 | "log" | |
11 | "os" | |
12 | "runtime" | |
13 | "time" | |
14 | ) | |
15 | ||
16 | var ( | |
17 | inline = flag.Bool("inline", false, "parse rule inlining") | |
18 | _switch = flag.Bool("switch", false, "replace if-else if-else like blocks with switch blocks") | |
19 | syntax = flag.Bool("syntax", false, "print out the syntax tree") | |
20 | highlight = flag.Bool("highlight", false, "test the syntax highlighter") | |
21 | ast = flag.Bool("ast", false, "generate an AST") | |
22 | test = flag.Bool("test", false, "test the PEG parser performance") | |
23 | print = flag.Bool("print", false, "directly dump the syntax tree") | |
24 | ) | |
25 | ||
26 | func main() { | |
27 | runtime.GOMAXPROCS(2) | |
28 | flag.Parse() | |
29 | ||
30 | if flag.NArg() != 1 { | |
31 | flag.Usage() | |
32 | log.Fatalf("FILE: the peg file to compile") | |
33 | } | |
34 | file := flag.Arg(0) | |
35 | ||
36 | buffer, err := ioutil.ReadFile(file) | |
37 | if err != nil { | |
38 | log.Fatal(err) | |
39 | } | |
40 | ||
41 | if *test { | |
42 | iterations, p := 1000, &Peg{Tree: New(*inline, *_switch), Buffer: string(buffer)} | |
43 | p.Init() | |
44 | start := time.Now() | |
45 | for i := 0; i < iterations; i++ { | |
46 | p.Parse() | |
47 | p.Reset() | |
48 | } | |
49 | total := float64(time.Since(start).Nanoseconds()) / float64(1000) | |
50 | fmt.Printf("time: %v us\n", total/float64(iterations)) | |
51 | return | |
52 | } | |
53 | ||
54 | p := &Peg{Tree: New(*inline, *_switch), Buffer: string(buffer), Pretty: true} | |
55 | p.Init() | |
56 | if err := p.Parse(); err != nil { | |
57 | log.Fatal(err) | |
58 | } | |
59 | ||
60 | p.Execute() | |
61 | ||
62 | if *ast { | |
63 | p.AST().Print(p.Buffer) | |
64 | } | |
65 | if *print { | |
66 | p.Print() | |
67 | } | |
68 | if *syntax { | |
69 | p.PrintSyntaxTree() | |
70 | } | |
71 | if *highlight { | |
72 | p.Highlighter() | |
73 | } | |
74 | ||
75 | filename := file + ".go" | |
76 | out, error := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) | |
77 | if error != nil { | |
78 | fmt.Printf("%v: %v\n", filename, error) | |
79 | return | |
80 | } | |
81 | defer out.Close() | |
82 | p.Compile(filename, out) | |
83 | } |
0 | // Copyright 2010 The Go Authors. All rights reserved. | |
1 | // Use of this source code is governed by a BSD-style | |
2 | // license that can be found in the LICENSE file. | |
3 | ||
4 | package main | |
5 | ||
6 | import ( | |
7 | "bytes" | |
8 | "fmt" | |
9 | "go/parser" | |
10 | "go/printer" | |
11 | "go/token" | |
12 | "io" | |
13 | "math" | |
14 | "os" | |
15 | "strconv" | |
16 | "strings" | |
17 | "text/template" | |
18 | ||
19 | "github.com/pointlander/jetset" | |
20 | ) | |
21 | ||
22 | const pegHeaderTemplate = `package {{.PackageName}} | |
23 | ||
24 | import ( | |
25 | {{range .Imports}}"{{.}}" | |
26 | {{end}} | |
27 | ) | |
28 | ||
29 | const endSymbol rune = {{.EndSymbol}} | |
30 | ||
31 | /* The rule types inferred from the grammar are below. */ | |
32 | type pegRule {{.PegRuleType}} | |
33 | ||
34 | const ( | |
35 | ruleUnknown pegRule = iota | |
36 | {{range .RuleNames}}rule{{.String}} | |
37 | {{end}} | |
38 | rulePre | |
39 | ruleIn | |
40 | ruleSuf | |
41 | ) | |
42 | ||
43 | var rul3s = [...]string { | |
44 | "Unknown", | |
45 | {{range .RuleNames}}"{{.String}}", | |
46 | {{end}} | |
47 | "Pre_", | |
48 | "_In_", | |
49 | "_Suf", | |
50 | } | |
51 | ||
52 | type node32 struct { | |
53 | token32 | |
54 | up, next *node32 | |
55 | } | |
56 | ||
57 | func (node *node32) print(depth int, buffer string) { | |
58 | for node != nil { | |
59 | for c := 0; c < depth; c++ { | |
60 | fmt.Printf(" ") | |
61 | } | |
62 | fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[node.pegRule], strconv.Quote(string(([]rune(buffer)[node.begin:node.end])))) | |
63 | if node.up != nil { | |
64 | node.up.print(depth + 1, buffer) | |
65 | } | |
66 | node = node.next | |
67 | } | |
68 | } | |
69 | ||
70 | func (node *node32) Print(buffer string) { | |
71 | node.print(0, buffer) | |
72 | } | |
73 | ||
74 | type element struct { | |
75 | node *node32 | |
76 | down *element | |
77 | } | |
78 | ||
79 | {{range .Sizes}} | |
80 | ||
81 | /* ${@} bit structure for abstract syntax tree */ | |
82 | type token{{.}} struct { | |
83 | pegRule | |
84 | begin, end, next uint{{.}} | |
85 | } | |
86 | ||
87 | func (t *token{{.}}) isZero() bool { | |
88 | return t.pegRule == ruleUnknown && t.begin == 0 && t.end == 0 && t.next == 0 | |
89 | } | |
90 | ||
91 | func (t *token{{.}}) isParentOf(u token{{.}}) bool { | |
92 | return t.begin <= u.begin && t.end >= u.end && t.next > u.next | |
93 | } | |
94 | ||
95 | func (t *token{{.}}) getToken32() token32 { | |
96 | return token32{pegRule: t.pegRule, begin: uint32(t.begin), end: uint32(t.end), next: uint32(t.next)} | |
97 | } | |
98 | ||
99 | func (t *token{{.}}) String() string { | |
100 | return fmt.Sprintf("\x1B[34m%v\x1B[m %v %v %v", rul3s[t.pegRule], t.begin, t.end, t.next) | |
101 | } | |
102 | ||
103 | type tokens{{.}} struct { | |
104 | tree []token{{.}} | |
105 | ordered [][]token{{.}} | |
106 | } | |
107 | ||
108 | func (t *tokens{{.}}) trim(length int) { | |
109 | t.tree = t.tree[0:length] | |
110 | } | |
111 | ||
112 | func (t *tokens{{.}}) Print() { | |
113 | for _, token := range t.tree { | |
114 | fmt.Println(token.String()) | |
115 | } | |
116 | } | |
117 | ||
118 | func (t *tokens{{.}}) Order() [][]token{{.}} { | |
119 | if t.ordered != nil { | |
120 | return t.ordered | |
121 | } | |
122 | ||
123 | depths := make([]int{{.}}, 1, math.MaxInt16) | |
124 | for i, token := range t.tree { | |
125 | if token.pegRule == ruleUnknown { | |
126 | t.tree = t.tree[:i] | |
127 | break | |
128 | } | |
129 | depth := int(token.next) | |
130 | if length := len(depths); depth >= length { | |
131 | depths = depths[:depth + 1] | |
132 | } | |
133 | depths[depth]++ | |
134 | } | |
135 | depths = append(depths, 0) | |
136 | ||
137 | ordered, pool := make([][]token{{.}}, len(depths)), make([]token{{.}}, len(t.tree) + len(depths)) | |
138 | for i, depth := range depths { | |
139 | depth++ | |
140 | ordered[i], pool, depths[i] = pool[:depth], pool[depth:], 0 | |
141 | } | |
142 | ||
143 | for i, token := range t.tree { | |
144 | depth := token.next | |
145 | token.next = uint{{.}}(i) | |
146 | ordered[depth][depths[depth]] = token | |
147 | depths[depth]++ | |
148 | } | |
149 | t.ordered = ordered | |
150 | return ordered | |
151 | } | |
152 | ||
153 | type state{{.}} struct { | |
154 | token{{.}} | |
155 | depths []int{{.}} | |
156 | leaf bool | |
157 | } | |
158 | ||
159 | func (t *tokens{{.}}) AST() *node32 { | |
160 | tokens := t.Tokens() | |
161 | stack := &element{node: &node32{token32:<-tokens}} | |
162 | for token := range tokens { | |
163 | if token.begin == token.end { | |
164 | continue | |
165 | } | |
166 | node := &node32{token32: token} | |
167 | for stack != nil && stack.node.begin >= token.begin && stack.node.end <= token.end { | |
168 | stack.node.next = node.up | |
169 | node.up = stack.node | |
170 | stack = stack.down | |
171 | } | |
172 | stack = &element{node: node, down: stack} | |
173 | } | |
174 | return stack.node | |
175 | } | |
176 | ||
177 | func (t *tokens{{.}}) PreOrder() (<-chan state{{.}}, [][]token{{.}}) { | |
178 | s, ordered := make(chan state{{.}}, 6), t.Order() | |
179 | go func() { | |
180 | var states [8]state{{.}} | |
181 | for i := range states { | |
182 | states[i].depths = make([]int{{.}}, len(ordered)) | |
183 | } | |
184 | depths, state, depth := make([]int{{.}}, len(ordered)), 0, 1 | |
185 | write := func(t token{{.}}, leaf bool) { | |
186 | S := states[state] | |
187 | state, S.pegRule, S.begin, S.end, S.next, S.leaf = (state + 1) % 8, t.pegRule, t.begin, t.end, uint{{.}}(depth), leaf | |
188 | copy(S.depths, depths) | |
189 | s <- S | |
190 | } | |
191 | ||
192 | states[state].token{{.}} = ordered[0][0] | |
193 | depths[0]++ | |
194 | state++ | |
195 | a, b := ordered[depth - 1][depths[depth - 1] - 1], ordered[depth][depths[depth]] | |
196 | depthFirstSearch: for { | |
197 | for { | |
198 | if i := depths[depth]; i > 0 { | |
199 | if c, j := ordered[depth][i - 1], depths[depth - 1]; a.isParentOf(c) && | |
200 | (j < 2 || !ordered[depth - 1][j - 2].isParentOf(c)) { | |
201 | if c.end != b.begin { | |
202 | write(token{{.}} {pegRule: ruleIn, begin: c.end, end: b.begin}, true) | |
203 | } | |
204 | break | |
205 | } | |
206 | } | |
207 | ||
208 | if a.begin < b.begin { | |
209 | write(token{{.}} {pegRule: rulePre, begin: a.begin, end: b.begin}, true) | |
210 | } | |
211 | break | |
212 | } | |
213 | ||
214 | next := depth + 1 | |
215 | if c := ordered[next][depths[next]]; c.pegRule != ruleUnknown && b.isParentOf(c) { | |
216 | write(b, false) | |
217 | depths[depth]++ | |
218 | depth, a, b = next, b, c | |
219 | continue | |
220 | } | |
221 | ||
222 | write(b, true) | |
223 | depths[depth]++ | |
224 | c, parent := ordered[depth][depths[depth]], true | |
225 | for { | |
226 | if c.pegRule != ruleUnknown && a.isParentOf(c) { | |
227 | b = c | |
228 | continue depthFirstSearch | |
229 | } else if parent && b.end != a.end { | |
230 | write(token{{.}} {pegRule: ruleSuf, begin: b.end, end: a.end}, true) | |
231 | } | |
232 | ||
233 | depth-- | |
234 | if depth > 0 { | |
235 | a, b, c = ordered[depth - 1][depths[depth - 1] - 1], a, ordered[depth][depths[depth]] | |
236 | parent = a.isParentOf(b) | |
237 | continue | |
238 | } | |
239 | ||
240 | break depthFirstSearch | |
241 | } | |
242 | } | |
243 | ||
244 | close(s) | |
245 | }() | |
246 | return s, ordered | |
247 | } | |
248 | ||
249 | func (t *tokens{{.}}) PrintSyntax() { | |
250 | tokens, ordered := t.PreOrder() | |
251 | max := -1 | |
252 | for token := range tokens { | |
253 | if !token.leaf { | |
254 | fmt.Printf("%v", token.begin) | |
255 | for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { | |
256 | fmt.Printf(" \x1B[36m%v\x1B[m", rul3s[ordered[i][depths[i] - 1].pegRule]) | |
257 | } | |
258 | fmt.Printf(" \x1B[36m%v\x1B[m\n", rul3s[token.pegRule]) | |
259 | } else if token.begin == token.end { | |
260 | fmt.Printf("%v", token.begin) | |
261 | for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { | |
262 | fmt.Printf(" \x1B[31m%v\x1B[m", rul3s[ordered[i][depths[i] - 1].pegRule]) | |
263 | } | |
264 | fmt.Printf(" \x1B[31m%v\x1B[m\n", rul3s[token.pegRule]) | |
265 | } else { | |
266 | for c, end := token.begin, token.end; c < end; c++ { | |
267 | if i := int(c); max + 1 < i { | |
268 | for j := max; j < i; j++ { | |
269 | fmt.Printf("skip %v %v\n", j, token.String()) | |
270 | } | |
271 | max = i | |
272 | } else if i := int(c); i <= max { | |
273 | for j := i; j <= max; j++ { | |
274 | fmt.Printf("dupe %v %v\n", j, token.String()) | |
275 | } | |
276 | } else { | |
277 | max = int(c) | |
278 | } | |
279 | fmt.Printf("%v", c) | |
280 | for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { | |
281 | fmt.Printf(" \x1B[34m%v\x1B[m", rul3s[ordered[i][depths[i] - 1].pegRule]) | |
282 | } | |
283 | fmt.Printf(" \x1B[34m%v\x1B[m\n", rul3s[token.pegRule]) | |
284 | } | |
285 | fmt.Printf("\n") | |
286 | } | |
287 | } | |
288 | } | |
289 | ||
290 | func (t *tokens{{.}}) PrintSyntaxTree(buffer string) { | |
291 | tokens, _ := t.PreOrder() | |
292 | for token := range tokens { | |
293 | for c := 0; c < int(token.next); c++ { | |
294 | fmt.Printf(" ") | |
295 | } | |
296 | fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[token.pegRule], strconv.Quote(string(([]rune(buffer)[token.begin:token.end])))) | |
297 | } | |
298 | } | |
299 | ||
300 | func (t *tokens{{.}}) Add(rule pegRule, begin, end, depth uint32, index int) { | |
301 | t.tree[index] = token{{.}}{pegRule: rule, begin: uint{{.}}(begin), end: uint{{.}}(end), next: uint{{.}}(depth)} | |
302 | } | |
303 | ||
304 | func (t *tokens{{.}}) Tokens() <-chan token32 { | |
305 | s := make(chan token32, 16) | |
306 | go func() { | |
307 | for _, v := range t.tree { | |
308 | s <- v.getToken32() | |
309 | } | |
310 | close(s) | |
311 | }() | |
312 | return s | |
313 | } | |
314 | ||
315 | func (t *tokens{{.}}) Error() []token32 { | |
316 | ordered := t.Order() | |
317 | length := len(ordered) | |
318 | tokens, length := make([]token32, length), length - 1 | |
319 | for i := range tokens { | |
320 | o := ordered[length - i] | |
321 | if len(o) > 1 { | |
322 | tokens[i] = o[len(o) - 2].getToken32() | |
323 | } | |
324 | } | |
325 | return tokens | |
326 | } | |
327 | {{end}} | |
328 | ||
329 | func (t *tokens32) Expand(index int) { | |
330 | tree := t.tree | |
331 | if index >= len(tree) { | |
332 | expanded := make([]token32, 2 * len(tree)) | |
333 | copy(expanded, tree) | |
334 | t.tree = expanded | |
335 | } | |
336 | } | |
337 | ||
338 | type {{.StructName}} struct { | |
339 | {{.StructVariables}} | |
340 | Buffer string | |
341 | buffer []rune | |
342 | rules [{{.RulesCount}}]func() bool | |
343 | Parse func(rule ...int) error | |
344 | Reset func() | |
345 | Pretty bool | |
346 | tokens32 | |
347 | } | |
348 | ||
349 | type textPosition struct { | |
350 | line, symbol int | |
351 | } | |
352 | ||
353 | type textPositionMap map[int] textPosition | |
354 | ||
355 | func translatePositions(buffer []rune, positions []int) textPositionMap { | |
356 | length, translations, j, line, symbol := len(positions), make(textPositionMap, len(positions)), 0, 1, 0 | |
357 | sort.Ints(positions) | |
358 | ||
359 | search: for i, c := range buffer { | |
360 | if c == '\n' {line, symbol = line + 1, 0} else {symbol++} | |
361 | if i == positions[j] { | |
362 | translations[positions[j]] = textPosition{line, symbol} | |
363 | for j++; j < length; j++ {if i != positions[j] {continue search}} | |
364 | break search | |
365 | } | |
366 | } | |
367 | ||
368 | return translations | |
369 | } | |
370 | ||
371 | type parseError struct { | |
372 | p *{{.StructName}} | |
373 | max token32 | |
374 | } | |
375 | ||
376 | func (e *parseError) Error() string { | |
377 | tokens, error := []token32{e.max}, "\n" | |
378 | positions, p := make([]int, 2 * len(tokens)), 0 | |
379 | for _, token := range tokens { | |
380 | positions[p], p = int(token.begin), p + 1 | |
381 | positions[p], p = int(token.end), p + 1 | |
382 | } | |
383 | translations := translatePositions(e.p.buffer, positions) | |
384 | format := "parse error near %v (line %v symbol %v - line %v symbol %v):\n%v\n" | |
385 | if e.p.Pretty { | |
386 | format = "parse error near \x1B[34m%v\x1B[m (line %v symbol %v - line %v symbol %v):\n%v\n" | |
387 | } | |
388 | for _, token := range tokens { | |
389 | begin, end := int(token.begin), int(token.end) | |
390 | error += fmt.Sprintf(format, | |
391 | rul3s[token.pegRule], | |
392 | translations[begin].line, translations[begin].symbol, | |
393 | translations[end].line, translations[end].symbol, | |
394 | strconv.Quote(string(e.p.buffer[begin:end]))) | |
395 | } | |
396 | ||
397 | return error | |
398 | } | |
399 | ||
400 | func (p *{{.StructName}}) PrintSyntaxTree() { | |
401 | p.tokens32.PrintSyntaxTree(p.Buffer) | |
402 | } | |
403 | ||
404 | func (p *{{.StructName}}) Highlighter() { | |
405 | p.PrintSyntax() | |
406 | } | |
407 | ||
408 | {{if .HasActions}} | |
409 | func (p *{{.StructName}}) Execute() { | |
410 | buffer, _buffer, text, begin, end := p.Buffer, p.buffer, "", 0, 0 | |
411 | for token := range p.Tokens() { | |
412 | switch (token.pegRule) { | |
413 | {{if .HasPush}} | |
414 | case rulePegText: | |
415 | begin, end = int(token.begin), int(token.end) | |
416 | text = string(_buffer[begin:end]) | |
417 | {{end}} | |
418 | {{range .Actions}}case ruleAction{{.GetId}}: | |
419 | {{.String}} | |
420 | {{end}} | |
421 | } | |
422 | } | |
423 | _, _, _, _, _ = buffer, _buffer, text, begin, end | |
424 | } | |
425 | {{end}} | |
426 | ||
427 | func (p *{{.StructName}}) Init() { | |
428 | p.buffer = []rune(p.Buffer) | |
429 | if len(p.buffer) == 0 || p.buffer[len(p.buffer) - 1] != endSymbol { | |
430 | p.buffer = append(p.buffer, endSymbol) | |
431 | } | |
432 | ||
433 | tree := tokens32{tree: make([]token32, math.MaxInt16)} | |
434 | var max token32 | |
435 | position, depth, tokenIndex, buffer, _rules := uint32(0), uint32(0), 0, p.buffer, p.rules | |
436 | ||
437 | p.Parse = func(rule ...int) error { | |
438 | r := 1 | |
439 | if len(rule) > 0 { | |
440 | r = rule[0] | |
441 | } | |
442 | matches := p.rules[r]() | |
443 | p.tokens32 = tree | |
444 | if matches { | |
445 | p.trim(tokenIndex) | |
446 | return nil | |
447 | } | |
448 | return &parseError{p, max} | |
449 | } | |
450 | ||
451 | p.Reset = func() { | |
452 | position, tokenIndex, depth = 0, 0, 0 | |
453 | } | |
454 | ||
455 | add := func(rule pegRule, begin uint32) { | |
456 | tree.Expand(tokenIndex) | |
457 | tree.Add(rule, begin, position, depth, tokenIndex) | |
458 | tokenIndex++ | |
459 | if begin != position && position > max.end { | |
460 | max = token32{rule, begin, position, depth} | |
461 | } | |
462 | } | |
463 | ||
464 | {{if .HasDot}} | |
465 | matchDot := func() bool { | |
466 | if buffer[position] != endSymbol { | |
467 | position++ | |
468 | return true | |
469 | } | |
470 | return false | |
471 | } | |
472 | {{end}} | |
473 | ||
474 | {{if .HasCharacter}} | |
475 | /*matchChar := func(c byte) bool { | |
476 | if buffer[position] == c { | |
477 | position++ | |
478 | return true | |
479 | } | |
480 | return false | |
481 | }*/ | |
482 | {{end}} | |
483 | ||
484 | {{if .HasString}} | |
485 | matchString := func(s string) bool { | |
486 | i := position | |
487 | for _, c := range s { | |
488 | if buffer[i] != c { | |
489 | return false | |
490 | } | |
491 | i++ | |
492 | } | |
493 | position = i | |
494 | return true | |
495 | } | |
496 | {{end}} | |
497 | ||
498 | {{if .HasRange}} | |
499 | /*matchRange := func(lower byte, upper byte) bool { | |
500 | if c := buffer[position]; c >= lower && c <= upper { | |
501 | position++ | |
502 | return true | |
503 | } | |
504 | return false | |
505 | }*/ | |
506 | {{end}} | |
507 | ||
508 | _rules = [...]func() bool { | |
509 | nil,` | |
510 | ||
511 | type Type uint8 | |
512 | ||
513 | const ( | |
514 | TypeUnknown Type = iota | |
515 | TypeRule | |
516 | TypeName | |
517 | TypeDot | |
518 | TypeCharacter | |
519 | TypeRange | |
520 | TypeString | |
521 | TypePredicate | |
522 | TypeStateChange | |
523 | TypeCommit | |
524 | TypeAction | |
525 | TypePackage | |
526 | TypeImport | |
527 | TypeState | |
528 | TypeAlternate | |
529 | TypeUnorderedAlternate | |
530 | TypeSequence | |
531 | TypePeekFor | |
532 | TypePeekNot | |
533 | TypeQuery | |
534 | TypeStar | |
535 | TypePlus | |
536 | TypePeg | |
537 | TypePush | |
538 | TypeImplicitPush | |
539 | TypeNil | |
540 | TypeLast | |
541 | ) | |
542 | ||
543 | var TypeMap = [...]string{ | |
544 | "TypeUnknown", | |
545 | "TypeRule", | |
546 | "TypeName", | |
547 | "TypeDot", | |
548 | "TypeCharacter", | |
549 | "TypeRange", | |
550 | "TypeString", | |
551 | "TypePredicate", | |
552 | "TypeCommit", | |
553 | "TypeAction", | |
554 | "TypePackage", | |
555 | "TypeImport", | |
556 | "TypeState", | |
557 | "TypeAlternate", | |
558 | "TypeUnorderedAlternate", | |
559 | "TypeSequence", | |
560 | "TypePeekFor", | |
561 | "TypePeekNot", | |
562 | "TypeQuery", | |
563 | "TypeStar", | |
564 | "TypePlus", | |
565 | "TypePeg", | |
566 | "TypePush", | |
567 | "TypeImplicitPush", | |
568 | "TypeNil", | |
569 | "TypeLast"} | |
570 | ||
571 | func (t Type) GetType() Type { | |
572 | return t | |
573 | } | |
574 | ||
575 | type Node interface { | |
576 | fmt.Stringer | |
577 | debug() | |
578 | ||
579 | Escaped() string | |
580 | SetString(s string) | |
581 | ||
582 | GetType() Type | |
583 | SetType(t Type) | |
584 | ||
585 | GetId() int | |
586 | SetId(id int) | |
587 | ||
588 | Init() | |
589 | Front() *node | |
590 | Next() *node | |
591 | PushFront(value *node) | |
592 | PopFront() *node | |
593 | PushBack(value *node) | |
594 | Len() int | |
595 | Copy() *node | |
596 | Slice() []*node | |
597 | } | |
598 | ||
599 | type node struct { | |
600 | Type | |
601 | string | |
602 | id int | |
603 | ||
604 | front *node | |
605 | back *node | |
606 | length int | |
607 | ||
608 | /* use hash table here instead of Copy? */ | |
609 | next *node | |
610 | } | |
611 | ||
612 | func (n *node) String() string { | |
613 | return n.string | |
614 | } | |
615 | ||
616 | func (n *node) debug() { | |
617 | if len(n.string) == 1 { | |
618 | fmt.Printf("%v %v '%v' %d\n", n.id, TypeMap[n.Type], n.string, n.string[0]) | |
619 | } else { | |
620 | fmt.Printf("%v %v '%v'\n", n.id, TypeMap[n.Type], n.string) | |
621 | } | |
622 | } | |
623 | ||
624 | func (n *node) Escaped() string { | |
625 | return escape(n.string) | |
626 | } | |
627 | ||
628 | func (n *node) SetString(s string) { | |
629 | n.string = s | |
630 | } | |
631 | ||
632 | func (n *node) SetType(t Type) { | |
633 | n.Type = t | |
634 | } | |
635 | ||
636 | func (n *node) GetId() int { | |
637 | return n.id | |
638 | } | |
639 | ||
640 | func (n *node) SetId(id int) { | |
641 | n.id = id | |
642 | } | |
643 | ||
644 | func (n *node) Init() { | |
645 | n.front = nil | |
646 | n.back = nil | |
647 | n.length = 0 | |
648 | } | |
649 | ||
650 | func (n *node) Front() *node { | |
651 | return n.front | |
652 | } | |
653 | ||
654 | func (n *node) Next() *node { | |
655 | return n.next | |
656 | } | |
657 | ||
658 | func (n *node) PushFront(value *node) { | |
659 | if n.back == nil { | |
660 | n.back = value | |
661 | } else { | |
662 | value.next = n.front | |
663 | } | |
664 | n.front = value | |
665 | n.length++ | |
666 | } | |
667 | ||
668 | func (n *node) PopFront() *node { | |
669 | front := n.front | |
670 | ||
671 | switch true { | |
672 | case front == nil: | |
673 | panic("tree is empty") | |
674 | case front == n.back: | |
675 | n.front, n.back = nil, nil | |
676 | default: | |
677 | n.front, front.next = front.next, nil | |
678 | } | |
679 | ||
680 | n.length-- | |
681 | return front | |
682 | } | |
683 | ||
684 | func (n *node) PushBack(value *node) { | |
685 | if n.front == nil { | |
686 | n.front = value | |
687 | } else { | |
688 | n.back.next = value | |
689 | } | |
690 | n.back = value | |
691 | n.length++ | |
692 | } | |
693 | ||
694 | func (n *node) Len() (c int) { | |
695 | return n.length | |
696 | } | |
697 | ||
698 | func (n *node) Copy() *node { | |
699 | return &node{Type: n.Type, string: n.string, id: n.id, front: n.front, back: n.back, length: n.length} | |
700 | } | |
701 | ||
702 | func (n *node) Slice() []*node { | |
703 | s := make([]*node, n.length) | |
704 | for element, i := n.Front(), 0; element != nil; element, i = element.Next(), i+1 { | |
705 | s[i] = element | |
706 | } | |
707 | return s | |
708 | } | |
709 | ||
710 | /* A tree data structure into which a PEG can be parsed. */ | |
711 | type Tree struct { | |
712 | Rules map[string]Node | |
713 | rulesCount map[string]uint | |
714 | node | |
715 | inline, _switch bool | |
716 | ||
717 | RuleNames []Node | |
718 | Sizes [1]int | |
719 | PackageName string | |
720 | Imports []string | |
721 | EndSymbol rune | |
722 | PegRuleType string | |
723 | StructName string | |
724 | StructVariables string | |
725 | RulesCount int | |
726 | Bits int | |
727 | HasActions bool | |
728 | Actions []Node | |
729 | HasPush bool | |
730 | HasCommit bool | |
731 | HasDot bool | |
732 | HasCharacter bool | |
733 | HasString bool | |
734 | HasRange bool | |
735 | } | |
736 | ||
737 | func New(inline, _switch bool) *Tree { | |
738 | return &Tree{Rules: make(map[string]Node), | |
739 | Sizes: [1]int{32}, | |
740 | rulesCount: make(map[string]uint), | |
741 | inline: inline, | |
742 | _switch: _switch} | |
743 | } | |
744 | ||
745 | func (t *Tree) AddRule(name string) { | |
746 | t.PushFront(&node{Type: TypeRule, string: name, id: t.RulesCount}) | |
747 | t.RulesCount++ | |
748 | } | |
749 | ||
750 | func (t *Tree) AddExpression() { | |
751 | expression := t.PopFront() | |
752 | rule := t.PopFront() | |
753 | rule.PushBack(expression) | |
754 | t.PushBack(rule) | |
755 | } | |
756 | ||
757 | func (t *Tree) AddName(text string) { | |
758 | t.PushFront(&node{Type: TypeName, string: text}) | |
759 | } | |
760 | ||
761 | func (t *Tree) AddDot() { t.PushFront(&node{Type: TypeDot, string: "."}) } | |
762 | func (t *Tree) AddCharacter(text string) { | |
763 | t.PushFront(&node{Type: TypeCharacter, string: text}) | |
764 | } | |
765 | func (t *Tree) AddDoubleCharacter(text string) { | |
766 | t.PushFront(&node{Type: TypeCharacter, string: strings.ToLower(text)}) | |
767 | t.PushFront(&node{Type: TypeCharacter, string: strings.ToUpper(text)}) | |
768 | t.AddAlternate() | |
769 | } | |
770 | func (t *Tree) AddHexaCharacter(text string) { | |
771 | hexa, _ := strconv.ParseInt(text, 16, 32) | |
772 | t.PushFront(&node{Type: TypeCharacter, string: string(hexa)}) | |
773 | } | |
774 | func (t *Tree) AddOctalCharacter(text string) { | |
775 | octal, _ := strconv.ParseInt(text, 8, 8) | |
776 | t.PushFront(&node{Type: TypeCharacter, string: string(octal)}) | |
777 | } | |
778 | func (t *Tree) AddPredicate(text string) { t.PushFront(&node{Type: TypePredicate, string: text}) } | |
779 | func (t *Tree) AddStateChange(text string) { t.PushFront(&node{Type: TypeStateChange, string: text}) } | |
780 | func (t *Tree) AddNil() { t.PushFront(&node{Type: TypeNil, string: "<nil>"}) } | |
781 | func (t *Tree) AddAction(text string) { t.PushFront(&node{Type: TypeAction, string: text}) } | |
782 | func (t *Tree) AddPackage(text string) { t.PushBack(&node{Type: TypePackage, string: text}) } | |
783 | func (t *Tree) AddImport(text string) { t.PushBack(&node{Type: TypeImport, string: text}) } | |
784 | func (t *Tree) AddState(text string) { | |
785 | peg := t.PopFront() | |
786 | peg.PushBack(&node{Type: TypeState, string: text}) | |
787 | t.PushBack(peg) | |
788 | } | |
789 | ||
790 | func (t *Tree) addList(listType Type) { | |
791 | a := t.PopFront() | |
792 | b := t.PopFront() | |
793 | var l *node | |
794 | if b.GetType() == listType { | |
795 | l = b | |
796 | } else { | |
797 | l = &node{Type: listType} | |
798 | l.PushBack(b) | |
799 | } | |
800 | l.PushBack(a) | |
801 | t.PushFront(l) | |
802 | } | |
803 | func (t *Tree) AddAlternate() { t.addList(TypeAlternate) } | |
804 | func (t *Tree) AddSequence() { t.addList(TypeSequence) } | |
805 | func (t *Tree) AddRange() { t.addList(TypeRange) } | |
806 | func (t *Tree) AddDoubleRange() { | |
807 | a := t.PopFront() | |
808 | b := t.PopFront() | |
809 | ||
810 | t.AddCharacter(strings.ToLower(b.String())) | |
811 | t.AddCharacter(strings.ToLower(a.String())) | |
812 | t.addList(TypeRange) | |
813 | ||
814 | t.AddCharacter(strings.ToUpper(b.String())) | |
815 | t.AddCharacter(strings.ToUpper(a.String())) | |
816 | t.addList(TypeRange) | |
817 | ||
818 | t.AddAlternate() | |
819 | } | |
820 | ||
821 | func (t *Tree) addFix(fixType Type) { | |
822 | n := &node{Type: fixType} | |
823 | n.PushBack(t.PopFront()) | |
824 | t.PushFront(n) | |
825 | } | |
826 | func (t *Tree) AddPeekFor() { t.addFix(TypePeekFor) } | |
827 | func (t *Tree) AddPeekNot() { t.addFix(TypePeekNot) } | |
828 | func (t *Tree) AddQuery() { t.addFix(TypeQuery) } | |
829 | func (t *Tree) AddStar() { t.addFix(TypeStar) } | |
830 | func (t *Tree) AddPlus() { t.addFix(TypePlus) } | |
831 | func (t *Tree) AddPush() { t.addFix(TypePush) } | |
832 | ||
833 | func (t *Tree) AddPeg(text string) { t.PushFront(&node{Type: TypePeg, string: text}) } | |
834 | ||
835 | func join(tasks []func()) { | |
836 | length := len(tasks) | |
837 | done := make(chan int, length) | |
838 | for _, task := range tasks { | |
839 | go func(task func()) { task(); done <- 1 }(task) | |
840 | } | |
841 | for d := <-done; d < length; d += <-done { | |
842 | } | |
843 | } | |
844 | ||
845 | func escape(c string) string { | |
846 | switch c { | |
847 | case "'": | |
848 | return "\\'" | |
849 | case "\"": | |
850 | return "\"" | |
851 | default: | |
852 | c = strconv.Quote(c) | |
853 | return c[1 : len(c)-1] | |
854 | } | |
855 | } | |
856 | ||
857 | func (t *Tree) Compile(file string, out io.Writer) { | |
858 | t.AddImport("fmt") | |
859 | t.AddImport("math") | |
860 | t.AddImport("sort") | |
861 | t.AddImport("strconv") | |
862 | t.EndSymbol = 0x110000 | |
863 | t.RulesCount++ | |
864 | ||
865 | counts := [TypeLast]uint{} | |
866 | { | |
867 | var rule *node | |
868 | var link func(node Node) | |
869 | link = func(n Node) { | |
870 | nodeType := n.GetType() | |
871 | id := counts[nodeType] | |
872 | counts[nodeType]++ | |
873 | switch nodeType { | |
874 | case TypeAction: | |
875 | n.SetId(int(id)) | |
876 | copy, name := n.Copy(), fmt.Sprintf("Action%v", id) | |
877 | t.Actions = append(t.Actions, copy) | |
878 | n.Init() | |
879 | n.SetType(TypeName) | |
880 | n.SetString(name) | |
881 | n.SetId(t.RulesCount) | |
882 | ||
883 | emptyRule := &node{Type: TypeRule, string: name, id: t.RulesCount} | |
884 | implicitPush := &node{Type: TypeImplicitPush} | |
885 | emptyRule.PushBack(implicitPush) | |
886 | implicitPush.PushBack(copy) | |
887 | implicitPush.PushBack(emptyRule.Copy()) | |
888 | t.PushBack(emptyRule) | |
889 | t.RulesCount++ | |
890 | ||
891 | t.Rules[name] = emptyRule | |
892 | t.RuleNames = append(t.RuleNames, emptyRule) | |
893 | case TypeName: | |
894 | name := n.String() | |
895 | if _, ok := t.Rules[name]; !ok { | |
896 | emptyRule := &node{Type: TypeRule, string: name, id: t.RulesCount} | |
897 | implicitPush := &node{Type: TypeImplicitPush} | |
898 | emptyRule.PushBack(implicitPush) | |
899 | implicitPush.PushBack(&node{Type: TypeNil, string: "<nil>"}) | |
900 | implicitPush.PushBack(emptyRule.Copy()) | |
901 | t.PushBack(emptyRule) | |
902 | t.RulesCount++ | |
903 | ||
904 | t.Rules[name] = emptyRule | |
905 | t.RuleNames = append(t.RuleNames, emptyRule) | |
906 | } | |
907 | case TypePush: | |
908 | copy, name := rule.Copy(), "PegText" | |
909 | copy.SetString(name) | |
910 | if _, ok := t.Rules[name]; !ok { | |
911 | emptyRule := &node{Type: TypeRule, string: name, id: t.RulesCount} | |
912 | emptyRule.PushBack(&node{Type: TypeNil, string: "<nil>"}) | |
913 | t.PushBack(emptyRule) | |
914 | t.RulesCount++ | |
915 | ||
916 | t.Rules[name] = emptyRule | |
917 | t.RuleNames = append(t.RuleNames, emptyRule) | |
918 | } | |
919 | n.PushBack(copy) | |
920 | fallthrough | |
921 | case TypeImplicitPush: | |
922 | link(n.Front()) | |
923 | case TypeRule, TypeAlternate, TypeUnorderedAlternate, TypeSequence, | |
924 | TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: | |
925 | for _, node := range n.Slice() { | |
926 | link(node) | |
927 | } | |
928 | } | |
929 | } | |
930 | /* first pass */ | |
931 | for _, node := range t.Slice() { | |
932 | switch node.GetType() { | |
933 | case TypePackage: | |
934 | t.PackageName = node.String() | |
935 | case TypeImport: | |
936 | t.Imports = append(t.Imports, node.String()) | |
937 | case TypePeg: | |
938 | t.StructName = node.String() | |
939 | t.StructVariables = node.Front().String() | |
940 | case TypeRule: | |
941 | if _, ok := t.Rules[node.String()]; !ok { | |
942 | expression := node.Front() | |
943 | copy := expression.Copy() | |
944 | expression.Init() | |
945 | expression.SetType(TypeImplicitPush) | |
946 | expression.PushBack(copy) | |
947 | expression.PushBack(node.Copy()) | |
948 | ||
949 | t.Rules[node.String()] = node | |
950 | t.RuleNames = append(t.RuleNames, node) | |
951 | } | |
952 | } | |
953 | } | |
954 | /* second pass */ | |
955 | for _, node := range t.Slice() { | |
956 | if node.GetType() == TypeRule { | |
957 | rule = node | |
958 | link(node) | |
959 | } | |
960 | } | |
961 | } | |
962 | ||
963 | join([]func(){ | |
964 | func() { | |
965 | var countRules func(node Node) | |
966 | ruleReached := make([]bool, t.RulesCount) | |
967 | countRules = func(node Node) { | |
968 | switch node.GetType() { | |
969 | case TypeRule: | |
970 | name, id := node.String(), node.GetId() | |
971 | if count, ok := t.rulesCount[name]; ok { | |
972 | t.rulesCount[name] = count + 1 | |
973 | } else { | |
974 | t.rulesCount[name] = 1 | |
975 | } | |
976 | if ruleReached[id] { | |
977 | return | |
978 | } | |
979 | ruleReached[id] = true | |
980 | countRules(node.Front()) | |
981 | case TypeName: | |
982 | countRules(t.Rules[node.String()]) | |
983 | case TypeImplicitPush, TypePush: | |
984 | countRules(node.Front()) | |
985 | case TypeAlternate, TypeUnorderedAlternate, TypeSequence, | |
986 | TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: | |
987 | for _, element := range node.Slice() { | |
988 | countRules(element) | |
989 | } | |
990 | } | |
991 | } | |
992 | for _, node := range t.Slice() { | |
993 | if node.GetType() == TypeRule { | |
994 | countRules(node) | |
995 | break | |
996 | } | |
997 | } | |
998 | }, | |
999 | func() { | |
1000 | var checkRecursion func(node Node) bool | |
1001 | ruleReached := make([]bool, t.RulesCount) | |
1002 | checkRecursion = func(node Node) bool { | |
1003 | switch node.GetType() { | |
1004 | case TypeRule: | |
1005 | id := node.GetId() | |
1006 | if ruleReached[id] { | |
1007 | fmt.Fprintf(os.Stderr, "possible infinite left recursion in rule '%v'\n", node) | |
1008 | return false | |
1009 | } | |
1010 | ruleReached[id] = true | |
1011 | consumes := checkRecursion(node.Front()) | |
1012 | ruleReached[id] = false | |
1013 | return consumes | |
1014 | case TypeAlternate: | |
1015 | for _, element := range node.Slice() { | |
1016 | if !checkRecursion(element) { | |
1017 | return false | |
1018 | } | |
1019 | } | |
1020 | return true | |
1021 | case TypeSequence: | |
1022 | for _, element := range node.Slice() { | |
1023 | if checkRecursion(element) { | |
1024 | return true | |
1025 | } | |
1026 | } | |
1027 | case TypeName: | |
1028 | return checkRecursion(t.Rules[node.String()]) | |
1029 | case TypePlus, TypePush, TypeImplicitPush: | |
1030 | return checkRecursion(node.Front()) | |
1031 | case TypeCharacter, TypeString: | |
1032 | return len(node.String()) > 0 | |
1033 | case TypeDot, TypeRange: | |
1034 | return true | |
1035 | } | |
1036 | return false | |
1037 | } | |
1038 | for _, node := range t.Slice() { | |
1039 | if node.GetType() == TypeRule { | |
1040 | checkRecursion(node) | |
1041 | } | |
1042 | } | |
1043 | }}) | |
1044 | ||
1045 | if t._switch { | |
1046 | var optimizeAlternates func(node Node) (consumes bool, s jetset.Set) | |
1047 | cache, firstPass := make([]struct { | |
1048 | reached, consumes bool | |
1049 | s jetset.Set | |
1050 | }, t.RulesCount), true | |
1051 | optimizeAlternates = func(n Node) (consumes bool, s jetset.Set) { | |
1052 | /*n.debug()*/ | |
1053 | switch n.GetType() { | |
1054 | case TypeRule: | |
1055 | cache := &cache[n.GetId()] | |
1056 | if cache.reached { | |
1057 | consumes, s = cache.consumes, cache.s | |
1058 | return | |
1059 | } | |
1060 | ||
1061 | cache.reached = true | |
1062 | consumes, s = optimizeAlternates(n.Front()) | |
1063 | cache.consumes, cache.s = consumes, s | |
1064 | case TypeName: | |
1065 | consumes, s = optimizeAlternates(t.Rules[n.String()]) | |
1066 | case TypeDot: | |
1067 | consumes = true | |
1068 | /* TypeDot set doesn't include the EndSymbol */ | |
1069 | s = s.Add(uint64(t.EndSymbol)) | |
1070 | s = s.Complement(uint64(t.EndSymbol)) | |
1071 | case TypeString, TypeCharacter: | |
1072 | consumes = true | |
1073 | s = s.Add(uint64([]rune(n.String())[0])) | |
1074 | case TypeRange: | |
1075 | consumes = true | |
1076 | element := n.Front() | |
1077 | lower := []rune(element.String())[0] | |
1078 | element = element.Next() | |
1079 | upper := []rune(element.String())[0] | |
1080 | s = s.AddRange(uint64(lower), uint64(upper)) | |
1081 | case TypeAlternate: | |
1082 | consumes = true | |
1083 | mconsumes, properties, c := | |
1084 | consumes, make([]struct { | |
1085 | intersects bool | |
1086 | s jetset.Set | |
1087 | }, n.Len()), 0 | |
1088 | for _, element := range n.Slice() { | |
1089 | mconsumes, properties[c].s = optimizeAlternates(element) | |
1090 | consumes = consumes && mconsumes | |
1091 | s = s.Union(properties[c].s) | |
1092 | c++ | |
1093 | } | |
1094 | ||
1095 | if firstPass { | |
1096 | break | |
1097 | } | |
1098 | ||
1099 | intersections := 2 | |
1100 | compare: | |
1101 | for ai, a := range properties[0 : len(properties)-1] { | |
1102 | for _, b := range properties[ai+1:] { | |
1103 | if a.s.Intersects(b.s) { | |
1104 | intersections++ | |
1105 | properties[ai].intersects = true | |
1106 | continue compare | |
1107 | } | |
1108 | } | |
1109 | } | |
1110 | if intersections >= len(properties) { | |
1111 | break | |
1112 | } | |
1113 | ||
1114 | c, unordered, ordered, max := | |
1115 | 0, &node{Type: TypeUnorderedAlternate}, &node{Type: TypeAlternate}, 0 | |
1116 | for _, element := range n.Slice() { | |
1117 | if properties[c].intersects { | |
1118 | ordered.PushBack(element.Copy()) | |
1119 | } else { | |
1120 | class := &node{Type: TypeUnorderedAlternate} | |
1121 | for d := 0; d < 256; d++ { | |
1122 | if properties[c].s.Has(uint64(d)) { | |
1123 | class.PushBack(&node{Type: TypeCharacter, string: string(d)}) | |
1124 | } | |
1125 | } | |
1126 | ||
1127 | sequence, predicate, length := | |
1128 | &node{Type: TypeSequence}, &node{Type: TypePeekFor}, properties[c].s.Len() | |
1129 | if length == 0 { | |
1130 | class.PushBack(&node{Type: TypeNil, string: "<nil>"}) | |
1131 | } | |
1132 | predicate.PushBack(class) | |
1133 | sequence.PushBack(predicate) | |
1134 | sequence.PushBack(element.Copy()) | |
1135 | ||
1136 | if element.GetType() == TypeNil { | |
1137 | unordered.PushBack(sequence) | |
1138 | } else if length > max { | |
1139 | unordered.PushBack(sequence) | |
1140 | max = length | |
1141 | } else { | |
1142 | unordered.PushFront(sequence) | |
1143 | } | |
1144 | } | |
1145 | c++ | |
1146 | } | |
1147 | n.Init() | |
1148 | if ordered.Front() == nil { | |
1149 | n.SetType(TypeUnorderedAlternate) | |
1150 | for _, element := range unordered.Slice() { | |
1151 | n.PushBack(element.Copy()) | |
1152 | } | |
1153 | } else { | |
1154 | for _, element := range ordered.Slice() { | |
1155 | n.PushBack(element.Copy()) | |
1156 | } | |
1157 | n.PushBack(unordered) | |
1158 | } | |
1159 | case TypeSequence: | |
1160 | classes, elements := | |
1161 | make([]struct { | |
1162 | s jetset.Set | |
1163 | }, n.Len()), n.Slice() | |
1164 | ||
1165 | for c, element := range elements { | |
1166 | consumes, classes[c].s = optimizeAlternates(element) | |
1167 | if consumes { | |
1168 | elements, classes = elements[c+1:], classes[:c+1] | |
1169 | break | |
1170 | } | |
1171 | } | |
1172 | ||
1173 | for c := len(classes) - 1; c >= 0; c-- { | |
1174 | s = s.Union(classes[c].s) | |
1175 | } | |
1176 | ||
1177 | for _, element := range elements { | |
1178 | optimizeAlternates(element) | |
1179 | } | |
1180 | case TypePeekNot, TypePeekFor: | |
1181 | optimizeAlternates(n.Front()) | |
1182 | case TypeQuery, TypeStar: | |
1183 | _, s = optimizeAlternates(n.Front()) | |
1184 | case TypePlus, TypePush, TypeImplicitPush: | |
1185 | consumes, s = optimizeAlternates(n.Front()) | |
1186 | case TypeAction, TypeNil: | |
1187 | //empty | |
1188 | } | |
1189 | return | |
1190 | } | |
1191 | for _, element := range t.Slice() { | |
1192 | if element.GetType() == TypeRule { | |
1193 | optimizeAlternates(element) | |
1194 | break | |
1195 | } | |
1196 | } | |
1197 | ||
1198 | for i, _ := range cache { | |
1199 | cache[i].reached = false | |
1200 | } | |
1201 | firstPass = false | |
1202 | for _, element := range t.Slice() { | |
1203 | if element.GetType() == TypeRule { | |
1204 | optimizeAlternates(element) | |
1205 | break | |
1206 | } | |
1207 | } | |
1208 | } | |
1209 | ||
1210 | var buffer bytes.Buffer | |
1211 | defer func() { | |
1212 | fileSet := token.NewFileSet() | |
1213 | code, error := parser.ParseFile(fileSet, file, &buffer, parser.ParseComments) | |
1214 | if error != nil { | |
1215 | buffer.WriteTo(out) | |
1216 | fmt.Printf("%v: %v\n", file, error) | |
1217 | return | |
1218 | } | |
1219 | formatter := printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8} | |
1220 | error = formatter.Fprint(out, fileSet, code) | |
1221 | if error != nil { | |
1222 | buffer.WriteTo(out) | |
1223 | fmt.Printf("%v: %v\n", file, error) | |
1224 | return | |
1225 | } | |
1226 | ||
1227 | }() | |
1228 | ||
1229 | _print := func(format string, a ...interface{}) { fmt.Fprintf(&buffer, format, a...) } | |
1230 | printSave := func(n uint) { _print("\n position%d, tokenIndex%d, depth%d := position, tokenIndex, depth", n, n, n) } | |
1231 | printRestore := func(n uint) { _print("\n position, tokenIndex, depth = position%d, tokenIndex%d, depth%d", n, n, n) } | |
1232 | printTemplate := func(s string) { | |
1233 | if error := template.Must(template.New("peg").Parse(s)).Execute(&buffer, t); error != nil { | |
1234 | panic(error) | |
1235 | } | |
1236 | } | |
1237 | ||
1238 | t.HasActions = counts[TypeAction] > 0 | |
1239 | t.HasPush = counts[TypePush] > 0 | |
1240 | t.HasCommit = counts[TypeCommit] > 0 | |
1241 | t.HasDot = counts[TypeDot] > 0 | |
1242 | t.HasCharacter = counts[TypeCharacter] > 0 | |
1243 | t.HasString = counts[TypeString] > 0 | |
1244 | t.HasRange = counts[TypeRange] > 0 | |
1245 | ||
1246 | var printRule func(n Node) | |
1247 | var compile func(expression Node, ko uint) | |
1248 | var label uint | |
1249 | labels := make(map[uint]bool) | |
1250 | printBegin := func() { _print("\n {") } | |
1251 | printEnd := func() { _print("\n }") } | |
1252 | printLabel := func(n uint) { | |
1253 | _print("\n") | |
1254 | if labels[n] { | |
1255 | _print(" l%d:\t", n) | |
1256 | } | |
1257 | } | |
1258 | printJump := func(n uint) { | |
1259 | _print("\n goto l%d", n) | |
1260 | labels[n] = true | |
1261 | } | |
1262 | printRule = func(n Node) { | |
1263 | switch n.GetType() { | |
1264 | case TypeRule: | |
1265 | _print("%v <- ", n) | |
1266 | printRule(n.Front()) | |
1267 | case TypeDot: | |
1268 | _print(".") | |
1269 | case TypeName: | |
1270 | _print("%v", n) | |
1271 | case TypeCharacter: | |
1272 | _print("'%v'", escape(n.String())) | |
1273 | case TypeString: | |
1274 | s := escape(n.String()) | |
1275 | _print("'%v'", s[1:len(s)-1]) | |
1276 | case TypeRange: | |
1277 | element := n.Front() | |
1278 | lower := element | |
1279 | element = element.Next() | |
1280 | upper := element | |
1281 | _print("[%v-%v]", escape(lower.String()), escape(upper.String())) | |
1282 | case TypePredicate: | |
1283 | _print("&{%v}", n) | |
1284 | case TypeStateChange: | |
1285 | _print("!{%v}", n) | |
1286 | case TypeAction: | |
1287 | _print("{%v}", n) | |
1288 | case TypeCommit: | |
1289 | _print("commit") | |
1290 | case TypeAlternate: | |
1291 | _print("(") | |
1292 | elements := n.Slice() | |
1293 | printRule(elements[0]) | |
1294 | for _, element := range elements[1:] { | |
1295 | _print(" / ") | |
1296 | printRule(element) | |
1297 | } | |
1298 | _print(")") | |
1299 | case TypeUnorderedAlternate: | |
1300 | _print("(") | |
1301 | elements := n.Slice() | |
1302 | printRule(elements[0]) | |
1303 | for _, element := range elements[1:] { | |
1304 | _print(" | ") | |
1305 | printRule(element) | |
1306 | } | |
1307 | _print(")") | |
1308 | case TypeSequence: | |
1309 | _print("(") | |
1310 | elements := n.Slice() | |
1311 | printRule(elements[0]) | |
1312 | for _, element := range elements[1:] { | |
1313 | _print(" ") | |
1314 | printRule(element) | |
1315 | } | |
1316 | _print(")") | |
1317 | case TypePeekFor: | |
1318 | _print("&") | |
1319 | printRule(n.Front()) | |
1320 | case TypePeekNot: | |
1321 | _print("!") | |
1322 | printRule(n.Front()) | |
1323 | case TypeQuery: | |
1324 | printRule(n.Front()) | |
1325 | _print("?") | |
1326 | case TypeStar: | |
1327 | printRule(n.Front()) | |
1328 | _print("*") | |
1329 | case TypePlus: | |
1330 | printRule(n.Front()) | |
1331 | _print("+") | |
1332 | case TypePush, TypeImplicitPush: | |
1333 | _print("<") | |
1334 | printRule(n.Front()) | |
1335 | _print(">") | |
1336 | case TypeNil: | |
1337 | default: | |
1338 | fmt.Fprintf(os.Stderr, "illegal node type: %v\n", n.GetType()) | |
1339 | } | |
1340 | } | |
1341 | compile = func(n Node, ko uint) { | |
1342 | switch n.GetType() { | |
1343 | case TypeRule: | |
1344 | fmt.Fprintf(os.Stderr, "internal error #1 (%v)\n", n) | |
1345 | case TypeDot: | |
1346 | _print("\n if !matchDot() {") | |
1347 | /*print("\n if buffer[position] == endSymbol {")*/ | |
1348 | printJump(ko) | |
1349 | /*print("}\nposition++")*/ | |
1350 | _print("}") | |
1351 | case TypeName: | |
1352 | name := n.String() | |
1353 | rule := t.Rules[name] | |
1354 | if t.inline && t.rulesCount[name] == 1 { | |
1355 | compile(rule.Front(), ko) | |
1356 | return | |
1357 | } | |
1358 | _print("\n if !_rules[rule%v]() {", name /*rule.GetId()*/) | |
1359 | printJump(ko) | |
1360 | _print("}") | |
1361 | case TypeRange: | |
1362 | element := n.Front() | |
1363 | lower := element | |
1364 | element = element.Next() | |
1365 | upper := element | |
1366 | /*print("\n if !matchRange('%v', '%v') {", escape(lower.String()), escape(upper.String()))*/ | |
1367 | _print("\n if c := buffer[position]; c < rune('%v') || c > rune('%v') {", escape(lower.String()), escape(upper.String())) | |
1368 | printJump(ko) | |
1369 | _print("}\nposition++") | |
1370 | case TypeCharacter: | |
1371 | /*print("\n if !matchChar('%v') {", escape(n.String()))*/ | |
1372 | _print("\n if buffer[position] != rune('%v') {", escape(n.String())) | |
1373 | printJump(ko) | |
1374 | _print("}\nposition++") | |
1375 | case TypeString: | |
1376 | _print("\n if !matchString(%v) {", strconv.Quote(n.String())) | |
1377 | printJump(ko) | |
1378 | _print("}") | |
1379 | case TypePredicate: | |
1380 | _print("\n if !(%v) {", n) | |
1381 | printJump(ko) | |
1382 | _print("}") | |
1383 | case TypeStateChange: | |
1384 | _print("\n %v", n) | |
1385 | case TypeAction: | |
1386 | case TypeCommit: | |
1387 | case TypePush: | |
1388 | fallthrough | |
1389 | case TypeImplicitPush: | |
1390 | ok, element := label, n.Front() | |
1391 | label++ | |
1392 | nodeType, rule := element.GetType(), element.Next() | |
1393 | printBegin() | |
1394 | if nodeType == TypeAction { | |
1395 | _print("\nadd(rule%v, position)", rule) | |
1396 | } else { | |
1397 | _print("\nposition%d := position", ok) | |
1398 | _print("\ndepth++") | |
1399 | compile(element, ko) | |
1400 | _print("\ndepth--") | |
1401 | _print("\nadd(rule%v, position%d)", rule, ok) | |
1402 | } | |
1403 | printEnd() | |
1404 | case TypeAlternate: | |
1405 | ok := label | |
1406 | label++ | |
1407 | printBegin() | |
1408 | elements := n.Slice() | |
1409 | printSave(ok) | |
1410 | for _, element := range elements[:len(elements)-1] { | |
1411 | next := label | |
1412 | label++ | |
1413 | compile(element, next) | |
1414 | printJump(ok) | |
1415 | printLabel(next) | |
1416 | printRestore(ok) | |
1417 | } | |
1418 | compile(elements[len(elements)-1], ko) | |
1419 | printEnd() | |
1420 | printLabel(ok) | |
1421 | case TypeUnorderedAlternate: | |
1422 | done, ok := ko, label | |
1423 | label++ | |
1424 | printBegin() | |
1425 | _print("\n switch buffer[position] {") | |
1426 | elements := n.Slice() | |
1427 | elements, last := elements[:len(elements)-1], elements[len(elements)-1].Front().Next() | |
1428 | for _, element := range elements { | |
1429 | sequence := element.Front() | |
1430 | class := sequence.Front() | |
1431 | sequence = sequence.Next() | |
1432 | _print("\n case") | |
1433 | comma := false | |
1434 | for _, character := range class.Slice() { | |
1435 | if comma { | |
1436 | _print(",") | |
1437 | } else { | |
1438 | comma = true | |
1439 | } | |
1440 | _print(" '%s'", escape(character.String())) | |
1441 | } | |
1442 | _print(":") | |
1443 | compile(sequence, done) | |
1444 | _print("\nbreak") | |
1445 | } | |
1446 | _print("\n default:") | |
1447 | compile(last, done) | |
1448 | _print("\nbreak") | |
1449 | _print("\n }") | |
1450 | printEnd() | |
1451 | printLabel(ok) | |
1452 | case TypeSequence: | |
1453 | for _, element := range n.Slice() { | |
1454 | compile(element, ko) | |
1455 | } | |
1456 | case TypePeekFor: | |
1457 | ok := label | |
1458 | label++ | |
1459 | printBegin() | |
1460 | printSave(ok) | |
1461 | compile(n.Front(), ko) | |
1462 | printRestore(ok) | |
1463 | printEnd() | |
1464 | case TypePeekNot: | |
1465 | ok := label | |
1466 | label++ | |
1467 | printBegin() | |
1468 | printSave(ok) | |
1469 | compile(n.Front(), ok) | |
1470 | printJump(ko) | |
1471 | printLabel(ok) | |
1472 | printRestore(ok) | |
1473 | printEnd() | |
1474 | case TypeQuery: | |
1475 | qko := label | |
1476 | label++ | |
1477 | qok := label | |
1478 | label++ | |
1479 | printBegin() | |
1480 | printSave(qko) | |
1481 | compile(n.Front(), qko) | |
1482 | printJump(qok) | |
1483 | printLabel(qko) | |
1484 | printRestore(qko) | |
1485 | printEnd() | |
1486 | printLabel(qok) | |
1487 | case TypeStar: | |
1488 | again := label | |
1489 | label++ | |
1490 | out := label | |
1491 | label++ | |
1492 | printLabel(again) | |
1493 | printBegin() | |
1494 | printSave(out) | |
1495 | compile(n.Front(), out) | |
1496 | printJump(again) | |
1497 | printLabel(out) | |
1498 | printRestore(out) | |
1499 | printEnd() | |
1500 | case TypePlus: | |
1501 | again := label | |
1502 | label++ | |
1503 | out := label | |
1504 | label++ | |
1505 | compile(n.Front(), ko) | |
1506 | printLabel(again) | |
1507 | printBegin() | |
1508 | printSave(out) | |
1509 | compile(n.Front(), out) | |
1510 | printJump(again) | |
1511 | printLabel(out) | |
1512 | printRestore(out) | |
1513 | printEnd() | |
1514 | case TypeNil: | |
1515 | default: | |
1516 | fmt.Fprintf(os.Stderr, "illegal node type: %v\n", n.GetType()) | |
1517 | } | |
1518 | } | |
1519 | ||
1520 | /* lets figure out which jump labels are going to be used with this dry compile */ | |
1521 | printTemp, _print := _print, func(format string, a ...interface{}) {} | |
1522 | for _, element := range t.Slice() { | |
1523 | if element.GetType() != TypeRule { | |
1524 | continue | |
1525 | } | |
1526 | expression := element.Front() | |
1527 | if expression.GetType() == TypeNil { | |
1528 | continue | |
1529 | } | |
1530 | ko := label | |
1531 | label++ | |
1532 | if count, ok := t.rulesCount[element.String()]; !ok { | |
1533 | continue | |
1534 | } else if t.inline && count == 1 && ko != 0 { | |
1535 | continue | |
1536 | } | |
1537 | compile(expression, ko) | |
1538 | } | |
1539 | _print, label = printTemp, 0 | |
1540 | ||
1541 | /* now for the real compile pass */ | |
1542 | t.PegRuleType = "uint8" | |
1543 | if length := int64(t.Len()); length > math.MaxUint32 { | |
1544 | t.PegRuleType = "uint64" | |
1545 | } else if length > math.MaxUint16 { | |
1546 | t.PegRuleType = "uint32" | |
1547 | } else if length > math.MaxUint8 { | |
1548 | t.PegRuleType = "uint16" | |
1549 | } | |
1550 | printTemplate(pegHeaderTemplate) | |
1551 | for _, element := range t.Slice() { | |
1552 | if element.GetType() != TypeRule { | |
1553 | continue | |
1554 | } | |
1555 | expression := element.Front() | |
1556 | if implicit := expression.Front(); expression.GetType() == TypeNil || implicit.GetType() == TypeNil { | |
1557 | if element.String() != "PegText" { | |
1558 | fmt.Fprintf(os.Stderr, "rule '%v' used but not defined\n", element) | |
1559 | } | |
1560 | _print("\n nil,") | |
1561 | continue | |
1562 | } | |
1563 | ko := label | |
1564 | label++ | |
1565 | _print("\n /* %v ", element.GetId()) | |
1566 | printRule(element) | |
1567 | _print(" */") | |
1568 | if count, ok := t.rulesCount[element.String()]; !ok { | |
1569 | fmt.Fprintf(os.Stderr, "rule '%v' defined but not used\n", element) | |
1570 | _print("\n nil,") | |
1571 | continue | |
1572 | } else if t.inline && count == 1 && ko != 0 { | |
1573 | _print("\n nil,") | |
1574 | continue | |
1575 | } | |
1576 | _print("\n func() bool {") | |
1577 | if labels[ko] { | |
1578 | printSave(ko) | |
1579 | } | |
1580 | compile(expression, ko) | |
1581 | //print("\n fmt.Printf(\"%v\\n\")", element.String()) | |
1582 | _print("\n return true") | |
1583 | if labels[ko] { | |
1584 | printLabel(ko) | |
1585 | printRestore(ko) | |
1586 | _print("\n return false") | |
1587 | } | |
1588 | _print("\n },") | |
1589 | } | |
1590 | _print("\n }\n p.rules = _rules") | |
1591 | _print("\n}\n") | |
1592 | } |
0 | # PE Grammar for PE Grammars | |
1 | # | |
2 | # Adapted from [1] by Ian Piumarta <first-name at last-name point com>. | |
3 | # | |
4 | # Best viewed using 140 columns monospaced with tabs every 8. | |
5 | # | |
6 | # [1] Bryan Ford. "Parsing Expression Grammars: A Recognition-Based Syntactic | |
7 | # Foundation." Symposium on Principles of Programming Languages, | |
8 | # January 14--16, 2004, Venice, Italy. | |
9 | ||
10 | package main | |
11 | ||
12 | # parser declaration | |
13 | ||
14 | type Peg Peg { | |
15 | *Tree | |
16 | } | |
17 | ||
18 | # Hierarchical syntax | |
19 | Grammar <- Spacing 'package' MustSpacing Identifier { p.AddPackage(text) } | |
20 | Import* | |
21 | 'type' MustSpacing Identifier { p.AddPeg(text) } | |
22 | 'Peg' Spacing Action { p.AddState(text) } | |
23 | Definition+ EndOfFile | |
24 | ||
25 | Import <- 'import' Spacing ["] < [a-zA-Z_/.\-]+ > ["] Spacing { p.AddImport(text) } | |
26 | ||
27 | Definition <- Identifier { p.AddRule(text) } | |
28 | LeftArrow Expression { p.AddExpression() } &(Identifier LeftArrow / !.) | |
29 | Expression <- Sequence (Slash Sequence { p.AddAlternate() } | |
30 | )* (Slash { p.AddNil(); p.AddAlternate() } | |
31 | )? | |
32 | / { p.AddNil() } | |
33 | Sequence <- Prefix (Prefix { p.AddSequence() } | |
34 | )* | |
35 | Prefix <- And Action { p.AddPredicate(text) } | |
36 | / Not Action { p.AddStateChange(text) } | |
37 | / And Suffix { p.AddPeekFor() } | |
38 | / Not Suffix { p.AddPeekNot() } | |
39 | / Suffix | |
40 | Suffix <- Primary (Question { p.AddQuery() } | |
41 | / Star { p.AddStar() } | |
42 | / Plus { p.AddPlus() } | |
43 | )? | |
44 | Primary <- Identifier !LeftArrow { p.AddName(text) } | |
45 | / Open Expression Close | |
46 | / Literal | |
47 | / Class | |
48 | / Dot { p.AddDot() } | |
49 | / Action { p.AddAction(text) } | |
50 | / Begin Expression End { p.AddPush() } | |
51 | ||
52 | # Lexical syntax | |
53 | ||
54 | #PrivateIdentifier <- < [a-z_] IdentCont* > Spacing | |
55 | Identifier <- < IdentStart IdentCont* > Spacing | |
56 | IdentStart <- [[a-z_]] | |
57 | IdentCont <- IdentStart / [0-9] | |
58 | Literal <- ['] (!['] Char)? (!['] Char { p.AddSequence() } | |
59 | )* ['] Spacing | |
60 | / ["] (!["] DoubleChar)? (!["] DoubleChar { p.AddSequence() } | |
61 | )* ["] Spacing | |
62 | Class <- ( '[[' ( '^' DoubleRanges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } | |
63 | / DoubleRanges )? | |
64 | ']]' | |
65 | / '[' ( '^' Ranges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } | |
66 | / Ranges )? | |
67 | ']' ) | |
68 | Spacing | |
69 | Ranges <- !']' Range (!']' Range { p.AddAlternate() } | |
70 | )* | |
71 | DoubleRanges <- !']]' DoubleRange (!']]' DoubleRange { p.AddAlternate() } | |
72 | )* | |
73 | Range <- Char '-' Char { p.AddRange() } | |
74 | / Char | |
75 | DoubleRange <- Char '-' Char { p.AddDoubleRange() } | |
76 | / DoubleChar | |
77 | Char <- Escape | |
78 | / !'\\' <.> { p.AddCharacter(text) } | |
79 | DoubleChar <- Escape | |
80 | / <[a-zA-Z]> { p.AddDoubleCharacter(text) } | |
81 | / !'\\' <.> { p.AddCharacter(text) } | |
82 | Escape <- "\\a" { p.AddCharacter("\a") } # bell | |
83 | / "\\b" { p.AddCharacter("\b") } # bs | |
84 | / "\\e" { p.AddCharacter("\x1B") } # esc | |
85 | / "\\f" { p.AddCharacter("\f") } # ff | |
86 | / "\\n" { p.AddCharacter("\n") } # nl | |
87 | / "\\r" { p.AddCharacter("\r") } # cr | |
88 | / "\\t" { p.AddCharacter("\t") } # ht | |
89 | / "\\v" { p.AddCharacter("\v") } # vt | |
90 | / "\\'" { p.AddCharacter("'") } | |
91 | / '\\"' { p.AddCharacter("\"") } | |
92 | / '\\[' { p.AddCharacter("[") } | |
93 | / '\\]' { p.AddCharacter("]") } | |
94 | / '\\-' { p.AddCharacter("-") } | |
95 | / '\\' "0x"<[0-9a-fA-F]+> { p.AddHexaCharacter(text) } | |
96 | / '\\' <[0-3][0-7][0-7]> { p.AddOctalCharacter(text) } | |
97 | / '\\' <[0-7][0-7]?> { p.AddOctalCharacter(text) } | |
98 | / '\\\\' { p.AddCharacter("\\") } | |
99 | LeftArrow <- ('<-' / '\0x2190') Spacing | |
100 | Slash <- '/' Spacing | |
101 | And <- '&' Spacing | |
102 | Not <- '!' Spacing | |
103 | Question <- '?' Spacing | |
104 | Star <- '*' Spacing | |
105 | Plus <- '+' Spacing | |
106 | Open <- '(' Spacing | |
107 | Close <- ')' Spacing | |
108 | Dot <- '.' Spacing | |
109 | SpaceComment <- (Space / Comment) | |
110 | Spacing <- SpaceComment* | |
111 | MustSpacing <- SpaceComment+ | |
112 | Comment <- '#' (!EndOfLine .)* EndOfLine | |
113 | Space <- ' ' / '\t' / EndOfLine | |
114 | EndOfLine <- '\r\n' / '\n' / '\r' | |
115 | EndOfFile <- !. | |
116 | Action <- '{' < ActionBody* > '}' Spacing | |
117 | ActionBody <- [^{}] / '{' ActionBody* '}' | |
118 | Begin <- '<' Spacing | |
119 | End <- '>' Spacing | |
120 |
0 | package main | |
1 | ||
2 | import ( | |
3 | "bytes" | |
4 | "io/ioutil" | |
5 | "testing" | |
6 | ) | |
7 | ||
8 | func TestCorrect(t *testing.T) { | |
9 | buffer := `package p | |
10 | type T Peg {} | |
11 | Grammar <- !. | |
12 | ` | |
13 | p := &Peg{Tree: New(false, false), Buffer: buffer} | |
14 | p.Init() | |
15 | err := p.Parse() | |
16 | if err != nil { | |
17 | t.Error(err) | |
18 | } | |
19 | } | |
20 | ||
21 | func TestNoSpacePackage(t *testing.T) { | |
22 | buffer := `packagenospace | |
23 | type T Peg {} | |
24 | Grammar <- !. | |
25 | ` | |
26 | p := &Peg{Tree: New(false, false), Buffer: buffer} | |
27 | p.Init() | |
28 | err := p.Parse() | |
29 | if err == nil { | |
30 | t.Error("packagenospace was parsed without error") | |
31 | } | |
32 | } | |
33 | ||
34 | func TestNoSpaceType(t *testing.T) { | |
35 | buffer := ` | |
36 | package p | |
37 | typenospace Peg {} | |
38 | Grammar <- !. | |
39 | ` | |
40 | p := &Peg{Tree: New(false, false), Buffer: buffer} | |
41 | p.Init() | |
42 | err := p.Parse() | |
43 | if err == nil { | |
44 | t.Error("typenospace was parsed without error") | |
45 | } | |
46 | } | |
47 | ||
48 | func TestSame(t *testing.T) { | |
49 | buffer, err := ioutil.ReadFile("peg.peg") | |
50 | if err != nil { | |
51 | t.Error(err) | |
52 | } | |
53 | ||
54 | p := &Peg{Tree: New(true, true), Buffer: string(buffer)} | |
55 | p.Init() | |
56 | if err := p.Parse(); err != nil { | |
57 | t.Error(err) | |
58 | } | |
59 | ||
60 | p.Execute() | |
61 | ||
62 | out := &bytes.Buffer{} | |
63 | p.Compile("peg.peg.go", out) | |
64 | ||
65 | bootstrap, err := ioutil.ReadFile("bootstrap.peg.go") | |
66 | if err != nil { | |
67 | t.Error(err) | |
68 | } | |
69 | ||
70 | if len(out.Bytes()) != len(bootstrap) { | |
71 | t.Error("code generated from peg.peg is not the same as bootstrap.peg.go") | |
72 | return | |
73 | } | |
74 | ||
75 | for i, v := range out.Bytes() { | |
76 | if v != bootstrap[i] { | |
77 | t.Error("code generated from peg.peg is not the same as bootstrap.peg.go") | |
78 | return | |
79 | } | |
80 | } | |
81 | } | |
82 | ||
83 | func BenchmarkParse(b *testing.B) { | |
84 | files := [...]string{ | |
85 | "peg.peg", | |
86 | "grammars/c/c.peg", | |
87 | "grammars/calculator/calculator.peg", | |
88 | "grammars/fexl/fexl.peg", | |
89 | "grammars/java/java_1_7.peg", | |
90 | } | |
91 | pegs := make([]*Peg, len(files)) | |
92 | for i, file := range files { | |
93 | input, err := ioutil.ReadFile(file) | |
94 | if err != nil { | |
95 | b.Error(err) | |
96 | } | |
97 | ||
98 | p := &Peg{Tree: New(true, true), Buffer: string(input)} | |
99 | p.Init() | |
100 | pegs[i] = p | |
101 | } | |
102 | ||
103 | b.ResetTimer() | |
104 | for i := 0; i < b.N; i++ { | |
105 | for _, peg := range pegs { | |
106 | peg.Reset() | |
107 | if err := peg.Parse(); err != nil { | |
108 | b.Error(err) | |
109 | } | |
110 | } | |
111 | } | |
112 | } |