Codebase list golang-github-pointlander-peg / c08c49e
New upstream version 0.0~git20160905.0.58700b5 Alexandre Viau 7 years ago
31 changed file(s) with 9277 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
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 https://medium.com/@octskyward/graal-truffle-134d8f28fb69#.jo3luf4dn
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 }
+1593
-0
peg.go less more
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 }