pax_global_header00006660000000000000000000000064127632017020014512gustar00rootroot0000000000000052 comment=58700b5efaa51d444ea98fbf81a514517f8cc019 peg-1.0.0/000077500000000000000000000000001276320170200122635ustar00rootroot00000000000000peg-1.0.0/.gitignore000066400000000000000000000001231276320170200142470ustar00rootroot00000000000000*.peg.go !bootstrap.peg.go *.exe *.6 peg calculator/calculator bootstrap/bootstrap peg-1.0.0/AUTHORS000066400000000000000000000003731276320170200133360ustar00rootroot00000000000000# This is the official list of Go authors for copyright purposes. # Names should be added to this file as # Name or Organization # The email address is not required for organizations. Andrew J Snodgrass peg-1.0.0/LICENSE000066400000000000000000000027141276320170200132740ustar00rootroot00000000000000Copyright (c) 2010, Go Authors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Go Authors nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. peg-1.0.0/LINKS.md000066400000000000000000000001051276320170200134610ustar00rootroot00000000000000https://medium.com/@octskyward/graal-truffle-134d8f28fb69#.jo3luf4dn peg-1.0.0/Makefile000066400000000000000000000005271276320170200137270ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. peg: bootstrap.peg.go peg.go main.go go build bootstrap.peg.go: bootstrap/main.go peg.go cd bootstrap; go build bootstrap/bootstrap clean: rm -f bootstrap/bootstrap peg peg.peg.go peg-1.0.0/README.md000066400000000000000000000055011276320170200135430ustar00rootroot00000000000000# About Peg, Parsing Expression Grammar, is an implementation of a Packrat parser generator. A Packrat parser is a descent recursive parser capable of backtracking. The generated parser searches for the correct parsing of the input. For more information see: * http://en.wikipedia.org/wiki/Parsing_expression_grammar * http://pdos.csail.mit.edu/~baford/packrat/ This Go implementation is based on: * http://piumarta.com/software/peg/ # Usage ``` -inline Tells the parser generator to inline parser rules. -switch Reduces the number of rules that have to be tried for some pegs. If statements are replaced with switch statements. ``` # Syntax First declare the package name: ``` package ``` Then declare the parser: ``` type Peg { } ``` Next declare the rules. The first rule is the entry point into the parser: ``` <- ``` The first rule should probably end with '!.' to indicate no more input follows: ``` first <- . !. ``` '.' means any character matches. For zero or more character matches use: ``` repetition <- .* ``` For one or more character matches use: ``` oneOrMore <- .+ ``` For an optional character match use: ``` optional <- .? ``` If specific characters are to be matched use single quotes: ``` specific <- 'a'* 'bc'+ 'de'? ``` will match the string "aaabcbcde". For choosing between different inputs use alternates: ``` prioritized <- 'a' 'a'* / 'bc'+ / 'de'? ``` will match "aaaa" or "bcbc" or "de" or "". The matches are attempted in order. If the characters are case insensitive use double quotes: ``` insensitive <- "abc" ``` will match "abc" or "Abc" or "ABc" etc... For matching a set of characters use a character class: ``` class <- [a-z] ``` will watch "a" or "b" or all the way to "z". For an inverse character class start with a tilde: ``` inverse <- [~a-z] ``` will match anything but "a" or "b" or all the way to "z" If the character class is case insensitive use double brackets: ``` insensitive <- [[A-Z]] ``` Use parentheses for grouping: ``` grouping <- (rule1 / rule2) rule3 ``` For looking ahead for a match (predicate) use: ``` lookAhead <- &rule1 rule2 ``` For inverse look ahead use: ``` inverse <- !rule1 rule2 ``` Use curly braces for Go code: ``` gocode <- { fmt.Println("hello world") } ``` For string captures use less than greater than: ``` capture <- <'capture'> { fmt.Println(buffer[begin:end]) } ``` Will print out "capture". The captured string is stored in buffer[begin:end]. # Files * bootstrap/main.go: bootstrap syntax tree of peg * peg.go: syntax tree and code generator * main.go: bootstrap main * peg.peg: peg in its own language # Testing There should be no differences between the bootstrap and self compiled: ``` ./peg -inline -switch peg.peg diff bootstrap.peg.go peg.peg.go ``` # Author Andrew Snodgrass peg-1.0.0/bootstrap.peg.go000066400000000000000000002127071276320170200154120ustar00rootroot00000000000000package main import ( "fmt" "math" "sort" "strconv" ) const endSymbol rune = 1114112 /* The rule types inferred from the grammar are below. */ type pegRule uint8 const ( ruleUnknown pegRule = iota ruleGrammar ruleImport ruleDefinition ruleExpression ruleSequence rulePrefix ruleSuffix rulePrimary ruleIdentifier ruleIdentStart ruleIdentCont ruleLiteral ruleClass ruleRanges ruleDoubleRanges ruleRange ruleDoubleRange ruleChar ruleDoubleChar ruleEscape ruleLeftArrow ruleSlash ruleAnd ruleNot ruleQuestion ruleStar rulePlus ruleOpen ruleClose ruleDot ruleSpaceComment ruleSpacing ruleMustSpacing ruleComment ruleSpace ruleEndOfLine ruleEndOfFile ruleAction ruleActionBody ruleBegin ruleEnd ruleAction0 ruleAction1 ruleAction2 rulePegText ruleAction3 ruleAction4 ruleAction5 ruleAction6 ruleAction7 ruleAction8 ruleAction9 ruleAction10 ruleAction11 ruleAction12 ruleAction13 ruleAction14 ruleAction15 ruleAction16 ruleAction17 ruleAction18 ruleAction19 ruleAction20 ruleAction21 ruleAction22 ruleAction23 ruleAction24 ruleAction25 ruleAction26 ruleAction27 ruleAction28 ruleAction29 ruleAction30 ruleAction31 ruleAction32 ruleAction33 ruleAction34 ruleAction35 ruleAction36 ruleAction37 ruleAction38 ruleAction39 ruleAction40 ruleAction41 ruleAction42 ruleAction43 ruleAction44 ruleAction45 ruleAction46 ruleAction47 ruleAction48 rulePre ruleIn ruleSuf ) var rul3s = [...]string{ "Unknown", "Grammar", "Import", "Definition", "Expression", "Sequence", "Prefix", "Suffix", "Primary", "Identifier", "IdentStart", "IdentCont", "Literal", "Class", "Ranges", "DoubleRanges", "Range", "DoubleRange", "Char", "DoubleChar", "Escape", "LeftArrow", "Slash", "And", "Not", "Question", "Star", "Plus", "Open", "Close", "Dot", "SpaceComment", "Spacing", "MustSpacing", "Comment", "Space", "EndOfLine", "EndOfFile", "Action", "ActionBody", "Begin", "End", "Action0", "Action1", "Action2", "PegText", "Action3", "Action4", "Action5", "Action6", "Action7", "Action8", "Action9", "Action10", "Action11", "Action12", "Action13", "Action14", "Action15", "Action16", "Action17", "Action18", "Action19", "Action20", "Action21", "Action22", "Action23", "Action24", "Action25", "Action26", "Action27", "Action28", "Action29", "Action30", "Action31", "Action32", "Action33", "Action34", "Action35", "Action36", "Action37", "Action38", "Action39", "Action40", "Action41", "Action42", "Action43", "Action44", "Action45", "Action46", "Action47", "Action48", "Pre_", "_In_", "_Suf", } type node32 struct { token32 up, next *node32 } func (node *node32) print(depth int, buffer string) { for node != nil { for c := 0; c < depth; c++ { fmt.Printf(" ") } fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[node.pegRule], strconv.Quote(string(([]rune(buffer)[node.begin:node.end])))) if node.up != nil { node.up.print(depth+1, buffer) } node = node.next } } func (node *node32) Print(buffer string) { node.print(0, buffer) } type element struct { node *node32 down *element } /* ${@} bit structure for abstract syntax tree */ type token32 struct { pegRule begin, end, next uint32 } func (t *token32) isZero() bool { return t.pegRule == ruleUnknown && t.begin == 0 && t.end == 0 && t.next == 0 } func (t *token32) isParentOf(u token32) bool { return t.begin <= u.begin && t.end >= u.end && t.next > u.next } func (t *token32) getToken32() token32 { return token32{pegRule: t.pegRule, begin: uint32(t.begin), end: uint32(t.end), next: uint32(t.next)} } func (t *token32) String() string { return fmt.Sprintf("\x1B[34m%v\x1B[m %v %v %v", rul3s[t.pegRule], t.begin, t.end, t.next) } type tokens32 struct { tree []token32 ordered [][]token32 } func (t *tokens32) trim(length int) { t.tree = t.tree[0:length] } func (t *tokens32) Print() { for _, token := range t.tree { fmt.Println(token.String()) } } func (t *tokens32) Order() [][]token32 { if t.ordered != nil { return t.ordered } depths := make([]int32, 1, math.MaxInt16) for i, token := range t.tree { if token.pegRule == ruleUnknown { t.tree = t.tree[:i] break } depth := int(token.next) if length := len(depths); depth >= length { depths = depths[:depth+1] } depths[depth]++ } depths = append(depths, 0) ordered, pool := make([][]token32, len(depths)), make([]token32, len(t.tree)+len(depths)) for i, depth := range depths { depth++ ordered[i], pool, depths[i] = pool[:depth], pool[depth:], 0 } for i, token := range t.tree { depth := token.next token.next = uint32(i) ordered[depth][depths[depth]] = token depths[depth]++ } t.ordered = ordered return ordered } type state32 struct { token32 depths []int32 leaf bool } func (t *tokens32) AST() *node32 { tokens := t.Tokens() stack := &element{node: &node32{token32: <-tokens}} for token := range tokens { if token.begin == token.end { continue } node := &node32{token32: token} for stack != nil && stack.node.begin >= token.begin && stack.node.end <= token.end { stack.node.next = node.up node.up = stack.node stack = stack.down } stack = &element{node: node, down: stack} } return stack.node } func (t *tokens32) PreOrder() (<-chan state32, [][]token32) { s, ordered := make(chan state32, 6), t.Order() go func() { var states [8]state32 for i := range states { states[i].depths = make([]int32, len(ordered)) } depths, state, depth := make([]int32, len(ordered)), 0, 1 write := func(t token32, leaf bool) { S := states[state] state, S.pegRule, S.begin, S.end, S.next, S.leaf = (state+1)%8, t.pegRule, t.begin, t.end, uint32(depth), leaf copy(S.depths, depths) s <- S } states[state].token32 = ordered[0][0] depths[0]++ state++ a, b := ordered[depth-1][depths[depth-1]-1], ordered[depth][depths[depth]] depthFirstSearch: for { for { if i := depths[depth]; i > 0 { if c, j := ordered[depth][i-1], depths[depth-1]; a.isParentOf(c) && (j < 2 || !ordered[depth-1][j-2].isParentOf(c)) { if c.end != b.begin { write(token32{pegRule: ruleIn, begin: c.end, end: b.begin}, true) } break } } if a.begin < b.begin { write(token32{pegRule: rulePre, begin: a.begin, end: b.begin}, true) } break } next := depth + 1 if c := ordered[next][depths[next]]; c.pegRule != ruleUnknown && b.isParentOf(c) { write(b, false) depths[depth]++ depth, a, b = next, b, c continue } write(b, true) depths[depth]++ c, parent := ordered[depth][depths[depth]], true for { if c.pegRule != ruleUnknown && a.isParentOf(c) { b = c continue depthFirstSearch } else if parent && b.end != a.end { write(token32{pegRule: ruleSuf, begin: b.end, end: a.end}, true) } depth-- if depth > 0 { a, b, c = ordered[depth-1][depths[depth-1]-1], a, ordered[depth][depths[depth]] parent = a.isParentOf(b) continue } break depthFirstSearch } } close(s) }() return s, ordered } func (t *tokens32) PrintSyntax() { tokens, ordered := t.PreOrder() max := -1 for token := range tokens { if !token.leaf { fmt.Printf("%v", token.begin) for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { fmt.Printf(" \x1B[36m%v\x1B[m", rul3s[ordered[i][depths[i]-1].pegRule]) } fmt.Printf(" \x1B[36m%v\x1B[m\n", rul3s[token.pegRule]) } else if token.begin == token.end { fmt.Printf("%v", token.begin) for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { fmt.Printf(" \x1B[31m%v\x1B[m", rul3s[ordered[i][depths[i]-1].pegRule]) } fmt.Printf(" \x1B[31m%v\x1B[m\n", rul3s[token.pegRule]) } else { for c, end := token.begin, token.end; c < end; c++ { if i := int(c); max+1 < i { for j := max; j < i; j++ { fmt.Printf("skip %v %v\n", j, token.String()) } max = i } else if i := int(c); i <= max { for j := i; j <= max; j++ { fmt.Printf("dupe %v %v\n", j, token.String()) } } else { max = int(c) } fmt.Printf("%v", c) for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { fmt.Printf(" \x1B[34m%v\x1B[m", rul3s[ordered[i][depths[i]-1].pegRule]) } fmt.Printf(" \x1B[34m%v\x1B[m\n", rul3s[token.pegRule]) } fmt.Printf("\n") } } } func (t *tokens32) PrintSyntaxTree(buffer string) { tokens, _ := t.PreOrder() for token := range tokens { for c := 0; c < int(token.next); c++ { fmt.Printf(" ") } fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[token.pegRule], strconv.Quote(string(([]rune(buffer)[token.begin:token.end])))) } } func (t *tokens32) Add(rule pegRule, begin, end, depth uint32, index int) { t.tree[index] = token32{pegRule: rule, begin: uint32(begin), end: uint32(end), next: uint32(depth)} } func (t *tokens32) Tokens() <-chan token32 { s := make(chan token32, 16) go func() { for _, v := range t.tree { s <- v.getToken32() } close(s) }() return s } func (t *tokens32) Error() []token32 { ordered := t.Order() length := len(ordered) tokens, length := make([]token32, length), length-1 for i := range tokens { o := ordered[length-i] if len(o) > 1 { tokens[i] = o[len(o)-2].getToken32() } } return tokens } func (t *tokens32) Expand(index int) { tree := t.tree if index >= len(tree) { expanded := make([]token32, 2*len(tree)) copy(expanded, tree) t.tree = expanded } } type Peg struct { *Tree Buffer string buffer []rune rules [92]func() bool Parse func(rule ...int) error Reset func() Pretty bool tokens32 } type textPosition struct { line, symbol int } type textPositionMap map[int]textPosition func translatePositions(buffer []rune, positions []int) textPositionMap { length, translations, j, line, symbol := len(positions), make(textPositionMap, len(positions)), 0, 1, 0 sort.Ints(positions) search: for i, c := range buffer { if c == '\n' { line, symbol = line+1, 0 } else { symbol++ } if i == positions[j] { translations[positions[j]] = textPosition{line, symbol} for j++; j < length; j++ { if i != positions[j] { continue search } } break search } } return translations } type parseError struct { p *Peg max token32 } func (e *parseError) Error() string { tokens, error := []token32{e.max}, "\n" positions, p := make([]int, 2*len(tokens)), 0 for _, token := range tokens { positions[p], p = int(token.begin), p+1 positions[p], p = int(token.end), p+1 } translations := translatePositions(e.p.buffer, positions) format := "parse error near %v (line %v symbol %v - line %v symbol %v):\n%v\n" if e.p.Pretty { format = "parse error near \x1B[34m%v\x1B[m (line %v symbol %v - line %v symbol %v):\n%v\n" } for _, token := range tokens { begin, end := int(token.begin), int(token.end) error += fmt.Sprintf(format, rul3s[token.pegRule], translations[begin].line, translations[begin].symbol, translations[end].line, translations[end].symbol, strconv.Quote(string(e.p.buffer[begin:end]))) } return error } func (p *Peg) PrintSyntaxTree() { p.tokens32.PrintSyntaxTree(p.Buffer) } func (p *Peg) Highlighter() { p.PrintSyntax() } func (p *Peg) Execute() { buffer, _buffer, text, begin, end := p.Buffer, p.buffer, "", 0, 0 for token := range p.Tokens() { switch token.pegRule { case rulePegText: begin, end = int(token.begin), int(token.end) text = string(_buffer[begin:end]) case ruleAction0: p.AddPackage(text) case ruleAction1: p.AddPeg(text) case ruleAction2: p.AddState(text) case ruleAction3: p.AddImport(text) case ruleAction4: p.AddRule(text) case ruleAction5: p.AddExpression() case ruleAction6: p.AddAlternate() case ruleAction7: p.AddNil() p.AddAlternate() case ruleAction8: p.AddNil() case ruleAction9: p.AddSequence() case ruleAction10: p.AddPredicate(text) case ruleAction11: p.AddStateChange(text) case ruleAction12: p.AddPeekFor() case ruleAction13: p.AddPeekNot() case ruleAction14: p.AddQuery() case ruleAction15: p.AddStar() case ruleAction16: p.AddPlus() case ruleAction17: p.AddName(text) case ruleAction18: p.AddDot() case ruleAction19: p.AddAction(text) case ruleAction20: p.AddPush() case ruleAction21: p.AddSequence() case ruleAction22: p.AddSequence() case ruleAction23: p.AddPeekNot() p.AddDot() p.AddSequence() case ruleAction24: p.AddPeekNot() p.AddDot() p.AddSequence() case ruleAction25: p.AddAlternate() case ruleAction26: p.AddAlternate() case ruleAction27: p.AddRange() case ruleAction28: p.AddDoubleRange() case ruleAction29: p.AddCharacter(text) case ruleAction30: p.AddDoubleCharacter(text) case ruleAction31: p.AddCharacter(text) case ruleAction32: p.AddCharacter("\a") case ruleAction33: p.AddCharacter("\b") case ruleAction34: p.AddCharacter("\x1B") case ruleAction35: p.AddCharacter("\f") case ruleAction36: p.AddCharacter("\n") case ruleAction37: p.AddCharacter("\r") case ruleAction38: p.AddCharacter("\t") case ruleAction39: p.AddCharacter("\v") case ruleAction40: p.AddCharacter("'") case ruleAction41: p.AddCharacter("\"") case ruleAction42: p.AddCharacter("[") case ruleAction43: p.AddCharacter("]") case ruleAction44: p.AddCharacter("-") case ruleAction45: p.AddHexaCharacter(text) case ruleAction46: p.AddOctalCharacter(text) case ruleAction47: p.AddOctalCharacter(text) case ruleAction48: p.AddCharacter("\\") } } _, _, _, _, _ = buffer, _buffer, text, begin, end } func (p *Peg) Init() { p.buffer = []rune(p.Buffer) if len(p.buffer) == 0 || p.buffer[len(p.buffer)-1] != endSymbol { p.buffer = append(p.buffer, endSymbol) } tree := tokens32{tree: make([]token32, math.MaxInt16)} var max token32 position, depth, tokenIndex, buffer, _rules := uint32(0), uint32(0), 0, p.buffer, p.rules p.Parse = func(rule ...int) error { r := 1 if len(rule) > 0 { r = rule[0] } matches := p.rules[r]() p.tokens32 = tree if matches { p.trim(tokenIndex) return nil } return &parseError{p, max} } p.Reset = func() { position, tokenIndex, depth = 0, 0, 0 } add := func(rule pegRule, begin uint32) { tree.Expand(tokenIndex) tree.Add(rule, begin, position, depth, tokenIndex) tokenIndex++ if begin != position && position > max.end { max = token32{rule, begin, position, depth} } } matchDot := func() bool { if buffer[position] != endSymbol { position++ return true } return false } /*matchChar := func(c byte) bool { if buffer[position] == c { position++ return true } return false }*/ /*matchRange := func(lower byte, upper byte) bool { if c := buffer[position]; c >= lower && c <= upper { position++ return true } return false }*/ _rules = [...]func() bool{ nil, /* 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)> */ func() bool { position0, tokenIndex0, depth0 := position, tokenIndex, depth { position1 := position depth++ if !_rules[ruleSpacing]() { goto l0 } if buffer[position] != rune('p') { goto l0 } position++ if buffer[position] != rune('a') { goto l0 } position++ if buffer[position] != rune('c') { goto l0 } position++ if buffer[position] != rune('k') { goto l0 } position++ if buffer[position] != rune('a') { goto l0 } position++ if buffer[position] != rune('g') { goto l0 } position++ if buffer[position] != rune('e') { goto l0 } position++ if !_rules[ruleMustSpacing]() { goto l0 } if !_rules[ruleIdentifier]() { goto l0 } { add(ruleAction0, position) } l3: { position4, tokenIndex4, depth4 := position, tokenIndex, depth { position5 := position depth++ if buffer[position] != rune('i') { goto l4 } position++ if buffer[position] != rune('m') { goto l4 } position++ if buffer[position] != rune('p') { goto l4 } position++ if buffer[position] != rune('o') { goto l4 } position++ if buffer[position] != rune('r') { goto l4 } position++ if buffer[position] != rune('t') { goto l4 } position++ if !_rules[ruleSpacing]() { goto l4 } if buffer[position] != rune('"') { goto l4 } position++ { position6 := position depth++ { switch buffer[position] { case '-': if buffer[position] != rune('-') { goto l4 } position++ break case '.': if buffer[position] != rune('.') { goto l4 } position++ break case '/': if buffer[position] != rune('/') { goto l4 } position++ break case '_': if buffer[position] != rune('_') { goto l4 } position++ break 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': if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l4 } position++ break default: if c := buffer[position]; c < rune('a') || c > rune('z') { goto l4 } position++ break } } l7: { position8, tokenIndex8, depth8 := position, tokenIndex, depth { switch buffer[position] { case '-': if buffer[position] != rune('-') { goto l8 } position++ break case '.': if buffer[position] != rune('.') { goto l8 } position++ break case '/': if buffer[position] != rune('/') { goto l8 } position++ break case '_': if buffer[position] != rune('_') { goto l8 } position++ break 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': if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l8 } position++ break default: if c := buffer[position]; c < rune('a') || c > rune('z') { goto l8 } position++ break } } goto l7 l8: position, tokenIndex, depth = position8, tokenIndex8, depth8 } depth-- add(rulePegText, position6) } if buffer[position] != rune('"') { goto l4 } position++ if !_rules[ruleSpacing]() { goto l4 } { add(ruleAction3, position) } depth-- add(ruleImport, position5) } goto l3 l4: position, tokenIndex, depth = position4, tokenIndex4, depth4 } if buffer[position] != rune('t') { goto l0 } position++ if buffer[position] != rune('y') { goto l0 } position++ if buffer[position] != rune('p') { goto l0 } position++ if buffer[position] != rune('e') { goto l0 } position++ if !_rules[ruleMustSpacing]() { goto l0 } if !_rules[ruleIdentifier]() { goto l0 } { add(ruleAction1, position) } if buffer[position] != rune('P') { goto l0 } position++ if buffer[position] != rune('e') { goto l0 } position++ if buffer[position] != rune('g') { goto l0 } position++ if !_rules[ruleSpacing]() { goto l0 } if !_rules[ruleAction]() { goto l0 } { add(ruleAction2, position) } { position16 := position depth++ if !_rules[ruleIdentifier]() { goto l0 } { add(ruleAction4, position) } if !_rules[ruleLeftArrow]() { goto l0 } if !_rules[ruleExpression]() { goto l0 } { add(ruleAction5, position) } { position19, tokenIndex19, depth19 := position, tokenIndex, depth { position20, tokenIndex20, depth20 := position, tokenIndex, depth if !_rules[ruleIdentifier]() { goto l21 } if !_rules[ruleLeftArrow]() { goto l21 } goto l20 l21: position, tokenIndex, depth = position20, tokenIndex20, depth20 { position22, tokenIndex22, depth22 := position, tokenIndex, depth if !matchDot() { goto l22 } goto l0 l22: position, tokenIndex, depth = position22, tokenIndex22, depth22 } } l20: position, tokenIndex, depth = position19, tokenIndex19, depth19 } depth-- add(ruleDefinition, position16) } l14: { position15, tokenIndex15, depth15 := position, tokenIndex, depth { position23 := position depth++ if !_rules[ruleIdentifier]() { goto l15 } { add(ruleAction4, position) } if !_rules[ruleLeftArrow]() { goto l15 } if !_rules[ruleExpression]() { goto l15 } { add(ruleAction5, position) } { position26, tokenIndex26, depth26 := position, tokenIndex, depth { position27, tokenIndex27, depth27 := position, tokenIndex, depth if !_rules[ruleIdentifier]() { goto l28 } if !_rules[ruleLeftArrow]() { goto l28 } goto l27 l28: position, tokenIndex, depth = position27, tokenIndex27, depth27 { position29, tokenIndex29, depth29 := position, tokenIndex, depth if !matchDot() { goto l29 } goto l15 l29: position, tokenIndex, depth = position29, tokenIndex29, depth29 } } l27: position, tokenIndex, depth = position26, tokenIndex26, depth26 } depth-- add(ruleDefinition, position23) } goto l14 l15: position, tokenIndex, depth = position15, tokenIndex15, depth15 } { position30 := position depth++ { position31, tokenIndex31, depth31 := position, tokenIndex, depth if !matchDot() { goto l31 } goto l0 l31: position, tokenIndex, depth = position31, tokenIndex31, depth31 } depth-- add(ruleEndOfFile, position30) } depth-- add(ruleGrammar, position1) } return true l0: position, tokenIndex, depth = position0, tokenIndex0, depth0 return false }, /* 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)> */ nil, /* 2 Definition <- <(Identifier Action4 LeftArrow Expression Action5 &((Identifier LeftArrow) / !.))> */ nil, /* 3 Expression <- <((Sequence (Slash Sequence Action6)* (Slash Action7)?) / Action8)> */ func() bool { { position35 := position depth++ { position36, tokenIndex36, depth36 := position, tokenIndex, depth if !_rules[ruleSequence]() { goto l37 } l38: { position39, tokenIndex39, depth39 := position, tokenIndex, depth if !_rules[ruleSlash]() { goto l39 } if !_rules[ruleSequence]() { goto l39 } { add(ruleAction6, position) } goto l38 l39: position, tokenIndex, depth = position39, tokenIndex39, depth39 } { position41, tokenIndex41, depth41 := position, tokenIndex, depth if !_rules[ruleSlash]() { goto l41 } { add(ruleAction7, position) } goto l42 l41: position, tokenIndex, depth = position41, tokenIndex41, depth41 } l42: goto l36 l37: position, tokenIndex, depth = position36, tokenIndex36, depth36 { add(ruleAction8, position) } } l36: depth-- add(ruleExpression, position35) } return true }, /* 4 Sequence <- <(Prefix (Prefix Action9)*)> */ func() bool { position45, tokenIndex45, depth45 := position, tokenIndex, depth { position46 := position depth++ if !_rules[rulePrefix]() { goto l45 } l47: { position48, tokenIndex48, depth48 := position, tokenIndex, depth if !_rules[rulePrefix]() { goto l48 } { add(ruleAction9, position) } goto l47 l48: position, tokenIndex, depth = position48, tokenIndex48, depth48 } depth-- add(ruleSequence, position46) } return true l45: position, tokenIndex, depth = position45, tokenIndex45, depth45 return false }, /* 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)))> */ func() bool { position50, tokenIndex50, depth50 := position, tokenIndex, depth { position51 := position depth++ { position52, tokenIndex52, depth52 := position, tokenIndex, depth if !_rules[ruleAnd]() { goto l53 } if !_rules[ruleAction]() { goto l53 } { add(ruleAction10, position) } goto l52 l53: position, tokenIndex, depth = position52, tokenIndex52, depth52 if !_rules[ruleNot]() { goto l55 } if !_rules[ruleAction]() { goto l55 } { add(ruleAction11, position) } goto l52 l55: position, tokenIndex, depth = position52, tokenIndex52, depth52 { switch buffer[position] { case '!': if !_rules[ruleNot]() { goto l50 } if !_rules[ruleSuffix]() { goto l50 } { add(ruleAction13, position) } break case '&': if !_rules[ruleAnd]() { goto l50 } if !_rules[ruleSuffix]() { goto l50 } { add(ruleAction12, position) } break default: if !_rules[ruleSuffix]() { goto l50 } break } } } l52: depth-- add(rulePrefix, position51) } return true l50: position, tokenIndex, depth = position50, tokenIndex50, depth50 return false }, /* 6 Suffix <- <(Primary ((&('+') (Plus Action16)) | (&('*') (Star Action15)) | (&('?') (Question Action14)))?)> */ func() bool { position60, tokenIndex60, depth60 := position, tokenIndex, depth { position61 := position depth++ { position62 := position depth++ { switch buffer[position] { case '<': { position64 := position depth++ if buffer[position] != rune('<') { goto l60 } position++ if !_rules[ruleSpacing]() { goto l60 } depth-- add(ruleBegin, position64) } if !_rules[ruleExpression]() { goto l60 } { position65 := position depth++ if buffer[position] != rune('>') { goto l60 } position++ if !_rules[ruleSpacing]() { goto l60 } depth-- add(ruleEnd, position65) } { add(ruleAction20, position) } break case '{': if !_rules[ruleAction]() { goto l60 } { add(ruleAction19, position) } break case '.': { position68 := position depth++ if buffer[position] != rune('.') { goto l60 } position++ if !_rules[ruleSpacing]() { goto l60 } depth-- add(ruleDot, position68) } { add(ruleAction18, position) } break case '[': { position70 := position depth++ { position71, tokenIndex71, depth71 := position, tokenIndex, depth if buffer[position] != rune('[') { goto l72 } position++ if buffer[position] != rune('[') { goto l72 } position++ { position73, tokenIndex73, depth73 := position, tokenIndex, depth { position75, tokenIndex75, depth75 := position, tokenIndex, depth if buffer[position] != rune('^') { goto l76 } position++ if !_rules[ruleDoubleRanges]() { goto l76 } { add(ruleAction23, position) } goto l75 l76: position, tokenIndex, depth = position75, tokenIndex75, depth75 if !_rules[ruleDoubleRanges]() { goto l73 } } l75: goto l74 l73: position, tokenIndex, depth = position73, tokenIndex73, depth73 } l74: if buffer[position] != rune(']') { goto l72 } position++ if buffer[position] != rune(']') { goto l72 } position++ goto l71 l72: position, tokenIndex, depth = position71, tokenIndex71, depth71 if buffer[position] != rune('[') { goto l60 } position++ { position78, tokenIndex78, depth78 := position, tokenIndex, depth { position80, tokenIndex80, depth80 := position, tokenIndex, depth if buffer[position] != rune('^') { goto l81 } position++ if !_rules[ruleRanges]() { goto l81 } { add(ruleAction24, position) } goto l80 l81: position, tokenIndex, depth = position80, tokenIndex80, depth80 if !_rules[ruleRanges]() { goto l78 } } l80: goto l79 l78: position, tokenIndex, depth = position78, tokenIndex78, depth78 } l79: if buffer[position] != rune(']') { goto l60 } position++ } l71: if !_rules[ruleSpacing]() { goto l60 } depth-- add(ruleClass, position70) } break case '"', '\'': { position83 := position depth++ { position84, tokenIndex84, depth84 := position, tokenIndex, depth if buffer[position] != rune('\'') { goto l85 } position++ { position86, tokenIndex86, depth86 := position, tokenIndex, depth { position88, tokenIndex88, depth88 := position, tokenIndex, depth if buffer[position] != rune('\'') { goto l88 } position++ goto l86 l88: position, tokenIndex, depth = position88, tokenIndex88, depth88 } if !_rules[ruleChar]() { goto l86 } goto l87 l86: position, tokenIndex, depth = position86, tokenIndex86, depth86 } l87: l89: { position90, tokenIndex90, depth90 := position, tokenIndex, depth { position91, tokenIndex91, depth91 := position, tokenIndex, depth if buffer[position] != rune('\'') { goto l91 } position++ goto l90 l91: position, tokenIndex, depth = position91, tokenIndex91, depth91 } if !_rules[ruleChar]() { goto l90 } { add(ruleAction21, position) } goto l89 l90: position, tokenIndex, depth = position90, tokenIndex90, depth90 } if buffer[position] != rune('\'') { goto l85 } position++ if !_rules[ruleSpacing]() { goto l85 } goto l84 l85: position, tokenIndex, depth = position84, tokenIndex84, depth84 if buffer[position] != rune('"') { goto l60 } position++ { position93, tokenIndex93, depth93 := position, tokenIndex, depth { position95, tokenIndex95, depth95 := position, tokenIndex, depth if buffer[position] != rune('"') { goto l95 } position++ goto l93 l95: position, tokenIndex, depth = position95, tokenIndex95, depth95 } if !_rules[ruleDoubleChar]() { goto l93 } goto l94 l93: position, tokenIndex, depth = position93, tokenIndex93, depth93 } l94: l96: { position97, tokenIndex97, depth97 := position, tokenIndex, depth { position98, tokenIndex98, depth98 := position, tokenIndex, depth if buffer[position] != rune('"') { goto l98 } position++ goto l97 l98: position, tokenIndex, depth = position98, tokenIndex98, depth98 } if !_rules[ruleDoubleChar]() { goto l97 } { add(ruleAction22, position) } goto l96 l97: position, tokenIndex, depth = position97, tokenIndex97, depth97 } if buffer[position] != rune('"') { goto l60 } position++ if !_rules[ruleSpacing]() { goto l60 } } l84: depth-- add(ruleLiteral, position83) } break case '(': { position100 := position depth++ if buffer[position] != rune('(') { goto l60 } position++ if !_rules[ruleSpacing]() { goto l60 } depth-- add(ruleOpen, position100) } if !_rules[ruleExpression]() { goto l60 } { position101 := position depth++ if buffer[position] != rune(')') { goto l60 } position++ if !_rules[ruleSpacing]() { goto l60 } depth-- add(ruleClose, position101) } break default: if !_rules[ruleIdentifier]() { goto l60 } { position102, tokenIndex102, depth102 := position, tokenIndex, depth if !_rules[ruleLeftArrow]() { goto l102 } goto l60 l102: position, tokenIndex, depth = position102, tokenIndex102, depth102 } { add(ruleAction17, position) } break } } depth-- add(rulePrimary, position62) } { position104, tokenIndex104, depth104 := position, tokenIndex, depth { switch buffer[position] { case '+': { position107 := position depth++ if buffer[position] != rune('+') { goto l104 } position++ if !_rules[ruleSpacing]() { goto l104 } depth-- add(rulePlus, position107) } { add(ruleAction16, position) } break case '*': { position109 := position depth++ if buffer[position] != rune('*') { goto l104 } position++ if !_rules[ruleSpacing]() { goto l104 } depth-- add(ruleStar, position109) } { add(ruleAction15, position) } break default: { position111 := position depth++ if buffer[position] != rune('?') { goto l104 } position++ if !_rules[ruleSpacing]() { goto l104 } depth-- add(ruleQuestion, position111) } { add(ruleAction14, position) } break } } goto l105 l104: position, tokenIndex, depth = position104, tokenIndex104, depth104 } l105: depth-- add(ruleSuffix, position61) } return true l60: position, tokenIndex, depth = position60, tokenIndex60, depth60 return false }, /* 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)))> */ nil, /* 8 Identifier <- <(<(IdentStart IdentCont*)> Spacing)> */ func() bool { position114, tokenIndex114, depth114 := position, tokenIndex, depth { position115 := position depth++ { position116 := position depth++ if !_rules[ruleIdentStart]() { goto l114 } l117: { position118, tokenIndex118, depth118 := position, tokenIndex, depth { position119 := position depth++ { position120, tokenIndex120, depth120 := position, tokenIndex, depth if !_rules[ruleIdentStart]() { goto l121 } goto l120 l121: position, tokenIndex, depth = position120, tokenIndex120, depth120 if c := buffer[position]; c < rune('0') || c > rune('9') { goto l118 } position++ } l120: depth-- add(ruleIdentCont, position119) } goto l117 l118: position, tokenIndex, depth = position118, tokenIndex118, depth118 } depth-- add(rulePegText, position116) } if !_rules[ruleSpacing]() { goto l114 } depth-- add(ruleIdentifier, position115) } return true l114: position, tokenIndex, depth = position114, tokenIndex114, depth114 return false }, /* 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]))> */ func() bool { position122, tokenIndex122, depth122 := position, tokenIndex, depth { position123 := position depth++ { switch buffer[position] { case '_': if buffer[position] != rune('_') { goto l122 } position++ break 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': if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l122 } position++ break default: if c := buffer[position]; c < rune('a') || c > rune('z') { goto l122 } position++ break } } depth-- add(ruleIdentStart, position123) } return true l122: position, tokenIndex, depth = position122, tokenIndex122, depth122 return false }, /* 10 IdentCont <- <(IdentStart / [0-9])> */ nil, /* 11 Literal <- <(('\'' (!'\'' Char)? (!'\'' Char Action21)* '\'' Spacing) / ('"' (!'"' DoubleChar)? (!'"' DoubleChar Action22)* '"' Spacing))> */ nil, /* 12 Class <- <((('[' '[' (('^' DoubleRanges Action23) / DoubleRanges)? (']' ']')) / ('[' (('^' Ranges Action24) / Ranges)? ']')) Spacing)> */ nil, /* 13 Ranges <- <(!']' Range (!']' Range Action25)*)> */ func() bool { position128, tokenIndex128, depth128 := position, tokenIndex, depth { position129 := position depth++ { position130, tokenIndex130, depth130 := position, tokenIndex, depth if buffer[position] != rune(']') { goto l130 } position++ goto l128 l130: position, tokenIndex, depth = position130, tokenIndex130, depth130 } if !_rules[ruleRange]() { goto l128 } l131: { position132, tokenIndex132, depth132 := position, tokenIndex, depth { position133, tokenIndex133, depth133 := position, tokenIndex, depth if buffer[position] != rune(']') { goto l133 } position++ goto l132 l133: position, tokenIndex, depth = position133, tokenIndex133, depth133 } if !_rules[ruleRange]() { goto l132 } { add(ruleAction25, position) } goto l131 l132: position, tokenIndex, depth = position132, tokenIndex132, depth132 } depth-- add(ruleRanges, position129) } return true l128: position, tokenIndex, depth = position128, tokenIndex128, depth128 return false }, /* 14 DoubleRanges <- <(!(']' ']') DoubleRange (!(']' ']') DoubleRange Action26)*)> */ func() bool { position135, tokenIndex135, depth135 := position, tokenIndex, depth { position136 := position depth++ { position137, tokenIndex137, depth137 := position, tokenIndex, depth if buffer[position] != rune(']') { goto l137 } position++ if buffer[position] != rune(']') { goto l137 } position++ goto l135 l137: position, tokenIndex, depth = position137, tokenIndex137, depth137 } if !_rules[ruleDoubleRange]() { goto l135 } l138: { position139, tokenIndex139, depth139 := position, tokenIndex, depth { position140, tokenIndex140, depth140 := position, tokenIndex, depth if buffer[position] != rune(']') { goto l140 } position++ if buffer[position] != rune(']') { goto l140 } position++ goto l139 l140: position, tokenIndex, depth = position140, tokenIndex140, depth140 } if !_rules[ruleDoubleRange]() { goto l139 } { add(ruleAction26, position) } goto l138 l139: position, tokenIndex, depth = position139, tokenIndex139, depth139 } depth-- add(ruleDoubleRanges, position136) } return true l135: position, tokenIndex, depth = position135, tokenIndex135, depth135 return false }, /* 15 Range <- <((Char '-' Char Action27) / Char)> */ func() bool { position142, tokenIndex142, depth142 := position, tokenIndex, depth { position143 := position depth++ { position144, tokenIndex144, depth144 := position, tokenIndex, depth if !_rules[ruleChar]() { goto l145 } if buffer[position] != rune('-') { goto l145 } position++ if !_rules[ruleChar]() { goto l145 } { add(ruleAction27, position) } goto l144 l145: position, tokenIndex, depth = position144, tokenIndex144, depth144 if !_rules[ruleChar]() { goto l142 } } l144: depth-- add(ruleRange, position143) } return true l142: position, tokenIndex, depth = position142, tokenIndex142, depth142 return false }, /* 16 DoubleRange <- <((Char '-' Char Action28) / DoubleChar)> */ func() bool { position147, tokenIndex147, depth147 := position, tokenIndex, depth { position148 := position depth++ { position149, tokenIndex149, depth149 := position, tokenIndex, depth if !_rules[ruleChar]() { goto l150 } if buffer[position] != rune('-') { goto l150 } position++ if !_rules[ruleChar]() { goto l150 } { add(ruleAction28, position) } goto l149 l150: position, tokenIndex, depth = position149, tokenIndex149, depth149 if !_rules[ruleDoubleChar]() { goto l147 } } l149: depth-- add(ruleDoubleRange, position148) } return true l147: position, tokenIndex, depth = position147, tokenIndex147, depth147 return false }, /* 17 Char <- <(Escape / (!'\\' <.> Action29))> */ func() bool { position152, tokenIndex152, depth152 := position, tokenIndex, depth { position153 := position depth++ { position154, tokenIndex154, depth154 := position, tokenIndex, depth if !_rules[ruleEscape]() { goto l155 } goto l154 l155: position, tokenIndex, depth = position154, tokenIndex154, depth154 { position156, tokenIndex156, depth156 := position, tokenIndex, depth if buffer[position] != rune('\\') { goto l156 } position++ goto l152 l156: position, tokenIndex, depth = position156, tokenIndex156, depth156 } { position157 := position depth++ if !matchDot() { goto l152 } depth-- add(rulePegText, position157) } { add(ruleAction29, position) } } l154: depth-- add(ruleChar, position153) } return true l152: position, tokenIndex, depth = position152, tokenIndex152, depth152 return false }, /* 18 DoubleChar <- <(Escape / (<([a-z] / [A-Z])> Action30) / (!'\\' <.> Action31))> */ func() bool { position159, tokenIndex159, depth159 := position, tokenIndex, depth { position160 := position depth++ { position161, tokenIndex161, depth161 := position, tokenIndex, depth if !_rules[ruleEscape]() { goto l162 } goto l161 l162: position, tokenIndex, depth = position161, tokenIndex161, depth161 { position164 := position depth++ { position165, tokenIndex165, depth165 := position, tokenIndex, depth if c := buffer[position]; c < rune('a') || c > rune('z') { goto l166 } position++ goto l165 l166: position, tokenIndex, depth = position165, tokenIndex165, depth165 if c := buffer[position]; c < rune('A') || c > rune('Z') { goto l163 } position++ } l165: depth-- add(rulePegText, position164) } { add(ruleAction30, position) } goto l161 l163: position, tokenIndex, depth = position161, tokenIndex161, depth161 { position168, tokenIndex168, depth168 := position, tokenIndex, depth if buffer[position] != rune('\\') { goto l168 } position++ goto l159 l168: position, tokenIndex, depth = position168, tokenIndex168, depth168 } { position169 := position depth++ if !matchDot() { goto l159 } depth-- add(rulePegText, position169) } { add(ruleAction31, position) } } l161: depth-- add(ruleDoubleChar, position160) } return true l159: position, tokenIndex, depth = position159, tokenIndex159, depth159 return false }, /* 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))> */ func() bool { position171, tokenIndex171, depth171 := position, tokenIndex, depth { position172 := position depth++ { position173, tokenIndex173, depth173 := position, tokenIndex, depth if buffer[position] != rune('\\') { goto l174 } position++ { position175, tokenIndex175, depth175 := position, tokenIndex, depth if buffer[position] != rune('a') { goto l176 } position++ goto l175 l176: position, tokenIndex, depth = position175, tokenIndex175, depth175 if buffer[position] != rune('A') { goto l174 } position++ } l175: { add(ruleAction32, position) } goto l173 l174: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l178 } position++ { position179, tokenIndex179, depth179 := position, tokenIndex, depth if buffer[position] != rune('b') { goto l180 } position++ goto l179 l180: position, tokenIndex, depth = position179, tokenIndex179, depth179 if buffer[position] != rune('B') { goto l178 } position++ } l179: { add(ruleAction33, position) } goto l173 l178: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l182 } position++ { position183, tokenIndex183, depth183 := position, tokenIndex, depth if buffer[position] != rune('e') { goto l184 } position++ goto l183 l184: position, tokenIndex, depth = position183, tokenIndex183, depth183 if buffer[position] != rune('E') { goto l182 } position++ } l183: { add(ruleAction34, position) } goto l173 l182: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l186 } position++ { position187, tokenIndex187, depth187 := position, tokenIndex, depth if buffer[position] != rune('f') { goto l188 } position++ goto l187 l188: position, tokenIndex, depth = position187, tokenIndex187, depth187 if buffer[position] != rune('F') { goto l186 } position++ } l187: { add(ruleAction35, position) } goto l173 l186: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l190 } position++ { position191, tokenIndex191, depth191 := position, tokenIndex, depth if buffer[position] != rune('n') { goto l192 } position++ goto l191 l192: position, tokenIndex, depth = position191, tokenIndex191, depth191 if buffer[position] != rune('N') { goto l190 } position++ } l191: { add(ruleAction36, position) } goto l173 l190: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l194 } position++ { position195, tokenIndex195, depth195 := position, tokenIndex, depth if buffer[position] != rune('r') { goto l196 } position++ goto l195 l196: position, tokenIndex, depth = position195, tokenIndex195, depth195 if buffer[position] != rune('R') { goto l194 } position++ } l195: { add(ruleAction37, position) } goto l173 l194: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l198 } position++ { position199, tokenIndex199, depth199 := position, tokenIndex, depth if buffer[position] != rune('t') { goto l200 } position++ goto l199 l200: position, tokenIndex, depth = position199, tokenIndex199, depth199 if buffer[position] != rune('T') { goto l198 } position++ } l199: { add(ruleAction38, position) } goto l173 l198: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l202 } position++ { position203, tokenIndex203, depth203 := position, tokenIndex, depth if buffer[position] != rune('v') { goto l204 } position++ goto l203 l204: position, tokenIndex, depth = position203, tokenIndex203, depth203 if buffer[position] != rune('V') { goto l202 } position++ } l203: { add(ruleAction39, position) } goto l173 l202: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l206 } position++ if buffer[position] != rune('\'') { goto l206 } position++ { add(ruleAction40, position) } goto l173 l206: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l208 } position++ if buffer[position] != rune('"') { goto l208 } position++ { add(ruleAction41, position) } goto l173 l208: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l210 } position++ if buffer[position] != rune('[') { goto l210 } position++ { add(ruleAction42, position) } goto l173 l210: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l212 } position++ if buffer[position] != rune(']') { goto l212 } position++ { add(ruleAction43, position) } goto l173 l212: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l214 } position++ if buffer[position] != rune('-') { goto l214 } position++ { add(ruleAction44, position) } goto l173 l214: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l216 } position++ if buffer[position] != rune('0') { goto l216 } position++ { position217, tokenIndex217, depth217 := position, tokenIndex, depth if buffer[position] != rune('x') { goto l218 } position++ goto l217 l218: position, tokenIndex, depth = position217, tokenIndex217, depth217 if buffer[position] != rune('X') { goto l216 } position++ } l217: { position219 := position depth++ { switch buffer[position] { case 'A', 'B', 'C', 'D', 'E', 'F': if c := buffer[position]; c < rune('A') || c > rune('F') { goto l216 } position++ break case 'a', 'b', 'c', 'd', 'e', 'f': if c := buffer[position]; c < rune('a') || c > rune('f') { goto l216 } position++ break default: if c := buffer[position]; c < rune('0') || c > rune('9') { goto l216 } position++ break } } l220: { position221, tokenIndex221, depth221 := position, tokenIndex, depth { switch buffer[position] { case 'A', 'B', 'C', 'D', 'E', 'F': if c := buffer[position]; c < rune('A') || c > rune('F') { goto l221 } position++ break case 'a', 'b', 'c', 'd', 'e', 'f': if c := buffer[position]; c < rune('a') || c > rune('f') { goto l221 } position++ break default: if c := buffer[position]; c < rune('0') || c > rune('9') { goto l221 } position++ break } } goto l220 l221: position, tokenIndex, depth = position221, tokenIndex221, depth221 } depth-- add(rulePegText, position219) } { add(ruleAction45, position) } goto l173 l216: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l225 } position++ { position226 := position depth++ if c := buffer[position]; c < rune('0') || c > rune('3') { goto l225 } position++ if c := buffer[position]; c < rune('0') || c > rune('7') { goto l225 } position++ if c := buffer[position]; c < rune('0') || c > rune('7') { goto l225 } position++ depth-- add(rulePegText, position226) } { add(ruleAction46, position) } goto l173 l225: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l228 } position++ { position229 := position depth++ if c := buffer[position]; c < rune('0') || c > rune('7') { goto l228 } position++ { position230, tokenIndex230, depth230 := position, tokenIndex, depth if c := buffer[position]; c < rune('0') || c > rune('7') { goto l230 } position++ goto l231 l230: position, tokenIndex, depth = position230, tokenIndex230, depth230 } l231: depth-- add(rulePegText, position229) } { add(ruleAction47, position) } goto l173 l228: position, tokenIndex, depth = position173, tokenIndex173, depth173 if buffer[position] != rune('\\') { goto l171 } position++ if buffer[position] != rune('\\') { goto l171 } position++ { add(ruleAction48, position) } } l173: depth-- add(ruleEscape, position172) } return true l171: position, tokenIndex, depth = position171, tokenIndex171, depth171 return false }, /* 20 LeftArrow <- <((('<' '-') / '←') Spacing)> */ func() bool { position234, tokenIndex234, depth234 := position, tokenIndex, depth { position235 := position depth++ { position236, tokenIndex236, depth236 := position, tokenIndex, depth if buffer[position] != rune('<') { goto l237 } position++ if buffer[position] != rune('-') { goto l237 } position++ goto l236 l237: position, tokenIndex, depth = position236, tokenIndex236, depth236 if buffer[position] != rune('←') { goto l234 } position++ } l236: if !_rules[ruleSpacing]() { goto l234 } depth-- add(ruleLeftArrow, position235) } return true l234: position, tokenIndex, depth = position234, tokenIndex234, depth234 return false }, /* 21 Slash <- <('/' Spacing)> */ func() bool { position238, tokenIndex238, depth238 := position, tokenIndex, depth { position239 := position depth++ if buffer[position] != rune('/') { goto l238 } position++ if !_rules[ruleSpacing]() { goto l238 } depth-- add(ruleSlash, position239) } return true l238: position, tokenIndex, depth = position238, tokenIndex238, depth238 return false }, /* 22 And <- <('&' Spacing)> */ func() bool { position240, tokenIndex240, depth240 := position, tokenIndex, depth { position241 := position depth++ if buffer[position] != rune('&') { goto l240 } position++ if !_rules[ruleSpacing]() { goto l240 } depth-- add(ruleAnd, position241) } return true l240: position, tokenIndex, depth = position240, tokenIndex240, depth240 return false }, /* 23 Not <- <('!' Spacing)> */ func() bool { position242, tokenIndex242, depth242 := position, tokenIndex, depth { position243 := position depth++ if buffer[position] != rune('!') { goto l242 } position++ if !_rules[ruleSpacing]() { goto l242 } depth-- add(ruleNot, position243) } return true l242: position, tokenIndex, depth = position242, tokenIndex242, depth242 return false }, /* 24 Question <- <('?' Spacing)> */ nil, /* 25 Star <- <('*' Spacing)> */ nil, /* 26 Plus <- <('+' Spacing)> */ nil, /* 27 Open <- <('(' Spacing)> */ nil, /* 28 Close <- <(')' Spacing)> */ nil, /* 29 Dot <- <('.' Spacing)> */ nil, /* 30 SpaceComment <- <(Space / Comment)> */ func() bool { position250, tokenIndex250, depth250 := position, tokenIndex, depth { position251 := position depth++ { position252, tokenIndex252, depth252 := position, tokenIndex, depth { position254 := position depth++ { switch buffer[position] { case '\t': if buffer[position] != rune('\t') { goto l253 } position++ break case ' ': if buffer[position] != rune(' ') { goto l253 } position++ break default: if !_rules[ruleEndOfLine]() { goto l253 } break } } depth-- add(ruleSpace, position254) } goto l252 l253: position, tokenIndex, depth = position252, tokenIndex252, depth252 { position256 := position depth++ if buffer[position] != rune('#') { goto l250 } position++ l257: { position258, tokenIndex258, depth258 := position, tokenIndex, depth { position259, tokenIndex259, depth259 := position, tokenIndex, depth if !_rules[ruleEndOfLine]() { goto l259 } goto l258 l259: position, tokenIndex, depth = position259, tokenIndex259, depth259 } if !matchDot() { goto l258 } goto l257 l258: position, tokenIndex, depth = position258, tokenIndex258, depth258 } if !_rules[ruleEndOfLine]() { goto l250 } depth-- add(ruleComment, position256) } } l252: depth-- add(ruleSpaceComment, position251) } return true l250: position, tokenIndex, depth = position250, tokenIndex250, depth250 return false }, /* 31 Spacing <- */ func() bool { { position261 := position depth++ l262: { position263, tokenIndex263, depth263 := position, tokenIndex, depth if !_rules[ruleSpaceComment]() { goto l263 } goto l262 l263: position, tokenIndex, depth = position263, tokenIndex263, depth263 } depth-- add(ruleSpacing, position261) } return true }, /* 32 MustSpacing <- */ func() bool { position264, tokenIndex264, depth264 := position, tokenIndex, depth { position265 := position depth++ if !_rules[ruleSpaceComment]() { goto l264 } l266: { position267, tokenIndex267, depth267 := position, tokenIndex, depth if !_rules[ruleSpaceComment]() { goto l267 } goto l266 l267: position, tokenIndex, depth = position267, tokenIndex267, depth267 } depth-- add(ruleMustSpacing, position265) } return true l264: position, tokenIndex, depth = position264, tokenIndex264, depth264 return false }, /* 33 Comment <- <('#' (!EndOfLine .)* EndOfLine)> */ nil, /* 34 Space <- <((&('\t') '\t') | (&(' ') ' ') | (&('\n' | '\r') EndOfLine))> */ nil, /* 35 EndOfLine <- <(('\r' '\n') / '\n' / '\r')> */ func() bool { position270, tokenIndex270, depth270 := position, tokenIndex, depth { position271 := position depth++ { position272, tokenIndex272, depth272 := position, tokenIndex, depth if buffer[position] != rune('\r') { goto l273 } position++ if buffer[position] != rune('\n') { goto l273 } position++ goto l272 l273: position, tokenIndex, depth = position272, tokenIndex272, depth272 if buffer[position] != rune('\n') { goto l274 } position++ goto l272 l274: position, tokenIndex, depth = position272, tokenIndex272, depth272 if buffer[position] != rune('\r') { goto l270 } position++ } l272: depth-- add(ruleEndOfLine, position271) } return true l270: position, tokenIndex, depth = position270, tokenIndex270, depth270 return false }, /* 36 EndOfFile <- */ nil, /* 37 Action <- <('{' '}' Spacing)> */ func() bool { position276, tokenIndex276, depth276 := position, tokenIndex, depth { position277 := position depth++ if buffer[position] != rune('{') { goto l276 } position++ { position278 := position depth++ l279: { position280, tokenIndex280, depth280 := position, tokenIndex, depth if !_rules[ruleActionBody]() { goto l280 } goto l279 l280: position, tokenIndex, depth = position280, tokenIndex280, depth280 } depth-- add(rulePegText, position278) } if buffer[position] != rune('}') { goto l276 } position++ if !_rules[ruleSpacing]() { goto l276 } depth-- add(ruleAction, position277) } return true l276: position, tokenIndex, depth = position276, tokenIndex276, depth276 return false }, /* 38 ActionBody <- <((!('{' / '}') .) / ('{' ActionBody* '}'))> */ func() bool { position281, tokenIndex281, depth281 := position, tokenIndex, depth { position282 := position depth++ { position283, tokenIndex283, depth283 := position, tokenIndex, depth { position285, tokenIndex285, depth285 := position, tokenIndex, depth { position286, tokenIndex286, depth286 := position, tokenIndex, depth if buffer[position] != rune('{') { goto l287 } position++ goto l286 l287: position, tokenIndex, depth = position286, tokenIndex286, depth286 if buffer[position] != rune('}') { goto l285 } position++ } l286: goto l284 l285: position, tokenIndex, depth = position285, tokenIndex285, depth285 } if !matchDot() { goto l284 } goto l283 l284: position, tokenIndex, depth = position283, tokenIndex283, depth283 if buffer[position] != rune('{') { goto l281 } position++ l288: { position289, tokenIndex289, depth289 := position, tokenIndex, depth if !_rules[ruleActionBody]() { goto l289 } goto l288 l289: position, tokenIndex, depth = position289, tokenIndex289, depth289 } if buffer[position] != rune('}') { goto l281 } position++ } l283: depth-- add(ruleActionBody, position282) } return true l281: position, tokenIndex, depth = position281, tokenIndex281, depth281 return false }, /* 39 Begin <- <('<' Spacing)> */ nil, /* 40 End <- <('>' Spacing)> */ nil, /* 42 Action0 <- <{ p.AddPackage(text) }> */ nil, /* 43 Action1 <- <{ p.AddPeg(text) }> */ nil, /* 44 Action2 <- <{ p.AddState(text) }> */ nil, nil, /* 46 Action3 <- <{ p.AddImport(text) }> */ nil, /* 47 Action4 <- <{ p.AddRule(text) }> */ nil, /* 48 Action5 <- <{ p.AddExpression() }> */ nil, /* 49 Action6 <- <{ p.AddAlternate() }> */ nil, /* 50 Action7 <- <{ p.AddNil(); p.AddAlternate() }> */ nil, /* 51 Action8 <- <{ p.AddNil() }> */ nil, /* 52 Action9 <- <{ p.AddSequence() }> */ nil, /* 53 Action10 <- <{ p.AddPredicate(text) }> */ nil, /* 54 Action11 <- <{ p.AddStateChange(text) }> */ nil, /* 55 Action12 <- <{ p.AddPeekFor() }> */ nil, /* 56 Action13 <- <{ p.AddPeekNot() }> */ nil, /* 57 Action14 <- <{ p.AddQuery() }> */ nil, /* 58 Action15 <- <{ p.AddStar() }> */ nil, /* 59 Action16 <- <{ p.AddPlus() }> */ nil, /* 60 Action17 <- <{ p.AddName(text) }> */ nil, /* 61 Action18 <- <{ p.AddDot() }> */ nil, /* 62 Action19 <- <{ p.AddAction(text) }> */ nil, /* 63 Action20 <- <{ p.AddPush() }> */ nil, /* 64 Action21 <- <{ p.AddSequence() }> */ nil, /* 65 Action22 <- <{ p.AddSequence() }> */ nil, /* 66 Action23 <- <{ p.AddPeekNot(); p.AddDot(); p.AddSequence() }> */ nil, /* 67 Action24 <- <{ p.AddPeekNot(); p.AddDot(); p.AddSequence() }> */ nil, /* 68 Action25 <- <{ p.AddAlternate() }> */ nil, /* 69 Action26 <- <{ p.AddAlternate() }> */ nil, /* 70 Action27 <- <{ p.AddRange() }> */ nil, /* 71 Action28 <- <{ p.AddDoubleRange() }> */ nil, /* 72 Action29 <- <{ p.AddCharacter(text) }> */ nil, /* 73 Action30 <- <{ p.AddDoubleCharacter(text) }> */ nil, /* 74 Action31 <- <{ p.AddCharacter(text) }> */ nil, /* 75 Action32 <- <{ p.AddCharacter("\a") }> */ nil, /* 76 Action33 <- <{ p.AddCharacter("\b") }> */ nil, /* 77 Action34 <- <{ p.AddCharacter("\x1B") }> */ nil, /* 78 Action35 <- <{ p.AddCharacter("\f") }> */ nil, /* 79 Action36 <- <{ p.AddCharacter("\n") }> */ nil, /* 80 Action37 <- <{ p.AddCharacter("\r") }> */ nil, /* 81 Action38 <- <{ p.AddCharacter("\t") }> */ nil, /* 82 Action39 <- <{ p.AddCharacter("\v") }> */ nil, /* 83 Action40 <- <{ p.AddCharacter("'") }> */ nil, /* 84 Action41 <- <{ p.AddCharacter("\"") }> */ nil, /* 85 Action42 <- <{ p.AddCharacter("[") }> */ nil, /* 86 Action43 <- <{ p.AddCharacter("]") }> */ nil, /* 87 Action44 <- <{ p.AddCharacter("-") }> */ nil, /* 88 Action45 <- <{ p.AddHexaCharacter(text) }> */ nil, /* 89 Action46 <- <{ p.AddOctalCharacter(text) }> */ nil, /* 90 Action47 <- <{ p.AddOctalCharacter(text) }> */ nil, /* 91 Action48 <- <{ p.AddCharacter("\\") }> */ nil, } p.rules = _rules } peg-1.0.0/bootstrap/000077500000000000000000000000001276320170200143005ustar00rootroot00000000000000peg-1.0.0/bootstrap/main.go000066400000000000000000000561341276320170200155640ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "fmt" "os" "runtime" ) func main() { runtime.GOMAXPROCS(2) t := New(true, true) /*package main import "fmt" import "math" import "sort" import "strconv" type Peg Peg { *Tree }*/ t.AddPackage("main") t.AddPeg("Peg") t.AddState(` *Tree `) addDot := t.AddDot addName := t.AddName addCharacter := t.AddCharacter addDoubleCharacter := t.AddDoubleCharacter addHexaCharacter := t.AddHexaCharacter addAction := t.AddAction addRule := func(name string, item func()) { t.AddRule(name) item() t.AddExpression() } addSequence := func(items ...func()) { sequence := false for _, item := range items { item() if sequence { t.AddSequence() } else { sequence = true } } } addAlternate := func(items ...func()) { alternate := false for _, item := range items { item() if alternate { t.AddAlternate() } else { alternate = true } } } addString := func(s string) { sequence := false for _, r := range s { t.AddCharacter(string(r)) if sequence { t.AddSequence() } else { sequence = true } } } addRange := func(begin, end string) { addCharacter(begin) addCharacter(end) t.AddRange() } addDoubleRange := func(begin, end string) { addCharacter(begin) addCharacter(end) t.AddDoubleRange() } addStar := func(item func()) { item() t.AddStar() } addPlus := func(item func()) { item() t.AddPlus() } addQuery := func(item func()) { item() t.AddQuery() } addPush := func(item func()) { item() t.AddPush() } addPeekNot := func(item func()) { item() t.AddPeekNot() } addPeekFor := func(item func()) { item() t.AddPeekFor() } /* Grammar <- Spacing 'package' MustSpacing Identifier { p.AddPackage(text) } Import* 'type' MustSpacing Identifier { p.AddPeg(text) } 'Peg' Spacing Action { p.AddState(text) } Definition+ EndOfFile */ addRule("Grammar", func() { addSequence( func() { addName("Spacing") }, func() { addString("package") }, func() { addName("MustSpacing") }, func() { addName("Identifier") }, func() { addAction(" p.AddPackage(text) ") }, func() { addStar(func() { addName("Import") }) }, func() { addString("type") }, func() { addName("MustSpacing") }, func() { addName("Identifier") }, func() { addAction(" p.AddPeg(text) ") }, func() { addString("Peg") }, func() { addName("Spacing") }, func() { addName("Action") }, func() { addAction(" p.AddState(text) ") }, func() { addPlus(func() { addName("Definition") }) }, func() { addName("EndOfFile") }, ) }) /* Import <- 'import' Spacing ["] < [a-zA-Z_/.\-]+ > ["] Spacing { p.AddImport(text) } */ addRule("Import", func() { addSequence( func() { addString("import") }, func() { addName("Spacing") }, func() { addCharacter(`"`) }, func() { addPush(func() { addPlus(func() { addAlternate( func() { addRange(`a`, `z`) }, func() { addRange(`A`, `Z`) }, func() { addCharacter(`_`) }, func() { addCharacter(`/`) }, func() { addCharacter(`.`) }, func() { addCharacter(`-`) }, ) }) }) }, func() { addCharacter(`"`) }, func() { addName("Spacing") }, func() { addAction(" p.AddImport(text) ") }, ) }) /* Definition <- Identifier { p.AddRule(text) } LeftArrow Expression { p.AddExpression() } &(Identifier LeftArrow / !.)*/ addRule("Definition", func() { addSequence( func() { addName("Identifier") }, func() { addAction(" p.AddRule(text) ") }, func() { addName("LeftArrow") }, func() { addName("Expression") }, func() { addAction(" p.AddExpression() ") }, func() { addPeekFor(func() { addAlternate( func() { addSequence( func() { addName("Identifier") }, func() { addName("LeftArrow") }, ) }, func() { addPeekNot(func() { addDot() }) }, ) }) }, ) }) /* Expression <- Sequence (Slash Sequence { p.AddAlternate() } )* (Slash { p.AddNil(); p.AddAlternate() } )? / { p.AddNil() } */ addRule("Expression", func() { addAlternate( func() { addSequence( func() { addName("Sequence") }, func() { addStar(func() { addSequence( func() { addName("Slash") }, func() { addName("Sequence") }, func() { addAction(" p.AddAlternate() ") }, ) }) }, func() { addQuery(func() { addSequence( func() { addName("Slash") }, func() { addAction(" p.AddNil(); p.AddAlternate() ") }, ) }) }, ) }, func() { addAction(" p.AddNil() ") }, ) }) /* Sequence <- Prefix (Prefix { p.AddSequence() } )* */ addRule("Sequence", func() { addSequence( func() { addName("Prefix") }, func() { addStar(func() { addSequence( func() { addName("Prefix") }, func() { addAction(" p.AddSequence() ") }, ) }) }, ) }) /* Prefix <- And Action { p.AddPredicate(text) } / Not Action { p.AddStateChange(text) } / And Suffix { p.AddPeekFor() } / Not Suffix { p.AddPeekNot() } / Suffix */ addRule("Prefix", func() { addAlternate( func() { addSequence( func() { addName("And") }, func() { addName("Action") }, func() { addAction(" p.AddPredicate(text) ") }, ) }, func() { addSequence( func() { addName("Not") }, func() { addName("Action") }, func() { addAction(" p.AddStateChange(text) ") }, ) }, func() { addSequence( func() { addName("And") }, func() { addName("Suffix") }, func() { addAction(" p.AddPeekFor() ") }, ) }, func() { addSequence( func() { addName("Not") }, func() { addName("Suffix") }, func() { addAction(" p.AddPeekNot() ") }, ) }, func() { addName("Suffix") }, ) }) /* Suffix <- Primary (Question { p.AddQuery() } / Star { p.AddStar() } / Plus { p.AddPlus() } )? */ addRule("Suffix", func() { addSequence( func() { addName("Primary") }, func() { addQuery(func() { addAlternate( func() { addSequence( func() { addName("Question") }, func() { addAction(" p.AddQuery() ") }, ) }, func() { addSequence( func() { addName("Star") }, func() { addAction(" p.AddStar() ") }, ) }, func() { addSequence( func() { addName("Plus") }, func() { addAction(" p.AddPlus() ") }, ) }, ) }) }, ) }) /* Primary <- Identifier !LeftArrow { p.AddName(text) } / Open Expression Close / Literal / Class / Dot { p.AddDot() } / Action { p.AddAction(text) } / Begin Expression End { p.AddPush() }*/ addRule("Primary", func() { addAlternate( func() { addSequence( func() { addName("Identifier") }, func() { addPeekNot(func() { t.AddName("LeftArrow") }) }, func() { addAction(" p.AddName(text) ") }, ) }, func() { addSequence( func() { addName("Open") }, func() { addName("Expression") }, func() { addName("Close") }, ) }, func() { addName("Literal") }, func() { addName("Class") }, func() { addSequence( func() { addName("Dot") }, func() { addAction(" p.AddDot() ") }, ) }, func() { addSequence( func() { addName("Action") }, func() { addAction(" p.AddAction(text) ") }, ) }, func() { addSequence( func() { addName("Begin") }, func() { addName("Expression") }, func() { addName("End") }, func() { addAction(" p.AddPush() ") }, ) }, ) }) /* Identifier <- < IdentStart IdentCont* > Spacing */ addRule("Identifier", func() { addSequence( func() { addPush(func() { addSequence( func() { addName("IdentStart") }, func() { addStar(func() { addName("IdentCont") }) }, ) }) }, func() { addName("Spacing") }, ) }) /* IdentStart <- [[a-z_]] */ addRule("IdentStart", func() { addAlternate( func() { addDoubleRange(`a`, `z`) }, func() { addCharacter(`_`) }, ) }) /* IdentCont <- IdentStart / [0-9] */ addRule("IdentCont", func() { addAlternate( func() { addName("IdentStart") }, func() { addRange(`0`, `9`) }, ) }) /* Literal <- ['] (!['] Char)? (!['] Char { p.AddSequence() } )* ['] Spacing / ["] (!["] DoubleChar)? (!["] DoubleChar { p.AddSequence() } )* ["] Spacing */ addRule("Literal", func() { addAlternate( func() { addSequence( func() { addCharacter(`'`) }, func() { addQuery(func() { addSequence( func() { addPeekNot(func() { addCharacter(`'`) }) }, func() { addName("Char") }, ) }) }, func() { addStar(func() { addSequence( func() { addPeekNot(func() { addCharacter(`'`) }) }, func() { addName("Char") }, func() { addAction(` p.AddSequence() `) }, ) }) }, func() { addCharacter(`'`) }, func() { addName("Spacing") }, ) }, func() { addSequence( func() { addCharacter(`"`) }, func() { addQuery(func() { addSequence( func() { addPeekNot(func() { addCharacter(`"`) }) }, func() { addName("DoubleChar") }, ) }) }, func() { addStar(func() { addSequence( func() { addPeekNot(func() { addCharacter(`"`) }) }, func() { addName("DoubleChar") }, func() { addAction(` p.AddSequence() `) }, ) }) }, func() { addCharacter(`"`) }, func() { addName("Spacing") }, ) }, ) }) /* Class <- ( '[[' ( '^' DoubleRanges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } / DoubleRanges )? ']]' / '[' ( '^' Ranges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } / Ranges )? ']' ) Spacing */ addRule("Class", func() { addSequence( func() { addAlternate( func() { addSequence( func() { addString(`[[`) }, func() { addQuery(func() { addAlternate( func() { addSequence( func() { addCharacter(`^`) }, func() { addName("DoubleRanges") }, func() { addAction(` p.AddPeekNot(); p.AddDot(); p.AddSequence() `) }, ) }, func() { addName("DoubleRanges") }, ) }) }, func() { addString(`]]`) }, ) }, func() { addSequence( func() { addCharacter(`[`) }, func() { addQuery(func() { addAlternate( func() { addSequence( func() { addCharacter(`^`) }, func() { addName("Ranges") }, func() { addAction(` p.AddPeekNot(); p.AddDot(); p.AddSequence() `) }, ) }, func() { addName("Ranges") }, ) }) }, func() { addCharacter(`]`) }, ) }, ) }, func() { addName("Spacing") }, ) }) /* Ranges <- !']' Range (!']' Range { p.AddAlternate() } )* */ addRule("Ranges", func() { addSequence( func() { addPeekNot(func() { addCharacter(`]`) }) }, func() { addName("Range") }, func() { addStar(func() { addSequence( func() { addPeekNot(func() { addCharacter(`]`) }) }, func() { addName("Range") }, func() { addAction(" p.AddAlternate() ") }, ) }) }, ) }) /* DoubleRanges <- !']]' DoubleRange (!']]' DoubleRange { p.AddAlternate() } )* */ addRule("DoubleRanges", func() { addSequence( func() { addPeekNot(func() { addString(`]]`) }) }, func() { addName("DoubleRange") }, func() { addStar(func() { addSequence( func() { addPeekNot(func() { addString(`]]`) }) }, func() { addName("DoubleRange") }, func() { addAction(" p.AddAlternate() ") }, ) }) }, ) }) /* Range <- Char '-' Char { p.AddRange() } / Char */ addRule("Range", func() { addAlternate( func() { addSequence( func() { addName("Char") }, func() { addCharacter(`-`) }, func() { addName("Char") }, func() { addAction(" p.AddRange() ") }, ) }, func() { addName("Char") }, ) }) /* DoubleRange <- Char '-' Char { p.AddDoubleRange() } / DoubleChar */ addRule("DoubleRange", func() { addAlternate( func() { addSequence( func() { addName("Char") }, func() { addCharacter(`-`) }, func() { addName("Char") }, func() { addAction(" p.AddDoubleRange() ") }, ) }, func() { addName("DoubleChar") }, ) }) /* Char <- Escape / !'\\' <.> { p.AddCharacter(text) } */ addRule("Char", func() { addAlternate( func() { addName("Escape") }, func() { addSequence( func() { addPeekNot(func() { addCharacter("\\") }) }, func() { addPush(func() { addDot() }) }, func() { addAction(` p.AddCharacter(text) `) }, ) }, ) }) /* DoubleChar <- Escape / <[a-zA-Z]> { p.AddDoubleCharacter(text) } / !'\\' <.> { p.AddCharacter(text) } */ addRule("DoubleChar", func() { addAlternate( func() { addName("Escape") }, func() { addSequence( func() { addPush(func() { addAlternate( func() { addRange(`a`, `z`) }, func() { addRange(`A`, `Z`) }, ) }) }, func() { addAction(` p.AddDoubleCharacter(text) `) }, ) }, func() { addSequence( func() { addPeekNot(func() { addCharacter("\\") }) }, func() { addPush(func() { addDot() }) }, func() { addAction(` p.AddCharacter(text) `) }, ) }, ) }) /* Escape <- "\\a" { p.AddCharacter("\a") } # bell / "\\b" { p.AddCharacter("\b") } # bs / "\\e" { p.AddCharacter("\x1B") } # esc / "\\f" { p.AddCharacter("\f") } # ff / "\\n" { p.AddCharacter("\n") } # nl / "\\r" { p.AddCharacter("\r") } # cr / "\\t" { p.AddCharacter("\t") } # ht / "\\v" { p.AddCharacter("\v") } # vt / "\\'" { p.AddCharacter("'") } / '\\"' { p.AddCharacter("\"") } / '\\[' { p.AddCharacter("[") } / '\\]' { p.AddCharacter("]") } / '\\-' { p.AddCharacter("-") } / '\\' "0x"<[0-9a-fA-F]+> { p.AddHexaCharacter(text) } / '\\' <[0-3][0-7][0-7]> { p.AddOctalCharacter(text) } / '\\' <[0-7][0-7]?> { p.AddOctalCharacter(text) } / '\\\\' { p.AddCharacter("\\") } */ addRule("Escape", func() { addAlternate( func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`a`) }, func() { addAction(` p.AddCharacter("\a") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`b`) }, func() { addAction(` p.AddCharacter("\b") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`e`) }, func() { addAction(` p.AddCharacter("\x1B") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`f`) }, func() { addAction(` p.AddCharacter("\f") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`n`) }, func() { addAction(` p.AddCharacter("\n") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`r`) }, func() { addAction(` p.AddCharacter("\r") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`t`) }, func() { addAction(` p.AddCharacter("\t") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addDoubleCharacter(`v`) }, func() { addAction(` p.AddCharacter("\v") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addCharacter(`'`) }, func() { addAction(` p.AddCharacter("'") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addCharacter(`"`) }, func() { addAction(` p.AddCharacter("\"") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addCharacter(`[`) }, func() { addAction(` p.AddCharacter("[") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addCharacter(`]`) }, func() { addAction(` p.AddCharacter("]") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addCharacter(`-`) }, func() { addAction(` p.AddCharacter("-") `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addSequence( func() { addCharacter(`0`) }, func() { addDoubleCharacter(`x`) }, ) }, func() { addPush(func() { addPlus(func() { addAlternate( func() { addRange(`0`, `9`) }, func() { addRange(`a`, `f`) }, func() { addRange(`A`, `F`) }, ) }) }) }, func() { addAction(` p.AddHexaCharacter(text) `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addPush(func() { addSequence( func() { addRange(`0`, `3`) }, func() { addRange(`0`, `7`) }, func() { addRange(`0`, `7`) }, ) }) }, func() { addAction(` p.AddOctalCharacter(text) `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addPush(func() { addSequence( func() { addRange(`0`, `7`) }, func() { addQuery(func() { addRange(`0`, `7`) }) }, ) }) }, func() { addAction(` p.AddOctalCharacter(text) `) }, ) }, func() { addSequence( func() { addCharacter("\\") }, func() { addCharacter("\\") }, func() { addAction(` p.AddCharacter("\\") `) }, ) }, ) }) /* LeftArrow <- ('<-' / '\0x2190') Spacing */ addRule("LeftArrow", func() { addSequence( func() { addAlternate( func() { addString(`<-`) }, func() { addHexaCharacter("2190") }, ) }, func() { addName("Spacing") }, ) }) /* Slash <- '/' Spacing */ addRule("Slash", func() { addSequence( func() { addCharacter(`/`) }, func() { addName("Spacing") }, ) }) /* And <- '&' Spacing */ addRule("And", func() { addSequence( func() { addCharacter(`&`) }, func() { addName("Spacing") }, ) }) /* Not <- '!' Spacing */ addRule("Not", func() { addSequence( func() { addCharacter(`!`) }, func() { addName("Spacing") }, ) }) /* Question <- '?' Spacing */ addRule("Question", func() { addSequence( func() { addCharacter(`?`) }, func() { addName("Spacing") }, ) }) /* Star <- '*' Spacing */ addRule("Star", func() { addSequence( func() { addCharacter(`*`) }, func() { addName("Spacing") }, ) }) /* Plus <- '+' Spacing */ addRule("Plus", func() { addSequence( func() { addCharacter(`+`) }, func() { addName("Spacing") }, ) }) /* Open <- '(' Spacing */ addRule("Open", func() { addSequence( func() { addCharacter(`(`) }, func() { addName("Spacing") }, ) }) /* Close <- ')' Spacing */ addRule("Close", func() { addSequence( func() { addCharacter(`)`) }, func() { addName("Spacing") }, ) }) /* Dot <- '.' Spacing */ addRule("Dot", func() { addSequence( func() { addCharacter(`.`) }, func() { addName("Spacing") }, ) }) /* SpaceComment <- (Space / Comment) */ addRule("SpaceComment", func() { addAlternate( func() { addName("Space") }, func() { addName("Comment") }, ) }) /* Spacing <- SpaceComment* */ addRule("Spacing", func() { addStar(func() { addName("SpaceComment") }) }) /* MustSpacing <- SpaceComment+ */ addRule("MustSpacing", func() { addPlus(func() { t.AddName("SpaceComment") }) }) /* Comment <- '#' (!EndOfLine .)* EndOfLine */ addRule("Comment", func() { addSequence( func() { addCharacter(`#`) }, func() { addStar(func() { addSequence( func() { addPeekNot(func() { addName("EndOfLine") }) }, func() { addDot() }, ) }) }, func() { addName("EndOfLine") }, ) }) /* Space <- ' ' / '\t' / EndOfLine */ addRule("Space", func() { addAlternate( func() { addCharacter(` `) }, func() { addCharacter("\t") }, func() { addName("EndOfLine") }, ) }) /* EndOfLine <- '\r\n' / '\n' / '\r' */ addRule("EndOfLine", func() { addAlternate( func() { addString("\r\n") }, func() { addCharacter("\n") }, func() { addCharacter("\r") }, ) }) /* EndOfFile <- !. */ addRule("EndOfFile", func() { addPeekNot(func() { addDot() }) }) /* Action <- '{' < ActionBody* > '}' Spacing */ addRule("Action", func() { addSequence( func() { addCharacter(`{`) }, func() { addPush(func() { addStar(func() { addName("ActionBody") }) }) }, func() { addCharacter(`}`) }, func() { addName("Spacing") }, ) }) /* ActionBody <- [^{}] / '{' ActionBody* '}' */ addRule("ActionBody", func() { addAlternate( func() { addSequence( func() { addPeekNot(func() { addAlternate( func() { addCharacter(`{`) }, func() { addCharacter(`}`) }, ) }) }, func() { addDot() }, ) }, func() { addSequence( func() { addCharacter(`{`) }, func() { addStar(func() { addName("ActionBody") }) }, func() { addCharacter(`}`) }, ) }, ) }) /* Begin <- '<' Spacing */ addRule("Begin", func() { addSequence( func() { addCharacter(`<`) }, func() { addName("Spacing") }, ) }) /* End <- '>' Spacing */ addRule("End", func() { addSequence( func() { addCharacter(`>`) }, func() { addName("Spacing") }, ) }) filename := "bootstrap.peg.go" out, error := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) if error != nil { fmt.Printf("%v: %v\n", filename, error) return } defer out.Close() t.Compile(filename, out) } peg-1.0.0/bootstrap/peg.go000077700000000000000000000000001276320170200167122../peg.goustar00rootroot00000000000000peg-1.0.0/grammars/000077500000000000000000000000001276320170200140745ustar00rootroot00000000000000peg-1.0.0/grammars/c/000077500000000000000000000000001276320170200143165ustar00rootroot00000000000000peg-1.0.0/grammars/c/Makefile000066400000000000000000000004071276320170200157570ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. c: c.peg.go main.go go build c.peg.go: c.peg ../../peg -switch -inline c.peg clean: rm -f c c.peg.go peg-1.0.0/grammars/c/c.peg000066400000000000000000000440171276320170200152430ustar00rootroot00000000000000#=========================================================================== # # Parsing Expression Grammar of C for Mouse 1.1 - 1.5. # Based on standard ISO/IEC 9899.1999:TC2, without preprocessor. # Requires semantics class to process Typedefs. # #--------------------------------------------------------------------------- # # Copyright (C) 2007, 2009, 2010 by Roman R Redziejowski (www.romanredz.se). # # The author gives unlimited permission to copy and distribute # this file, with or without modifications, as long as this notice # is preserved, and any changes are properly documented. # # This file is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # #--------------------------------------------------------------------------- # # Latest update 2010-11-19 # #--------------------------------------------------------------------------- # # Modifications to the standard grammar: # # Defined # as start of line comment. # Added FunctionSpecifier "_stdcall". # Added TypeQualifier "__declspec()". # Added TypeSpecifier "__attribute__()". # The scope of TypedefNames is not implemented. # #--------------------------------------------------------------------------- # # Implementation of typedefs. # # A TypedefName is an Identifier that has been declared as such # by a previous typedef declaration. It can be used as TypeSpecifier # in DeclarationSpecifiers and SpecifierQualifierList. # Recognizing it as such is essential for correct parsing. # In other contexts, TypedefName is treated as an ordinary Identifier. # # According to 6.7.2, comment 2, of the Standard, TypedefName can appear # in DeclarationSpecifiers or SpecifierQualifierList at most once, # and then as the only TypeSpecifier. To make sure that an Identifer # is recognized as TypedefName only in these contexts, definitions # of these items are changed as follows: # # - TypedefName is removed as an alternative of TypeSpecifier. # # - DeclarationSpecifiers and SpecifierQualifierList are redefined # to allow either single TypedefName or one or more TypeSpecifiers. # # The semantics class, via semantic actions, maintains a table of TypedefNames. # # The rule defining TypedefName as Identifier has a semantic action # that returns true iff the Identifier is in the table. # That means TypedefName is accepted iff it is in the table. # # According to 6.7.7, comment 3, of the Standard, # in a Declaration whose StorageClassSpecifier is TYPEDEF, # each Declarator defines an Identifier to be a TypedefName. # These Identifiers are entered into the table as follows. # # - Each Identifier has itself as semantic value. # # - Each DirectDeclarator starts with either Identifier # or Declarator in parentheses. # Its semantic value is either that Identifier, # or the Identifier obtained as semantic value of that Declarator. # # - Each Declarator has as semantic value the Identifier # appearing in its DirectDeclarator, # # - Each InitDeclarator has as semantic value the Identifier # appearing in its Declarator. # # - InitDeclaratorList has as semantic value # the list of Identifiers appearing in its InitDeclarators. # # - DeclarationSpecifiers has semantic value "typedef" # if any of the specifiers is "typedef" or null otherwise. # # - Declaration has a semantic action that enters Identifiers # delivered by InitDeclaratorList into typedef table # if DeclarationSpecifiers indicate "typedef". # # #--------------------------------------------------------------------------- # # Change log # 2009-07-13 Posted on Internet. # 2010-11-19 Removed superfluous '?' after 'Spacing'. # # #--------------------------------------------------------------------------- # # 2013-02-21 Modified to work with github.com/pointlander/peg # #=========================================================================== #------------------------------------------------------------------------- # A.2.4 External definitions #------------------------------------------------------------------------- package main type C Peg { } TranslationUnit <- Spacing ExternalDeclaration+ EOT ExternalDeclaration <- FunctionDefinition / Declaration FunctionDefinition <- DeclarationSpecifiers Declarator DeclarationList? CompoundStatement DeclarationList <- Declaration+ #------------------------------------------------------------------------- # A.2.2 Declarations #------------------------------------------------------------------------- Declaration <- DeclarationSpecifiers InitDeclaratorList? SEMI #{} DeclarationSpecifiers <- (( StorageClassSpecifier / TypeQualifier / FunctionSpecifier )* TypedefName ( StorageClassSpecifier / TypeQualifier / FunctionSpecifier )* ) #{DeclarationSpecifiers} / ( StorageClassSpecifier / TypeSpecifier / TypeQualifier / FunctionSpecifier )+ #{DeclarationSpecifiers} InitDeclaratorList <- InitDeclarator (COMMA InitDeclarator)* #{} InitDeclarator <- Declarator (EQU Initializer)? #{} StorageClassSpecifier <- TYPEDEF / EXTERN / STATIC / AUTO / REGISTER / ATTRIBUTE LPAR LPAR (!RPAR .)* RPAR RPAR TypeSpecifier <- VOID / CHAR / SHORT / INT / LONG / FLOAT / DOUBLE / SIGNED / UNSIGNED / BOOL / COMPLEX / StructOrUnionSpecifier / EnumSpecifier StructOrUnionSpecifier <- StructOrUnion ( Identifier? LWING StructDeclaration+ RWING / Identifier ) StructOrUnion <- STRUCT / UNION StructDeclaration <- SpecifierQualifierList StructDeclaratorList SEMI SpecifierQualifierList <- ( TypeQualifier* TypedefName TypeQualifier* ) / ( TypeSpecifier / TypeQualifier )+ StructDeclaratorList <- StructDeclarator (COMMA StructDeclarator)* StructDeclarator <- Declarator? COLON ConstantExpression / Declarator EnumSpecifier <- ENUM ( Identifier? LWING EnumeratorList COMMA? RWING / Identifier ) EnumeratorList <- Enumerator (COMMA Enumerator)* Enumerator <- EnumerationConstant (EQU ConstantExpression)? TypeQualifier <- CONST / RESTRICT / VOLATILE / DECLSPEC LPAR Identifier RPAR FunctionSpecifier <- INLINE / STDCALL Declarator <- Pointer? DirectDeclarator #{} DirectDeclarator <- ( Identifier / LPAR Declarator RPAR ) ( LBRK TypeQualifier* AssignmentExpression? RBRK / LBRK STATIC TypeQualifier* AssignmentExpression RBRK / LBRK TypeQualifier+ STATIC AssignmentExpression RBRK / LBRK TypeQualifier* STAR RBRK / LPAR ParameterTypeList RPAR / LPAR IdentifierList? RPAR )* #{} Pointer <- ( STAR TypeQualifier* )+ ParameterTypeList <- ParameterList (COMMA ELLIPSIS)? ParameterList <- ParameterDeclaration (COMMA ParameterDeclaration)* ParameterDeclaration <- DeclarationSpecifiers ( Declarator / AbstractDeclarator )? IdentifierList <- Identifier (COMMA Identifier)* TypeName <- SpecifierQualifierList AbstractDeclarator? AbstractDeclarator <- Pointer? DirectAbstractDeclarator / Pointer DirectAbstractDeclarator <- ( LPAR AbstractDeclarator RPAR / LBRK (AssignmentExpression / STAR)? RBRK / LPAR ParameterTypeList? RPAR ) ( LBRK (AssignmentExpression / STAR)? RBRK / LPAR ParameterTypeList? RPAR )* TypedefName <-Identifier #{&TypedefName} Initializer <- AssignmentExpression / LWING InitializerList COMMA? RWING InitializerList <- Designation? Initializer (COMMA Designation? Initializer)* Designation <- Designator+ EQU Designator <- LBRK ConstantExpression RBRK / DOT Identifier #------------------------------------------------------------------------- # A.2.3 Statements #------------------------------------------------------------------------- Statement <- LabeledStatement / CompoundStatement / ExpressionStatement / SelectionStatement / IterationStatement / JumpStatement LabeledStatement <- Identifier COLON Statement / CASE ConstantExpression COLON Statement / DEFAULT COLON Statement CompoundStatement <- LWING ( Declaration / Statement )* RWING ExpressionStatement <- Expression? SEMI SelectionStatement <- IF LPAR Expression RPAR Statement (ELSE Statement)? / SWITCH LPAR Expression RPAR Statement IterationStatement <- WHILE LPAR Expression RPAR Statement / DO Statement WHILE LPAR Expression RPAR SEMI / FOR LPAR Expression? SEMI Expression? SEMI Expression? RPAR Statement / FOR LPAR Declaration Expression? SEMI Expression? RPAR Statement JumpStatement <- GOTO Identifier SEMI / CONTINUE SEMI / BREAK SEMI / RETURN Expression? SEMI #------------------------------------------------------------------------- # A.2.1 Expressions #------------------------------------------------------------------------- PrimaryExpression <- Identifier / Constant / StringLiteral / LPAR Expression RPAR PostfixExpression <- ( PrimaryExpression / LPAR TypeName RPAR LWING InitializerList COMMA? RWING ) ( LBRK Expression RBRK / LPAR ArgumentExpressionList? RPAR / DOT Identifier / PTR Identifier / INC / DEC )* ArgumentExpressionList <- AssignmentExpression (COMMA AssignmentExpression)* UnaryExpression <- PostfixExpression / INC UnaryExpression / DEC UnaryExpression / UnaryOperator CastExpression / SIZEOF (UnaryExpression / LPAR TypeName RPAR ) UnaryOperator <- AND / STAR / PLUS / MINUS / TILDA / BANG CastExpression <- (LPAR TypeName RPAR)* UnaryExpression MultiplicativeExpression <- CastExpression ((STAR / DIV / MOD) CastExpression)* AdditiveExpression <- MultiplicativeExpression ((PLUS / MINUS) MultiplicativeExpression)* ShiftExpression <- AdditiveExpression ((LEFT / RIGHT) AdditiveExpression)* RelationalExpression <- ShiftExpression ((LE / GE / LT / GT) ShiftExpression)* EqualityExpression <- RelationalExpression ((EQUEQU / BANGEQU) RelationalExpression)* ANDExpression <- EqualityExpression (AND EqualityExpression)* ExclusiveORExpression <- ANDExpression (HAT ANDExpression)* InclusiveORExpression <- ExclusiveORExpression (OR ExclusiveORExpression)* LogicalANDExpression <- InclusiveORExpression (ANDAND InclusiveORExpression)* LogicalORExpression <- LogicalANDExpression (OROR LogicalANDExpression)* ConditionalExpression <- LogicalORExpression (QUERY Expression COLON LogicalORExpression)* AssignmentExpression <- UnaryExpression AssignmentOperator AssignmentExpression / ConditionalExpression AssignmentOperator <- EQU / STAREQU / DIVEQU / MODEQU / PLUSEQU / MINUSEQU / LEFTEQU / RIGHTEQU / ANDEQU / HATEQU / OREQU Expression <- AssignmentExpression (COMMA AssignmentExpression)* ConstantExpression <- ConditionalExpression #------------------------------------------------------------------------- # A.1.1 Lexical elements # Tokens are: Keyword, Identifier, Constant, StringLiteral, Punctuator. # Tokens are separated by Spacing. #------------------------------------------------------------------------- Spacing <- ( WhiteSpace / LongComment / LineComment / Pragma )* WhiteSpace <- [ \n\r\t] # 7.4.1.10 [\u000B\u000C] LongComment <- '/*' (!'*/'.)* '*/' # 6.4.9 LineComment <- '//' (!'\n' .)* # 6.4.9 Pragma <- '#' (!'\n' .)* # Treat pragma as comment #------------------------------------------------------------------------- # A.1.2 Keywords #------------------------------------------------------------------------- AUTO <- 'auto' !IdChar Spacing BREAK <- 'break' !IdChar Spacing CASE <- 'case' !IdChar Spacing CHAR <- 'char' !IdChar Spacing CONST <- 'const' !IdChar Spacing CONTINUE <- 'continue' !IdChar Spacing DEFAULT <- 'default' !IdChar Spacing DOUBLE <- 'double' !IdChar Spacing DO <- 'do' !IdChar Spacing ELSE <- 'else' !IdChar Spacing ENUM <- 'enum' !IdChar Spacing EXTERN <- 'extern' !IdChar Spacing FLOAT <- 'float' !IdChar Spacing FOR <- 'for' !IdChar Spacing GOTO <- 'goto' !IdChar Spacing IF <- 'if' !IdChar Spacing INT <- 'int' !IdChar Spacing INLINE <- 'inline' !IdChar Spacing LONG <- 'long' !IdChar Spacing REGISTER <- 'register' !IdChar Spacing RESTRICT <- 'restrict' !IdChar Spacing RETURN <- 'return' !IdChar Spacing SHORT <- 'short' !IdChar Spacing SIGNED <- 'signed' !IdChar Spacing SIZEOF <- 'sizeof' !IdChar Spacing STATIC <- 'static' !IdChar Spacing STRUCT <- 'struct' !IdChar Spacing SWITCH <- 'switch' !IdChar Spacing TYPEDEF <- 'typedef' !IdChar Spacing UNION <- 'union' !IdChar Spacing UNSIGNED <- 'unsigned' !IdChar Spacing VOID <- 'void' !IdChar Spacing VOLATILE <- 'volatile' !IdChar Spacing WHILE <- 'while' !IdChar Spacing BOOL <- '_Bool' !IdChar Spacing COMPLEX <- '_Complex' !IdChar Spacing STDCALL <- '_stdcall' !IdChar Spacing DECLSPEC <- '__declspec' !IdChar Spacing ATTRIBUTE <- '__attribute__' !IdChar Spacing Keyword <- ( 'auto' / 'break' / 'case' / 'char' / 'const' / 'continue' / 'default' / 'double' / 'do' / 'else' / 'enum' / 'extern' / 'float' / 'for' / 'goto' / 'if' / 'int' / 'inline' / 'long' / 'register' / 'restrict' / 'return' / 'short' / 'signed' / 'sizeof' / 'static' / 'struct' / 'switch' / 'typedef' / 'union' / 'unsigned' / 'void' / 'volatile' / 'while' / '_Bool' / '_Complex' / '_Imaginary' / '_stdcall' / '__declspec' / '__attribute__' ) !IdChar #------------------------------------------------------------------------- # A.1.3 Identifiers # The standard does not explicitly state that identifiers must be # distinct from keywords, but it seems so. #------------------------------------------------------------------------- Identifier <- !Keyword IdNondigit IdChar* Spacing #{} IdNondigit <- [a-z] / [A-Z] / [_] / UniversalCharacter IdChar <- [a-z] / [A-Z] / [0-9] / [_] / UniversalCharacter #------------------------------------------------------------------------- # A.1.4 Universal character names #------------------------------------------------------------------------- UniversalCharacter <- '\\u' HexQuad / '\\U' HexQuad HexQuad HexQuad <- HexDigit HexDigit HexDigit HexDigit #------------------------------------------------------------------------- # A.1.5 Constants #------------------------------------------------------------------------- Constant <- FloatConstant / IntegerConstant # Note: can be a prefix of Float Constant! / EnumerationConstant / CharacterConstant IntegerConstant <- ( DecimalConstant / HexConstant / OctalConstant ) IntegerSuffix? Spacing DecimalConstant <- [1-9][0-9]* OctalConstant <- '0' [0-7]* HexConstant <- HexPrefix HexDigit+ HexPrefix <- '0x' / '0X' HexDigit <- [a-f] / [A-F] / [0-9] IntegerSuffix <- [uU] Lsuffix? / Lsuffix [uU]? Lsuffix <- 'll' / 'LL' / [lL] FloatConstant <- ( DecimalFloatConstant / HexFloatConstant ) FloatSuffix? Spacing DecimalFloatConstant <- Fraction Exponent? / [0-9]+ Exponent HexFloatConstant <- HexPrefix HexFraction BinaryExponent? / HexPrefix HexDigit+ BinaryExponent Fraction <- [0-9]* '.' [0-9]+ / [0-9]+ '.' HexFraction <- HexDigit* '.' HexDigit+ / HexDigit+ '.' Exponent <- [eE][+\-]? [0-9]+ BinaryExponent <- [pP][+\-]? [0-9]+ FloatSuffix <- [flFL] EnumerationConstant <- Identifier CharacterConstant <- 'L'? ['] Char* ['] Spacing Char <- Escape / !['\n\\] . Escape <- SimpleEscape / OctalEscape / HexEscape / UniversalCharacter SimpleEscape <- '\\' ['\"?\\abfnrtv] OctalEscape <- '\\' [0-7][0-7]?[0-7]? HexEscape <- '\\x' HexDigit+ #------------------------------------------------------------------------- # A.1.6 String Literals #------------------------------------------------------------------------- StringLiteral <- 'L'? (["] StringChar* ["] Spacing)+ StringChar <- Escape / ![\"\n\\] . #------------------------------------------------------------------------- # A.1.7 Punctuators #------------------------------------------------------------------------- LBRK <- '[' Spacing RBRK <- ']' Spacing LPAR <- '(' Spacing RPAR <- ')' Spacing LWING <- '{' Spacing RWING <- '}' Spacing DOT <- '.' Spacing PTR <- '->' Spacing INC <- '++' Spacing DEC <- '--' Spacing AND <- '&' ![&] Spacing STAR <- '*' ![=] Spacing PLUS <- '+' ![+=] Spacing MINUS <- '-' ![\-=>] Spacing TILDA <- '~' Spacing BANG <- '!' ![=] Spacing DIV <- '/' ![=] Spacing MOD <- '%' ![=>] Spacing LEFT <- '<<' ![=] Spacing RIGHT <- '>>' ![=] Spacing LT <- '<' ![=] Spacing GT <- '>' ![=] Spacing LE <- '<=' Spacing GE <- '>=' Spacing EQUEQU <- '==' Spacing BANGEQU <- '!=' Spacing HAT <- '^' ![=] Spacing OR <- '|' ![=] Spacing ANDAND <- '&&' Spacing OROR <- '||' Spacing QUERY <- '?' Spacing COLON <- ':' ![>] Spacing SEMI <- ';' Spacing ELLIPSIS <- '...' Spacing EQU <- '=' !"=" Spacing STAREQU <- '*=' Spacing DIVEQU <- '/=' Spacing MODEQU <- '%=' Spacing PLUSEQU <- '+=' Spacing MINUSEQU <- '-=' Spacing LEFTEQU <- '<<=' Spacing RIGHTEQU <- '>>=' Spacing ANDEQU <- '&=' Spacing HATEQU <- '^=' Spacing OREQU <- '|=' Spacing COMMA <- ',' Spacing EOT <- !. peg-1.0.0/grammars/c/main.go000066400000000000000000000024541276320170200155760ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "fmt" "io/ioutil" "log" "os" "strings" ) func main() { if len(os.Args) < 2 { fmt.Printf("%v FILE\n", os.Args[0]) os.Exit(1) } var walk func(name string) walk = func(name string) { fileInfo, err := os.Stat(name) if err != nil { log.Fatal(err) } if fileInfo.Mode() & (os.ModeNamedPipe | os.ModeSocket | os.ModeDevice) != 0 { /* will lock up if opened */ } else if fileInfo.IsDir() { fmt.Printf("directory %v\n", name) file, err := os.Open(name) if err != nil { log.Fatal(err) } files, err := file.Readdir(-1) if err != nil { log.Fatal(err) } file.Close() for _, f := range files { if !strings.HasSuffix(name, "/") { name += "/" } walk(name + f.Name()) } } else if strings.HasSuffix(name, ".c") { fmt.Printf("parse %v\n", name) file, err := os.Open(name) if err != nil { log.Fatal(err) } buffer, err := ioutil.ReadAll(file) if err != nil { log.Fatal(err) } file.Close() clang := &C{Buffer: string(buffer)} clang.Init() if err := clang.Parse(); err != nil { log.Fatal(err) } } } walk(os.Args[1]) } peg-1.0.0/grammars/calculator/000077500000000000000000000000001276320170200162255ustar00rootroot00000000000000peg-1.0.0/grammars/calculator/Makefile000066400000000000000000000005241276320170200176660ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. calculator: calculator.peg.go calculator.go main.go go build calculator.peg.go: calculator.peg ../../peg -switch -inline calculator.peg clean: rm -f calculator calculator.peg.go peg-1.0.0/grammars/calculator/calculator.go000066400000000000000000000033261276320170200207110ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "math/big" ) type Type uint8 const ( TypeNumber Type = iota TypeNegation TypeAdd TypeSubtract TypeMultiply TypeDivide TypeModulus TypeExponentiation ) type ByteCode struct { T Type Value *big.Int } func (code *ByteCode) String() string { switch code.T { case TypeNumber: return code.Value.String() case TypeAdd: return "+" case TypeNegation, TypeSubtract: return "-" case TypeMultiply: return "*" case TypeDivide: return "/" case TypeModulus: return "%" case TypeExponentiation: return "^" } return "" } type Expression struct { Code []ByteCode Top int } func (e *Expression) Init(expression string) { e.Code = make([]ByteCode, len(expression)) } func (e *Expression) AddOperator(operator Type) { code, top := e.Code, e.Top e.Top++ code[top].T = operator } func (e *Expression) AddValue(value string) { code, top := e.Code, e.Top e.Top++ code[top].Value = new(big.Int) code[top].Value.SetString(value, 10) } func (e *Expression) Evaluate() *big.Int { stack, top := make([]big.Int, len(e.Code)), 0 for _, code := range e.Code[0:e.Top] { switch code.T { case TypeNumber: stack[top].Set(code.Value) top++ continue case TypeNegation: a := &stack[top-1] a.Neg(a) continue } a, b := &stack[top-2], &stack[top-1] top-- switch code.T { case TypeAdd: a.Add(a, b) case TypeSubtract: a.Sub(a, b) case TypeMultiply: a.Mul(a, b) case TypeDivide: a.Div(a, b) case TypeModulus: a.Mod(a, b) case TypeExponentiation: a.Exp(a, b, nil) } } return &stack[0] } peg-1.0.0/grammars/calculator/calculator.peg000066400000000000000000000015651276320170200210620ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. package main type Calculator Peg { Expression } e <- sp e1 !. e1 <- e2 ( add e2 { p.AddOperator(TypeAdd) } / minus e2 { p.AddOperator(TypeSubtract) } )* e2 <- e3 ( multiply e3 { p.AddOperator(TypeMultiply) } / divide e3 { p.AddOperator(TypeDivide) } / modulus e3 { p.AddOperator(TypeModulus) } )* e3 <- e4 ( exponentiation e4 { p.AddOperator(TypeExponentiation) } )* e4 <- minus value { p.AddOperator(TypeNegation) } / value value <- < [0-9]+ > sp { p.AddValue(buffer[begin:end]) } / open e1 close add <- '+' sp minus <- '-' sp multiply <- '*' sp divide <- '/' sp modulus <- '%' sp exponentiation <- '^' sp open <- '(' sp close <- ')' sp sp <- ( ' ' / '\t' )* peg-1.0.0/grammars/calculator/main.go000066400000000000000000000012161276320170200175000ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "fmt" "log" "os" ) func main() { if len(os.Args) < 2 { name := os.Args[0] fmt.Printf("Usage: %v \"EXPRESSION\"\n", name) fmt.Printf("Example: %v \"( 1 - -3 ) / 3 + 2 * ( 3 + -4 ) + 3 %% 2^2\"\n =2\n", name) os.Exit(1) } expression := os.Args[1] calc := &Calculator{Buffer: expression} calc.Init() calc.Expression.Init(expression) if err := calc.Parse(); err != nil { log.Fatal(err) } calc.Execute() fmt.Printf("= %v\n", calc.Evaluate()) } peg-1.0.0/grammars/fexl/000077500000000000000000000000001276320170200150325ustar00rootroot00000000000000peg-1.0.0/grammars/fexl/Makefile000066400000000000000000000004341276320170200164730ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. fexl: fexl.peg.go main.go go build fexl.peg.go: fexl.peg ../../peg -switch -inline fexl.peg clean: rm -f fexl fexl.peg.go peg-1.0.0/grammars/fexl/doc/000077500000000000000000000000001276320170200155775ustar00rootroot00000000000000peg-1.0.0/grammars/fexl/doc/NOTICE000066400000000000000000000010551276320170200165040ustar00rootroot00000000000000Copyright 2011 Patrick Chkoreff Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. peg-1.0.0/grammars/fexl/doc/README000066400000000000000000000045021276320170200164600ustar00rootroot00000000000000Fexl (Function EXpression Language) http://fexl.com AUTHOR Patrick Chkoreff wrote this software. Please see the NOTICE file for terms of use. CREDITS I thank Moses Schönfinkel, who in 1924 wrote a paper titled "On the building blocks of mathematical logic". I found this paper in "From Frege to Gödel, A Source Book in Mathematical Logic, 1879-1931". Mr. Schönfinkel observes that all computable functions can be defined in terms of just two primitive functions C and S applied together in various combinations. This is a profound and magnificent insight for which I am very grateful. The C function is governed by the rule ((C x) y) = x. This is known as the "constancy function", or "Konstanzfunktion" in the original German. The S function is governed by the rule (((S x) y) z) = ((x z) (y z)). This is known as the "fusion function", or "Verschmelzungfunktion" in the original German. I also thank Jørgen Steensgaard-Madsen, who in 1989 wrote a paper titled "Typed Representation of Objects by Functions". I found this paper in the "ACM Transactions on Programming Languages and Systems, January 1989, Volume 11 Number 1". Mr. Steensgaard-Madsen observes that all of what we ordinarily understand as "data" can be represented as pure functions. Even a piece of data as humble as a single bit is in essence just a function. HOW TO INSTALL Go into the source code directory and run this command: ./build install You may be prompted for your sudo (superuser) password. That builds the program locally in ../bin, then copies it to the /usr/bin directory. If you need to install it in a different place, change the install_location variable inside the build script. HOW TO BUILD LOCALLY If you wish to enhance or test the program, you might prefer to build it locally in the ../bin directory and run it from there, without installing into /usr/bin. You do that with this command: ./build HOW TO RUN To run a fexl program which is read from standard input: fexl To run a fexl program which is read from a file named "script": fexl script You may also use the "shebang" method to create an executable fexl file. For example, create a file named "script" and put this on the first line: #!/usr/bin/fexl Then make your script executable with: chmod +x script Now you can run your script directly this way: ./script peg-1.0.0/grammars/fexl/doc/try.fxl000077500000000000000000000506151276320170200171420ustar00rootroot00000000000000#!../bin/fexl # ^^^ use that line for the locally built version #!/usr/bin/fexl # ^^^ use that line for the installed version # NOTE: If you run ./try.fxl, it will go through a bunch of tests, including # one at the end where it asks you to type lines of text and terminate with # Ctrl-D. If you'd like to run the test without having to type anything, and # compare it with the reference output, do this: # # cat try.fxl | ../bin/fexl | cmp - out # # That should run quietly with exit code 0. ##### # This function halts by simply consuming all arguments given to it. \halt == (\_ halt) # Useful: \string_from = (\x string_type x x; long_type x (long_string x); double_type x (double_string x); x) \print = (\item string_put (string_from item)) \nl = (print " ") \T = (\T\F T) \F = (\T\F F) \string_eq=(\x\y string_compare x y F T F) \long_le = (\x\y long_compare x y T T F) \long_lt = (\x\y long_compare x y T F F) \long_ge = (\x\y long_compare x y F T T) \long_gt = (\x\y long_compare x y F F T) \long_ne = (\x\y long_compare x y T F T) \long_min = (\x\y long_compare x y x x y) ### List functions # "end" is the empty list. \end = (\end\item end) # The "item" (cons) list constructor is built-in, but could be defined thus: # \item = (\head\tail \end\item item head tail) # Return the first N items of the list. \list_prefix == (\list\N long_le N 0 end; list end \head\tail \N = (long_sub N 1) item head; list_prefix tail N ) # Return the item at position N in the list, or default if no such item. \list_at == (\list\N\default list default \head\tail long_compare N 0 default head \N = (long_sub N 1) list_at tail N default ) \list_map == (\next\fun\list list next \head\tail fun head; list_map next fun tail) \list_do = (list_map I) \list_print = (\fun list_do \x string_put; fun x) # We don't use char_put because of buffering problems. \chars_print = (list_print long_char) \bits_print = (list_print \x x "1" "0") # Reverse a list. \reverse=(\list \reverse==(\list\result list result \h\t reverse t (item h result)) reverse list end ) ######## \test_hello_world== ( print "hello world" nl; ) ######## \test_cat== ( print "=== Enter lines of text and I'll echo them. Press Ctrl-D to stop";nl; \long_lt = (\x\y long_compare x y T F F) # The cat program echoes the input to the output. \cat == (char_get \ch long_lt ch 0 I; char_put ch; cat) cat ) ######## \test_string_slice== ( print (string_slice "abcde" 0 1); nl; print (string_slice "abcde" 0 2); nl; print (string_slice "abcde" 0 3); nl; print (string_slice "abcde" 0 4); nl; print (string_slice "abcde" 0 5); nl; print (string_slice "abcde" 0 6); nl; print (string_slice "abcde" 0 700); nl; print (string_slice "a" 0 0); nl; print (string_slice "a" 0 1); nl; print (string_slice "a" 0 2); nl; print (string_slice "a" -1 0); nl; print "=====";nl; print (string_slice "a" 0 1); nl; print (string_slice "a" -1 2); nl; print (string_slice "a" -2 3); nl; print (string_slice "a" -2 4); nl; print (string_slice "a" -2 0); nl; print (string_slice "abcde" 0 5); nl; print (string_slice "abcde" -1 5); nl; print (string_slice "abcde" -2 5); nl; print (string_slice "abcde" -3 5); nl; print (string_slice "abcde" -4 5); nl; print (string_slice "abcde" -5 5); nl; print (string_slice "abcde" -5 6); nl; print (string_slice "abcde" -5 7); nl; print (string_slice "abcde" -5 8); nl; print (string_slice "abcde" -5 9); nl; print (string_slice "abcde" -5 10); nl; print (string_slice "abcde" -5 11); nl; print "=====";nl; print (string_slice "" 0 0); nl; print (string_slice "" 0 800); nl; print (string_slice "" -30 800); nl; #string_put (string_from (string_slice "a" 0 1));nl; #string_put (string_from (string_slice "a" 0 1));nl; #string_put (string_from (string_slice "a" 0 1));nl; #string_put (string_from (string_slice "a" 0 1));nl; #string_put (string_slice "a" 0 0) ) ######## \test_write_binary == ( # Writing binary \string_3014 = ( string_append (long_char 03); string_append (long_char 00); string_append (long_char 01); string_append (long_char 04); "" ) string_put string_3014; ) ######## \test_string_len== ( print (string_len ""); nl; print (string_len "a"); nl; print (string_len "ab"); nl; print (string_len "12345678901234567890123456789012"); nl; ) ######## \test_string_at== ( print (string_at "abc" -1); nl; print (string_at "abc" 0); nl; print (string_at "abc" 1); nl; print (string_at "abc" 2); nl; print (string_at "abc" 3); nl; ) ######## \test_string_compare== ( \string_014 = ( string_append (long_char 00); string_append (long_char 01); string_append (long_char 04); "" ) \string_041 = ( string_append (long_char 00); string_append (long_char 04); string_append (long_char 01); "" ) \string_0142 = (string_append string_014; long_char 02); \do_compare=(\x\y\expect \result = (string_compare x y "LT" "EQ" "GT") print "string_compare "; print x; print " "; print y; print " "; print result; print " "; print (string_eq result expect "GOOD" "BAD"); nl; ) do_compare string_0142 string_014 "GT"; do_compare string_014 string_0142 "LT"; do_compare string_014 string_014 "EQ"; do_compare string_014 string_041 "LT"; do_compare string_041 string_014 "GT"; do_compare string_041 string_0142 "GT"; ) ######## \test_string_common == ( \string_eq=(\x\y string_compare x y F T F) \long_eq=(\x\y long_compare x y F T F) \check = (\value\expect \halt == (\_ halt) \ok = (long_eq value expect) print " "; print (ok "GOOD" "BAD");nl; ok I halt ) \test_string_common = (\x\y\expect \len = (string_common x y) print "string_common ";print x; print " "; print y; print " = "; print len; check len expect; ) test_string_common "" "" 0; test_string_common "" "a" 0; test_string_common "a" "a" 1; test_string_common "a" "ab" 1; test_string_common "ab" "a" 1; test_string_common "ab" "ab" 2; test_string_common "abc" "abd" 2; test_string_common "aac" "abd" 1; test_string_common "abd" "abd" 3; test_string_common "cbd" "abd" 0; test_string_common "x" "" 0; ) ######## \test_long_add== ( \x=(long_add 37 23) print "The value of x is "; print x; print "."; nl; ) ######## \test_procedural== ( # Make some abbreviations. \add=double_add \sub=double_sub \mul=double_mul \div=double_div print ~@ === Here we demonstrate an ordinary "procedural" style of programming. This works because definitions are NOT recursive by default. If you want a recursive definition, you must use "==" instead of just "=". @; \show=(\name\value print name; print " = "; print value; nl;) \x=3.0 \y=4.0 \x=(add x x) \y=(mul y x) show "x" x; show "y" y; \x=(div x; mul y 4.0) show "x" x; show "y" y; \z=(mul x; mul y; add 1.0 y) show "x" x; show "y" y; show "z" z; \z=(div z 5.0) show "z" z; ) \test_eager== ( \long_le = (\x\y long_compare x y T T F) \sum == (\total\count long_le count 0 total; # This form evaluates eagerly: \total = (long_add total count) # Or if you prefer, you can use "?" to force eager evaluation like this: #? (long_add total count) \total sum total (long_sub count 1)) \sum = (sum 0) \count = 100000 print "The sum of 1 .. ";print count; print " is "; print (sum count);nl; ) \test_double_compare == ( \do_compare=(\x\y\expect \result = (double_compare x y "LT" "EQ" "GT") print "double_compare "; print x; print " "; print y; print " "; print result; print " "; print (string_eq result expect "GOOD" "BAD"); nl; ) do_compare 23.0 23.0 "EQ" do_compare 23.0 24.0 "LT" do_compare 23.1 23.2 "LT" do_compare 24.0 23.0 "GT" do_compare 24.0 240.0 "LT" do_compare -1.0 4.0 "LT" do_compare 4.0 -1.0 "GT" do_compare -1.0 -1.0 "EQ" ) ####### Some tests with arbitrary precision arithmetic. \module_test_arithmetic == ( # These put a binary digit 0 or 1 on the front of a list. \d0 = (item F) \d1 = (item T) # the natural numbers 0 and 1 \nat_0 = end \nat_1 = (d1 nat_0) # (nat_2x x) is twice x. \nat_2x=(\x x nat_0 \_\_ d0 x) # (nat_2x1 x) is twice x plus 1. \nat_2x1=d1 # (nat_eq0 x) is true iff x = 0 \nat_eq0=(\x x T \_\_ F) # (nat_inc x) is x+1. (x incremented by 1). Both x and the result are of # type nat. \nat_inc==(\x x nat_1 \b\n b (d0; nat_inc n) (d1 n)) # (nat_dec x) is x-1 if x > 0, or 0 if x = 0. (x decremented by 1) Both x # and the result are of type nat. \nat_dec==(\x x nat_0 \b\n b (nat_eq0 n nat_0 (d0 n)) (d1; nat_dec n)) # (nat_add x y) is x+y. (the sum of x and y) The x, y, and result are of # type nat. \nat_add == (\x\y x y \bx\nx y x \by\ny \sum=(nat_add nx ny) bx (by (d0; nat_inc sum) (d1 sum)) (item by sum) ) # (nat_mul x y) is x*y. (the product of x and y) The x, y, and result are # of type nat. \nat_mul == (\x\y x nat_0 \bx\nx y nat_0 \by\ny bx (by (d1; nat_add nx (nat_mul ny x)) (d0; nat_mul ny x)) (by (d0; nat_mul nx y) (d0; d0; nat_mul nx ny)) ) # (int_ge0 x) is true if int x >= 0. \int_ge0=(\x x T \s\_ s) # (int_abs x) is the absolute value of int x. The result is a nat. \int_abs=(\x x nat_0 \_\n n) \int_0 = end \int_1 = (d1; d1; int_0) # (nat_int x) is nat x converted to the int +x. \nat_int=(\x nat_eq0 x int_0; d1 x) # (nat_neg x) is nat x converted to the int -x. \nat_neg=(\x nat_eq0 x int_0; d0 x) # (int_2x x) is twice x. \int_2x=(\x x int_0 \b\n item b; d0; n) # (int_inc x) is int x+1. \int_inc=(\x x int_1 \b\n b (d1; nat_inc n) (nat_neg (nat_dec n))) # (int_dec x) is int x-1. \int_dec=(\x x (d0; nat_1) \b\n b (nat_int (nat_dec n)) (d0; nat_inc n)) # (nat_sub x y) is x-y. (x minus y) The x, y are of type nat, but the # result is of type int because the result might be negative. \nat_sub==(\x\y x (nat_neg y) \bx\nx y (nat_int x) \by\ny \z = (int_2x (nat_sub nx ny)) bx (by I int_inc) (by int_dec I) z ) # (nat_div x y) divides x by y. It yields a pair , where q is the # quotient and r is the remainder. # # The result satisfies the equation x = q*y + r, 0 <= r < y. # # NOTE: If you divide by zero, the function yields the pair <0,0>. \nat_div==(\x\y\return x (return nat_0 nat_0) \bx\nx y (return nat_0 nat_0) \by\ny by ( # divide by odd nat_div nx y \q\r \r=(bx nat_2x1 nat_2x r) \d=(nat_sub r y) int_ge0 d (return (nat_2x1 q) (int_abs d)) (return (nat_2x q) r) ) ( # divide by even nat_div nx ny \q\r return q (bx nat_2x1 nat_2x r) ) ) \nat_compare == (\x\y \lt\eq\gt x (y eq \_\_ lt) \bx\nx y gt \by\ny nat_compare nx ny lt (bx (by eq gt) (by lt eq)) gt ) \nat_le = (\x\y nat_compare x y T T F) \nat_ge = (\x\y nat_compare x y F T T) \nat_2 = (d0 nat_1) \nat_5 = (d1 nat_2) \nat_10 = (d0 nat_5) \nat_div10 = (\x nat_div x nat_10) # Convert a nat into a machine long value, ignoring any overflow. \nat_long = ( \nat_long == (\sum\pow\bits bits sum \bit\bits \sum = (bit (long_add pow) I sum) \pow = (long_mul 2 pow) nat_long sum pow bits ) nat_long 0 1 ) # (nat_base_10_lo n) is the list of ASCII decimal digits for n starting # with the least significant digit. \nat_base_10_lo == (\x nat_div10 x \q\r \ch = (long_add 48; nat_long r); item ch; nat_eq0 q end; nat_base_10_lo q ) # (nat_base_10 n) is the list of ASCII decimal digits for n starting # with the most significant digit. \nat_base_10=(\n reverse; nat_base_10_lo n) \nat_print = (\x chars_print (nat_base_10 x)) \nat_print_lo = (\x chars_print (nat_base_10_lo x)) # for testing: # show in reverse decimal #\nat_print = nat_print_lo # show in binary #\nat_print = bits_print \int_base_10 = (\x int_ge0 x (nat_base_10; int_abs x) (item 45; nat_base_10; int_abs x) ) \int_print = (\x chars_print (int_base_10 x)) # LATER maybe char constants? e.g. '0' == 48 '-' == 45 # This would be handled in the standard resolution context. It would not be # part of the grammar. The symbol "'0'" would simply be resolved to the long # value 48. ###### \nat_2 = (d0 nat_1) \nat_3 = (d1 nat_1) \nat_4 = (d0 nat_2) \nat_5 = (d1 nat_2) \nat_6 = (d0 nat_3) \nat_7 = (d1 nat_3) \nat_8 = (d0 nat_4) \nat_9 = (d1 nat_4) \nat_10 = (d0 nat_5) \nat_11 = (d1 nat_5) \nat_12 = (d0 nat_6) \nat_13 = (d1 nat_6) \nat_14 = (d0 nat_7) \nat_15 = (d1 nat_7) \nat_16 = (d0 nat_8) \nat_17 = (d1 nat_8) \nat_18 = (d0 nat_9) \nat_19 = (d1 nat_9) \nat_32 = (d0 nat_16) \nat_20 = (d0 nat_10) \nat_24 = (d0 nat_12) \nat_31 = (d1 nat_15) \nat_48 = (d0 nat_24) \nat_49 = (d1 nat_24) #### \test_fibonacci == ( # This lets you use either built-in arithmetic or arbitrary-precision # arithmetic. \test_case == ( \if_show_all \number_type \num_rounds if_show_all ( print "Print the first ";print num_rounds; print " Fibonacci numbers "; print "using number type ";print number_type;nl; ) ( print "Print the Fibonacci number at position ";print num_rounds; print " using number type ";print number_type;nl; ) \choose = ( \return \case = (string_eq number_type) case "double" (return print double_add 1.0); case "nat" (return nat_print nat_add nat_1); halt ) choose \num_print \num_add \num_1 \nums_print = (list_do \x num_print x; nl) # Produces the infinite list of all Fibonacci numbers. \fibonacci = ( \1 \add \fibonacci == (\x\y item x; \z = (add x y) fibonacci y z ) fibonacci 1 1 ) \fibonacci = (fibonacci num_1 num_add) if_show_all (nums_print; list_prefix fibonacci num_rounds) (num_print; list_at fibonacci (long_sub num_rounds 1) num_1) nl; ) #test_case T "nat" 200; #test_case T "nat" 2000; #test_case T "nat" 1; #test_case T "nat" 2; #test_case T "nat" 3; #test_case F "nat" 4; #test_case F "double" 4; #test_case F "nat" 1000; #test_case F "nat" 100; #test_case T "nat" 100; #test_case F "double" 1000; #test_case F "nat" 10000; #test_case T "nat" 100; #test_case T "nat" 10; #test_case F "nat" 500; #test_case T "double" 200; #test_case T "nat" 200; #test_case F "nat" 200; #test_case F "nat" 2000; test_case T "nat" 300; test_case F "nat" 1600; # 10.208s ) #### \test_binary_counter == ( \loop == ( \count \num long_le count 0 I; print (nat_long num); print " "; bits_print num; nl; \count = (long_sub count 1) \num = (nat_inc num) loop count num ) loop 50 nat_0 ) \test_divide== ( # LATER automatically check the constraints \test_div = (\x\y nat_div x y \q\r print "test_div";nl; \show=(\key\val print key;print " = "; nat_print val; nl;) show "x" x; show "y" y; show "q" q; show "r" r; nl; ) test_div nat_0 nat_0; test_div nat_0 nat_1; test_div nat_1 nat_0; test_div nat_1 nat_1; test_div nat_2 nat_1; test_div nat_0 nat_2; test_div nat_1 nat_2; test_div nat_2 nat_2; test_div nat_3 nat_2; test_div nat_4 nat_2; test_div nat_0 nat_3; test_div nat_1 nat_3; test_div nat_2 nat_3; test_div nat_3 nat_3; test_div nat_4 nat_3; test_div nat_5 nat_3; test_div nat_6 nat_3; test_div nat_7 nat_3; test_div nat_8 nat_3; test_div nat_9 nat_3; test_div nat_10 nat_3; test_div nat_11 nat_3; test_div nat_12 nat_3; test_div nat_0 nat_4; test_div nat_1 nat_4; test_div nat_2 nat_4; test_div nat_3 nat_4; test_div nat_4 nat_4; test_div nat_5 nat_4; test_div nat_6 nat_4; test_div nat_7 nat_4; test_div nat_8 nat_4; test_div nat_9 nat_4; test_div nat_10 nat_4; test_div nat_11 nat_4; test_div nat_12 nat_4; test_div nat_12 nat_4; test_div nat_0 nat_5; test_div nat_1 nat_5; test_div nat_2 nat_5; test_div nat_3 nat_5; test_div nat_4 nat_5; test_div nat_5 nat_5; test_div nat_6 nat_5; test_div nat_7 nat_5; test_div nat_8 nat_5; test_div nat_9 nat_5; test_div nat_10 nat_5; test_div nat_11 nat_5; test_div nat_12 nat_5; test_div nat_13 nat_5; test_div nat_14 nat_5; test_div nat_15 nat_5; test_div nat_16 nat_5; test_div nat_17 nat_5; test_div nat_18 nat_5; test_div nat_19 nat_5; \big_test = ( \next \x = (nat_mul nat_31 nat_19) \churn = (\x nat_add nat_17; nat_mul x x) \x = (churn x) \x = (churn x) \x = (churn x) \x = (churn x) \x = (churn x) \x = (churn x) \y =nat_10 \y=(nat_mul y y) test_div x y; test_div (churn x) (churn; churn; churn; churn; churn; churn y); next ) big_test #big_test; #big_test; #big_test; #big_test; ) \test_sub == ( \test_sub = (\x\y \z = (nat_sub x y) print "== test_sub: "; nat_print x; print " - "; nat_print y; print " = "; int_print z;nl; ) test_sub nat_0 nat_0 test_sub nat_1 nat_0 test_sub nat_2 nat_0 test_sub nat_3 nat_0 test_sub nat_4 nat_0 test_sub nat_1 nat_1 test_sub nat_0 nat_1 test_sub nat_0 nat_2 test_sub nat_1 nat_2 test_sub nat_2 nat_2 test_sub nat_3 nat_2 test_sub nat_4 nat_2 test_sub nat_0 nat_3 test_sub nat_1 nat_3 test_sub nat_2 nat_3 test_sub nat_3 nat_3 test_sub nat_4 nat_3 test_sub nat_5 nat_3 test_sub nat_6 nat_3 test_sub nat_0 nat_4 test_sub nat_1 nat_4 test_sub nat_2 nat_4 test_sub nat_3 nat_4 test_sub nat_4 nat_4 test_sub nat_5 nat_4 test_sub nat_6 nat_4 test_sub nat_7 nat_4 test_sub nat_0 nat_5 test_sub nat_1 nat_5 test_sub nat_2 nat_5 test_sub nat_3 nat_5 test_sub nat_4 nat_5 test_sub nat_5 nat_5 test_sub nat_6 nat_5 test_sub nat_7 nat_5 test_sub nat_8 nat_5 test_sub nat_9 nat_5 test_sub nat_3 nat_19 test_sub nat_19 nat_19 test_sub nat_49 nat_19 test_sub nat_48 nat_19 ) \return return test_fibonacci test_binary_counter test_divide test_sub ) module_test_arithmetic \test_fibonacci \test_binary_counter \test_divide \test_sub ######## # Choose your test(s) to run down here. Comment the ones don't want to run. \test_string_type== ( \test_case=(\x\expect \result = (string_type x "yes" "no") print "string_type "; print result; print " ["; print (string_eq result expect "GOOD" "BAD"); print "]"; nl; ) test_case 4 "no" test_case 2.3 "no" test_case (\x\y y x) "no" test_case C "no" test_case (string_append "hello " "world") "yes" test_case ((\x\y y x) "hi" I) "yes" test_case "hey!" "yes" ) \test_double_type== ( \test_case=(\x\expect \result = (double_type x "yes" "no") print "double_type "; print result; print " ["; print (string_eq result expect "GOOD" "BAD"); print "]"; nl; ) test_case 4 "no" test_case 2.3 "yes" test_case (\x\y y x) "no" test_case C "no" test_case (string_append "hello " "world") "no" test_case ((\x\y y x) (double_add 4.2 2.6) I) "yes" test_case "hey!" "no" ) \test_long_type== ( \test_case=(\x\expect \result = (long_type x "yes" "no") print "long_type "; print result; print " ["; print (string_eq result expect "GOOD" "BAD"); print "]"; nl; ) test_case 4 "yes" test_case 2.3 "no" test_case (\x\y y x) "no" test_case C "no" test_case (string_append "hello " "world") "no" test_case ((\x\y y x) (long_add 4 2) I) "yes" test_case "hey!" "no" ) \test_string_long == ( \test_case=(\x\expect \quote = ~@ "@ \result = (string_long x "no" \n string_append "yes " (long_string n)) print "string_long "; string_put quote; string_put x; string_put quote print " : "; print result; print " ["; print (string_eq result expect "GOOD" "BAD"); print "]"; nl; ) test_case "0" "yes 0" test_case "1" "yes 1" test_case "-1" "yes -1" test_case "123" "yes 123" test_case "-123" "yes -123" test_case "x123" "no" test_case "1x23" "no" test_case "" "no" test_case " 456 " "no" test_case "456 " "no" test_case "1.6" "no" test_case "0." "no" ) \test_string_double == ( \test_case=(\x\expect \quote = ~@ "@ \result = (string_double x "no" \n string_append "yes " (double_string n)) print "string_double "; string_put quote; string_put x; string_put quote print " : "; print result; print " ["; print (string_eq result expect "GOOD" "BAD"); print "]"; nl; ) test_case "0" "yes 0" test_case "1" "yes 1" test_case "-1" "yes -1" test_case "123" "yes 123" test_case "-123" "yes -123" test_case "x123" "no" test_case "1x23" "no" test_case "" "no" test_case " 456 " "no" test_case " 456.78 " "no" test_case "456.78" "yes 456.78" test_case "456 " "no" test_case "1.6" "yes 1.6" test_case "0." "yes 0" test_case "-0" "yes -0" test_case "-0.0" "yes -0" test_case "-0.0123" "yes -0.0123" ) \test_long_double == ( \test_case = ( \x \y = (long_double x) \x_str = (long_string x) \y_str = (double_string y) print "long x = "; string_put x_str; print " double y = "; string_put y_str;nl; ) test_case 4 test_case 0 test_case -1 test_case -37 test_case 126478 ) \test_double_long == ( \test_case = ( \x \y = (double_long x) \x_str = (double_string x) \y_str = (long_string y) print "double x = "; string_put x_str; print " long y = "; string_put y_str;nl; ) test_case 4.0 test_case 0.0 test_case -1.0 test_case -37.0 test_case 126478.0 test_case 4.3 test_case 0.3 test_case -1.3 test_case -37.3 test_case 126478.3 test_case 4.9 test_case 0.9 test_case -1.9 test_case -37.9 test_case 126478.9 test_case -126478.9 ) #### test_string_type test_double_type test_long_type test_long_double test_double_long test_string_long test_string_double test_hello_world test_string_slice test_write_binary test_string_len test_string_at test_string_compare test_string_common test_long_add test_double_compare test_procedural test_eager test_binary_counter; test_divide; test_sub; test_fibonacci test_cat \\Extra stuff down here becomes input to the test_cat function. peg-1.0.0/grammars/fexl/fexl.peg000066400000000000000000000010341276320170200164630ustar00rootroot00000000000000package main type Fexl Peg { } Fexl <- ws Expression+ Input? !. Input <- '\\\\' .* Expression <- Comment / ';' ws Expression* / Definition / Argument / Term Comment <- '#' (![\n\r] .)* ws Definition <- '\\' Symbol '=' ws Term / Recursive Recursive <- '\\' Symbol '==' ws Term Argument <- '\\' Symbol Term <- open Expression+ close / Symbol Symbol <- (String / (![ \t\n\r\\()"~;=] .)+) ws String <- '"' (!'"' .)* '"' / Complex Complex <- tilde '@' (!'@' .)* '@' tilde <- '~' open <- '(' ws close <- ')' ws ws <- [ \t\n\r]* peg-1.0.0/grammars/fexl/main.go000066400000000000000000000006661276320170200163150ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "log" "io/ioutil" ) func main() { buffer, err := ioutil.ReadFile("doc/try.fxl") if err != nil { log.Fatal(err) } fexl := &Fexl{Buffer: string(buffer)} fexl.Init() if err := fexl.Parse(); err != nil { log.Fatal(err) } fexl.Highlighter() } peg-1.0.0/grammars/java/000077500000000000000000000000001276320170200150155ustar00rootroot00000000000000peg-1.0.0/grammars/java/Makefile000066400000000000000000000004601276320170200164550ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. java: java_1_7.peg.go main.go go build java_1_7.peg.go: java_1_7.peg ../../peg -switch -inline java_1_7.peg clean: rm -f java java_1_7.peg.go peg-1.0.0/grammars/java/java_1_7.peg000066400000000000000000000637321276320170200171140ustar00rootroot00000000000000#=========================================================================== # # Parsing Expression Grammar for Java 1.7 for Mouse 1.1 - 1.5. # Based on Chapters 3 and 18 of Java Language Specification, Third Edition, # at http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html, # and description of Java SE 7 enhancements in # http://download.java.net/jdk7/docs/technotes/guides/language/enhancements.html. # #--------------------------------------------------------------------------- # # Copyright (C) 2006, 2009, 2010, 2011 # by Roman R Redziejowski(www.romanredz.se). # # The author gives unlimited permission to copy and distribute # this file, with or without modifications, as long as this notice # is preserved, and any changes are properly documented. # # This file is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # #--------------------------------------------------------------------------- # # Latest update 2011-07-21 # #--------------------------------------------------------------------------- # # Change log # 2006-12-06 Posted on Internet. # 2009-04-04 Modified to conform to Mouse syntax: # Underscore removed from names # \f in Space replaced by Unicode for FormFeed. # 2009-07-10 Unused rule THREADSAFE removed. # 2009-07-10 Copying and distribution conditions relaxed by the author. # 2010-07-01 Updated Mouse version in the comment. # 2010-09-15 Updated comment on Java release. # 2010-09-18 Updated list of reserved words ("keywords") according to # JLS 3.9: added "const" and "goto", removed "threadsafe". # 2010-09-18 Removed superfluous "?" everywhere after "Spacing". # 2010-10-05 Removed erroneous "TypeArguments?" from "EnumConstant". # See JLS 8.9, JLS 18.1. # NB. "Annotations" are optional, but not shown as such in JLS. # 2010-10-20 Corrected "FormalParameterList" according to JLS 8.4.1. # NB. "VariableModifiers" in "FormalParameter" and "LastFormalParameter" # are optional, but not shown as such in JLS. # 2010-10-20 Corrected "Annotation" according to JLS 9.7. # Is incorrect in JLS 18.1 (does not allow list of value pairs). # 2010-10-20 Corrected "LocalVariableDeclarationStatement". # Is incorrect in JLS 18.1: only FINAL allowed as "VariableModifier". # Is incorrect in JLS 14.4: "VariableModifiers" not shown as optional. # 2010-10-20 Corrected "AnnotationTypeElementRest": added SEMI as last alternative. # See JLS 9.6. NB. Missing in JLS 18.1. # 2010-10-20 Moved "Identifier" from "AnnotationTypeElementRest" to # "AnnotationMethodRest". Was incorrect in JLS 18.1. # 2010-10-21 Inverted order of alternatives in "HexSignificand". # 2010-10-24 Corrected previous correction: moved SEMI from # "AnnotationTypeElementRest" to "AnnotationTypeElementDeclaration". # 2010-10-25 Repeated "u" allowed in UnicodeEscape (JLS 3.3). # Line terminators not allowed in StringLiteral (JLS 3.10.5). # (Found thanks to Java PEG for Parboiled, which in turn credits # Reinier Zwitserloot for finding it.) # 2011-07-19 Added SEMI after "VariableDeclarators" in "MemberDecl" (JLS 8.3). # 2011-07-21 Corrected "ArrayInitializer" to allow for "{,}" (JLS 10.6). # #--------------------------------------------------------------------------- # # Changes for Java 1.7 # 2011-07-18 Implemented Binary Literals: added "BinaryNumeral". # 2011-07-19 Implemented Underscores in Numerical Literals: # Added "Digits" and "HexDigits". Removed "Digit". # Modified "DecimalNumeral", "HexNumeral", "BinaryNumeral", # "OctalNumeral", "DecimalFloat", "Exponent", # "HexSignificand", and "BinaryExponent". # 2011-07-20 Implemented Type Inference for Generic Instance Creation: # Added "Diamond". # Modified "ClassCreatorRest" by adding "Diamond?". # 2011-07-20 Implemented try-with-resources Statement: # Added try-with-resources as an alternative of "Statement". # Added "Resource". (Based on comments to JavacParser). # 2011-07-20 Implemented catching of multiple exceptions: # Modified "Catch" to allow multiple exception types. # Based on a pure guess. # #--------------------------------------------------------------------------- # # 2013-02-16 Modified to work with github.com/pointlander/peg # #=========================================================================== #------------------------------------------------------------------------- # Compilation Unit #------------------------------------------------------------------------- package main type Java Peg { } CompilationUnit <- Spacing PackageDeclaration? ImportDeclaration* TypeDeclaration* EOT PackageDeclaration <- Annotation* PACKAGE QualifiedIdentifier SEMI ImportDeclaration <- IMPORT STATIC? QualifiedIdentifier (DOT STAR)? SEMI TypeDeclaration <- Modifier* (ClassDeclaration / EnumDeclaration / InterfaceDeclaration / AnnotationTypeDeclaration) / SEMI #------------------------------------------------------------------------- # Class Declaration #------------------------------------------------------------------------- ClassDeclaration <- CLASS Identifier TypeParameters? (EXTENDS ClassType)? (IMPLEMENTS ClassTypeList)? ClassBody ClassBody <- LWING ClassBodyDeclaration* RWING ClassBodyDeclaration <- SEMI / STATIC? Block # Static or Instance Initializer / Modifier* MemberDecl # ClassMemberDeclaration MemberDecl <- TypeParameters GenericMethodOrConstructorRest # Generic Method or Constructor / Type Identifier MethodDeclaratorRest # Method / Type VariableDeclarators SEMI # Field / VOID Identifier VoidMethodDeclaratorRest # Void method / Identifier ConstructorDeclaratorRest # Constructor / InterfaceDeclaration # Interface / ClassDeclaration # Class / EnumDeclaration # Enum / AnnotationTypeDeclaration # Annotation GenericMethodOrConstructorRest <- (Type / VOID) Identifier MethodDeclaratorRest / Identifier ConstructorDeclaratorRest MethodDeclaratorRest <- FormalParameters Dim* (THROWS ClassTypeList)? (MethodBody / SEMI) VoidMethodDeclaratorRest <- FormalParameters (THROWS ClassTypeList)? (MethodBody / SEMI) ConstructorDeclaratorRest <- FormalParameters (THROWS ClassTypeList)? MethodBody MethodBody <- Block #------------------------------------------------------------------------- # Interface Declaration #------------------------------------------------------------------------- InterfaceDeclaration <- INTERFACE Identifier TypeParameters? (EXTENDS ClassTypeList)? InterfaceBody InterfaceBody <- LWING InterfaceBodyDeclaration* RWING InterfaceBodyDeclaration <- Modifier* InterfaceMemberDecl / SEMI InterfaceMemberDecl <- InterfaceMethodOrFieldDecl / InterfaceGenericMethodDecl / VOID Identifier VoidInterfaceMethodDeclaratorRest / InterfaceDeclaration / AnnotationTypeDeclaration / ClassDeclaration / EnumDeclaration InterfaceMethodOrFieldDecl <- Type Identifier InterfaceMethodOrFieldRest InterfaceMethodOrFieldRest <- ConstantDeclaratorsRest SEMI / InterfaceMethodDeclaratorRest InterfaceMethodDeclaratorRest <- FormalParameters Dim* (THROWS ClassTypeList)? SEM InterfaceGenericMethodDecl <- TypeParameters (Type / VOID) Identifier InterfaceMethodDeclaratorRest VoidInterfaceMethodDeclaratorRest <- FormalParameters (THROWS ClassTypeList)? SEMI ConstantDeclaratorsRest <- ConstantDeclaratorRest (COMMA ConstantDeclarator)* ConstantDeclarator <- Identifier ConstantDeclaratorRest ConstantDeclaratorRest <- Dim* EQU VariableInitializer #------------------------------------------------------------------------- # Enum Declaration #------------------------------------------------------------------------- EnumDeclaration <- ENUM Identifier (IMPLEMENTS ClassTypeList)? EnumBody EnumBody <- LWING EnumConstants? COMMA? EnumBodyDeclarations? RWING EnumConstants <- EnumConstant (COMMA EnumConstant)* EnumConstant <- Annotation* Identifier Arguments? ClassBody? EnumBodyDeclarations <- SEMI ClassBodyDeclaration* #------------------------------------------------------------------------- # Variable Declarations #------------------------------------------------------------------------- LocalVariableDeclarationStatement <- (FINAL / Annotation)* Type VariableDeclarators SEMI VariableDeclarators <- VariableDeclarator (COMMA VariableDeclarator)* VariableDeclarator <- Identifier Dim* (EQU VariableInitializer)? #------------------------------------------------------------------------- # Formal Parameters #------------------------------------------------------------------------- FormalParameters <- LPAR FormalParameterList? RPAR FormalParameter <- (FINAL / Annotation)* Type VariableDeclaratorId LastFormalParameter <- (FINAL / Annotation)* Type ELLIPSIS VariableDeclaratorId FormalParameterList <- FormalParameter (COMMA FormalParameter)* (COMMA LastFormalParameter)? / LastFormalParameter VariableDeclaratorId <- Identifier Dim* #------------------------------------------------------------------------- # Statements #------------------------------------------------------------------------- Block <- LWING BlockStatements RWING BlockStatements <- BlockStatement* BlockStatement <- LocalVariableDeclarationStatement / Modifier* ( ClassDeclaration / EnumDeclaration ) / Statement Statement <- Block / ASSERT Expression (COLON Expression)? SEMI / IF ParExpression Statement (ELSE Statement)? / FOR LPAR ForInit? SEMI Expression? SEMI ForUpdate? RPAR Statement / FOR LPAR FormalParameter COLON Expression RPAR Statement / WHILE ParExpression Statement / DO Statement WHILE ParExpression SEMI / TRY LPAR Resource (SEMI Resource)* SEMI? RPAR Block Catch* Finally? / TRY Block (Catch+ Finally? / Finally) / SWITCH ParExpression LWING SwitchBlockStatementGroups RWING / SYNCHRONIZED ParExpression Block / RETURN Expression? SEMI / THROW Expression SEMI / BREAK Identifier? SEMI / CONTINUE Identifier? SEMI / SEMI / StatementExpression SEMI / Identifier COLON Statement Resource <- Modifier* Type VariableDeclaratorId EQU Expression Catch <- CATCH LPAR (FINAL / Annotation)* Type (OR Type)* VariableDeclaratorId RPAR Block Finally <- FINALLY Block SwitchBlockStatementGroups <- SwitchBlockStatementGroup* SwitchBlockStatementGroup <- SwitchLabel BlockStatements SwitchLabel <- CASE ConstantExpression COLON / CASE EnumConstantName COLON / DEFAULT COLON ForInit <- (FINAL / Annotation)* Type VariableDeclarators / StatementExpression (COMMA StatementExpression)* ForUpdate <- StatementExpression (COMMA StatementExpression)* EnumConstantName <- Identifier #------------------------------------------------------------------------- # Expressions #------------------------------------------------------------------------- StatementExpression <- Expression # This is more generous than definition in section 14.8, which allows only # specific forms of Expression. ConstantExpression <- Expression Expression <- ConditionalExpression (AssignmentOperator ConditionalExpression)* # This definition is part of the modification in JLS Chapter 18 # to minimize look ahead. In JLS Chapter 15.27, Expression is defined # as AssignmentExpression, which is effectively defined as # (LeftHandSide AssignmentOperator)* ConditionalExpression. # The above is obtained by allowing ANY ConditionalExpression # as LeftHandSide, which results in accepting statements like 5 = a. AssignmentOperator <- EQU / PLUSEQU / MINUSEQU / STAREQU / DIVEQU / ANDEQU / OREQU / HATEQU / MODEQU / SLEQU / SREQU / BSREQU ConditionalExpression <- ConditionalOrExpression (QUERY Expression COLON ConditionalOrExpression)* ConditionalOrExpression <- ConditionalAndExpression (OROR ConditionalAndExpression)* ConditionalAndExpression <- InclusiveOrExpression (ANDAND InclusiveOrExpression)* InclusiveOrExpression <- ExclusiveOrExpression (OR ExclusiveOrExpression)* ExclusiveOrExpression <- AndExpression (HAT AndExpression)* AndExpression <- EqualityExpression (AND EqualityExpression)* EqualityExpression <- RelationalExpression ((EQUAL / NOTEQUAL) RelationalExpression)* RelationalExpression <- ShiftExpression ((LE / GE / LT / GT) ShiftExpression / INSTANCEOF ReferenceType)* ShiftExpression <- AdditiveExpression ((SL / SR / BSR) AdditiveExpression)* AdditiveExpression <- MultiplicativeExpression ((PLUS / MINUS) MultiplicativeExpression)* MultiplicativeExpression <- UnaryExpression ((STAR / DIV / MOD) UnaryExpression)* UnaryExpression <- PrefixOp UnaryExpression / LPAR Type RPAR UnaryExpression / Primary (Selector)* (PostfixOp)* Primary <- ParExpression / NonWildcardTypeArguments (ExplicitGenericInvocationSuffix / THIS Arguments) / THIS Arguments? / SUPER SuperSuffix / Literal / NEW Creator / QualifiedIdentifier IdentifierSuffix? / BasicType Dim* DOT CLASS / VOID DOT CLASS IdentifierSuffix <- LBRK ( RBRK Dim* DOT CLASS / Expression RBRK) / Arguments / DOT ( CLASS / ExplicitGenericInvocation / THIS / SUPER Arguments / NEW NonWildcardTypeArguments? InnerCreator ) ExplicitGenericInvocation <- NonWildcardTypeArguments ExplicitGenericInvocationSuffix NonWildcardTypeArguments <- LPOINT ReferenceType (COMMA ReferenceType)* RPOINT ExplicitGenericInvocationSuffix <- SUPER SuperSuffix / Identifier Arguments PrefixOp <- INC / DEC / BANG / TILDA / PLUS / MINUS PostfixOp <- INC / DEC Selector <- DOT Identifier Arguments? / DOT ExplicitGenericInvocation / DOT THIS / DOT SUPER SuperSuffix / DOT NEW NonWildcardTypeArguments? InnerCreator / DimExpr SuperSuffix <- Arguments / DOT Identifier Arguments? BasicType <- ( 'byte' / 'short' / 'char' / 'int' / 'long' / 'float' / 'double' / 'boolean' ) !LetterOrDigit Spacing Arguments <- LPAR (Expression (COMMA Expression)*)? RPAR Creator <- NonWildcardTypeArguments? CreatedName ClassCreatorRest / NonWildcardTypeArguments? (ClassType / BasicType) ArrayCreatorRest CreatedName <- Identifier NonWildcardTypeArguments? (DOT Identifier NonWildcardTypeArguments?)* InnerCreator <- Identifier ClassCreatorRest ArrayCreatorRest <- LBRK ( RBRK Dim* ArrayInitializer / Expression RBRK DimExpr* Dim* ) # This is more generous than JLS 15.10. According to that definition, # BasicType must be followed by at least one DimExpr or by ArrayInitializer. ClassCreatorRest <- Diamond? Arguments ClassBody? Diamond <- LPOINT RPOINT ArrayInitializer <- LWING (VariableInitializer (COMMA VariableInitializer)*)? COMMA? RWING VariableInitializer <- ArrayInitializer / Expression ParExpression <- LPAR Expression RPAR QualifiedIdentifier <- Identifier (DOT Identifier)* Dim <- LBRK RBRK DimExpr <- LBRK Expression RBRK #------------------------------------------------------------------------- # Types and Modifiers #------------------------------------------------------------------------- Type <- (BasicType / ClassType) Dim* ReferenceType <- BasicType Dim+ / ClassType Dim* ClassType <- Identifier TypeArguments? (DOT Identifier TypeArguments?)* ClassTypeList <- ClassType (COMMA ClassType)* TypeArguments <- LPOINT TypeArgument (COMMA TypeArgument)* RPOINT TypeArgument <- ReferenceType / QUERY ((EXTENDS / SUPER) ReferenceType)? TypeParameters <- LPOINT TypeParameter (COMMA TypeParameter)* RPOINT TypeParameter <- Identifier (EXTENDS Bound)? Bound <- ClassType (AND ClassType)* Modifier <- Annotation / ( 'public' / 'protected' / 'private' / 'static' / 'abstract' / 'final' / 'native' / 'synchronized' / 'transient' / 'volatile' / 'strictfp' ) !LetterOrDigit Spacing # This common definition of Modifier is part of the modification # in JLS Chapter 18 to minimize look ahead. The main body of JLS has # different lists of modifiers for different language elements. #------------------------------------------------------------------------- # Annotations #------------------------------------------------------------------------- AnnotationTypeDeclaration <- AT INTERFACE Identifier AnnotationTypeBody AnnotationTypeBody <- LWING AnnotationTypeElementDeclaration* RWING AnnotationTypeElementDeclaration <- Modifier* AnnotationTypeElementRest / SEMI AnnotationTypeElementRest <- Type AnnotationMethodOrConstantRest SEMI / ClassDeclaration / EnumDeclaration / InterfaceDeclaration / AnnotationTypeDeclaration AnnotationMethodOrConstantRest <- AnnotationMethodRest / AnnotationConstantRest AnnotationMethodRest <- Identifier LPAR RPAR DefaultValue? AnnotationConstantRest <- VariableDeclarators DefaultValue <- DEFAULT ElementValue Annotation <- NormalAnnotation / SingleElementAnnotation / MarkerAnnotation NormalAnnotation <- AT QualifiedIdentifier LPAR ElementValuePairs? RPAR SingleElementAnnotation <- AT QualifiedIdentifier LPAR ElementValue RPAR MarkerAnnotation <- AT QualifiedIdentifier ElementValuePairs <- ElementValuePair (COMMA ElementValuePair)* ElementValuePair <- Identifier EQU ElementValue ElementValue <- ConditionalExpression / Annotation / ElementValueArrayInitializer ElementValueArrayInitializer <- LWING ElementValues? COMMA? RWING ElementValues <- ElementValue (COMMA ElementValue)* #========================================================================= # Lexical Structure #========================================================================= #------------------------------------------------------------------------- # JLS 3.6-7 Spacing #------------------------------------------------------------------------- Spacing <- ( [ \t\r\n]+ # WhiteSpace [ \t\r\n\u000C]+ / '/*' (!'*/' .)* '*/' # TraditionalComment / '//' (![\r\n] .)* [\r\n] # EndOfLineComment )* #------------------------------------------------------------------------- # JLS 3.8 Identifiers #------------------------------------------------------------------------- Identifier <- !Keyword Letter LetterOrDigit* Spacing Letter <- [a-z] / [A-Z] / [_$] LetterOrDigit <- [a-z] / [A-Z] / [0-9] / [_$] # These are traditional definitions of letters and digits. # JLS defines letters and digits as Unicode characters recognized # as such by special Java procedures, which is difficult # to express in terms of Parsing Expressions. #------------------------------------------------------------------------- # JLS 3.9 Keywords # More precisely: reserved words. According to JLS, "true", "false", # and "null" are technically not keywords - but still must not appear # as identifiers. Keywords "const" and "goto" are not used; JLS explains # the reason. #------------------------------------------------------------------------- Keyword <- ( 'abstract' / 'assert' / 'boolean' / 'break' / 'byte' / 'case' / 'catch' / 'char' / 'class' / 'const' / 'continue' / 'default' / 'double' / 'do' / 'else' / 'enum' / 'extends' / 'false' / 'finally' / 'final' / 'float' / 'for' / 'goto' / 'if' / 'implements' / 'import' / 'interface' / 'int' / 'instanceof' / 'long' / 'native' / 'new' / 'null' / 'package' / 'private' / 'protected' / 'public' / 'return' / 'short' / 'static' / 'strictfp' / 'super' / 'switch' / 'synchronized' / 'this' / 'throws' / 'throw' / 'transient' / 'true' / 'try' / 'void' / 'volatile' / 'while' ) !LetterOrDigit ASSERT <- 'assert' !LetterOrDigit Spacing BREAK <- 'break' !LetterOrDigit Spacing CASE <- 'case' !LetterOrDigit Spacing CATCH <- 'catch' !LetterOrDigit Spacing CLASS <- 'class' !LetterOrDigit Spacing CONTINUE <- 'continue' !LetterOrDigit Spacing DEFAULT <- 'default' !LetterOrDigit Spacing DO <- 'do' !LetterOrDigit Spacing ELSE <- 'else' !LetterOrDigit Spacing ENUM <- 'enum' !LetterOrDigit Spacing EXTENDS <- 'extends' !LetterOrDigit Spacing FINALLY <- 'finally' !LetterOrDigit Spacing FINAL <- 'final' !LetterOrDigit Spacing FOR <- 'for' !LetterOrDigit Spacing IF <- 'if' !LetterOrDigit Spacing IMPLEMENTS <- 'implements' !LetterOrDigit Spacing IMPORT <- 'import' !LetterOrDigit Spacing INTERFACE <- 'interface' !LetterOrDigit Spacing INSTANCEOF <- 'instanceof' !LetterOrDigit Spacing NEW <- 'new' !LetterOrDigit Spacing PACKAGE <- 'package' !LetterOrDigit Spacing RETURN <- 'return' !LetterOrDigit Spacing STATIC <- 'static' !LetterOrDigit Spacing SUPER <- 'super' !LetterOrDigit Spacing SWITCH <- 'switch' !LetterOrDigit Spacing SYNCHRONIZED <- 'synchronized' !LetterOrDigit Spacing THIS <- 'this' !LetterOrDigit Spacing THROWS <- 'throws' !LetterOrDigit Spacing THROW <- 'throw' !LetterOrDigit Spacing TRY <- 'try' !LetterOrDigit Spacing VOID <- 'void' !LetterOrDigit Spacing WHILE <- 'while' !LetterOrDigit Spacing #------------------------------------------------------------------------- # JLS 3.10 Literals #------------------------------------------------------------------------- Literal <- ( FloatLiteral / IntegerLiteral # May be a prefix of FloatLiteral / CharLiteral / StringLiteral / 'true' !LetterOrDigit / 'false' !LetterOrDigit / 'null' !LetterOrDigit ) Spacing IntegerLiteral <- ( HexNumeral / BinaryNumeral / OctalNumeral # May be a prefix of HexNumeral or BinaryNumeral / DecimalNumeral # May be a prefix of OctalNumeral ) [lL]? DecimalNumeral <- '0' / [1-9] ([_]* [0-9])* HexNumeral <- ('0x' / '0X') HexDigits BinaryNumeral <- ('0b' / '0B') [01] ([_]* [01])* OctalNumeral <- '0' ([_]* [0-7])+ FloatLiteral <- HexFloat / DecimalFloat DecimalFloat <- Digits '.' Digits? Exponent? [fFdD]? / '.' Digits Exponent? [fFdD]? / Digits Exponent [fFdD]? / Digits Exponent? [fFdD] Exponent <- [eE] [+\-]? Digits HexFloat <- HexSignificand BinaryExponent [fFdD]? HexSignificand <- ('0x' / '0X') HexDigits? '.' HexDigits / HexNumeral '.'? # May be a prefix of above BinaryExponent <- [pP] [+\-]? Digits Digits <- [0-9]([_]*[0-9])* HexDigits <- HexDigit ([_]*HexDigit)* HexDigit <- [a-f] / [A-F] / [0-9] CharLiteral <- ['] (Escape / !['\\] .) ['] StringLiteral <- '\"' (Escape / !["\\\n\r] .)* '\"' Escape <- '\\' ([btnfr"'\\] / OctalEscape / UnicodeEscape) OctalEscape <- [0-3][0-7][0-7] / [0-7][0-7] / [0-7] UnicodeEscape <- 'u'+ HexDigit HexDigit HexDigit HexDigit #------------------------------------------------------------------------- # JLS 3.11-12 Separators, Operators #------------------------------------------------------------------------- AT <- '@' Spacing AND <- '&'![=&] Spacing ANDAND <- '&&' Spacing ANDEQU <- '&=' Spacing BANG <- '!' !'=' Spacing BSR <- '>>>' !'=' Spacing BSREQU <- '>>>=' Spacing COLON <- ':' Spacing COMMA <- ',' Spacing DEC <- '--' Spacing DIV <- '/' !'=' Spacing DIVEQU <- '/=' Spacing DOT <- '.' Spacing ELLIPSIS <- '...' Spacing EQU <- '=' !'=' Spacing EQUAL <- '==' Spacing GE <- '>=' Spacing GT <- '>'![=>] Spacing HAT <- '^' !'=' Spacing HATEQU <- '^=' Spacing INC <- '++' Spacing LBRK <- '[' Spacing LE <- '<=' Spacing LPAR <- '(' Spacing LPOINT <- '<' Spacing LT <- '<' ![=<] Spacing LWING <- '{' Spacing MINUS <- '-' ![=\-] Spacing MINUSEQU <- '-=' Spacing MOD <- '%' !'=' Spacing MODEQU <- '%=' Spacing NOTEQUAL <- '!=' Spacing OR <- '|' ![=|] Spacing OREQU <- '|=' Spacing OROR <- '||' Spacing PLUS <- '+' ![=+] Spacing PLUSEQU <- '+=' Spacing QUERY <- '?' Spacing RBRK <- ']' Spacing RPAR <- ')' Spacing RPOINT <- '>' Spacing RWING <- '}' Spacing SEMI <- ';' Spacing SL <- '<<' !'=' Spacing SLEQU <- '<<=' Spacing SR <- '>>' ![=>] Spacing SREQU <- '>>=' Spacing STAR <- '*' !'=' Spacing STAREQU <- '*=' Spacing TILDA <- '~' Spacing EOT <- !. peg-1.0.0/grammars/java/main.go000066400000000000000000000024571276320170200163000ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "fmt" "io/ioutil" "log" "os" "strings" ) func main() { if len(os.Args) < 2 { fmt.Printf("%v FILE\n", os.Args[0]) os.Exit(1) } var walk func(name string) walk = func(name string) { fileInfo, err := os.Stat(name) if err != nil { log.Fatal(err) } if fileInfo.Mode() & (os.ModeNamedPipe | os.ModeSocket | os.ModeDevice) != 0 { /* will lock up if opened */ } else if fileInfo.IsDir() { fmt.Printf("directory %v\n", name) file, err := os.Open(name) if err != nil { log.Fatal(err) } files, err := file.Readdir(-1) if err != nil { log.Fatal(err) } file.Close() for _, f := range files { if !strings.HasSuffix(name, "/") { name += "/" } walk(name + f.Name()) } } else if strings.HasSuffix(name, ".java") { fmt.Printf("parse %v\n", name) file, err := os.Open(name) if err != nil { log.Fatal(err) } buffer, err := ioutil.ReadAll(file) if err != nil { log.Fatal(err) } file.Close() java := &Java{Buffer: string(buffer)} java.Init() if err := java.Parse(); err != nil { log.Fatal(err) } } } walk(os.Args[1]) } peg-1.0.0/grammars/long_test/000077500000000000000000000000001276320170200160725ustar00rootroot00000000000000peg-1.0.0/grammars/long_test/Makefile000066400000000000000000000004401276320170200175300ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. long_test: long.peg.go main.go go build long.peg.go: long.peg peg -switch -inline long.peg clean: rm -f long_test long.peg.go peg-1.0.0/grammars/long_test/long.peg000066400000000000000000000003411276320170200175240ustar00rootroot00000000000000# Copyright 2010 The Go Authors. All rights reserved. # Use of this source code is governed by a BSD-style # license that can be found in the LICENSE file. package main type Long Peg { } String <- '\"' (!'\"' .)* '\"' !. peg-1.0.0/grammars/long_test/main.go000066400000000000000000000007701276320170200173510ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "fmt" "log" ) func main() { expression := "" long := &Long{Buffer: "\"" + expression + "\""} long.Init() for c := 0; c < 100000; c++ { if err := long.Parse(); err != nil { fmt.Printf("%v\n", c) log.Fatal(err) } long.Reset() expression = expression + "X" long.Buffer = "\"" + expression + "\"" } } peg-1.0.0/main.go000066400000000000000000000035021276320170200135360ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "flag" "fmt" "io/ioutil" "log" "os" "runtime" "time" ) var ( inline = flag.Bool("inline", false, "parse rule inlining") _switch = flag.Bool("switch", false, "replace if-else if-else like blocks with switch blocks") syntax = flag.Bool("syntax", false, "print out the syntax tree") highlight = flag.Bool("highlight", false, "test the syntax highlighter") ast = flag.Bool("ast", false, "generate an AST") test = flag.Bool("test", false, "test the PEG parser performance") print = flag.Bool("print", false, "directly dump the syntax tree") ) func main() { runtime.GOMAXPROCS(2) flag.Parse() if flag.NArg() != 1 { flag.Usage() log.Fatalf("FILE: the peg file to compile") } file := flag.Arg(0) buffer, err := ioutil.ReadFile(file) if err != nil { log.Fatal(err) } if *test { iterations, p := 1000, &Peg{Tree: New(*inline, *_switch), Buffer: string(buffer)} p.Init() start := time.Now() for i := 0; i < iterations; i++ { p.Parse() p.Reset() } total := float64(time.Since(start).Nanoseconds()) / float64(1000) fmt.Printf("time: %v us\n", total/float64(iterations)) return } p := &Peg{Tree: New(*inline, *_switch), Buffer: string(buffer), Pretty: true} p.Init() if err := p.Parse(); err != nil { log.Fatal(err) } p.Execute() if *ast { p.AST().Print(p.Buffer) } if *print { p.Print() } if *syntax { p.PrintSyntaxTree() } if *highlight { p.Highlighter() } filename := file + ".go" out, error := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) if error != nil { fmt.Printf("%v: %v\n", filename, error) return } defer out.Close() p.Compile(filename, out) } peg-1.0.0/peg.go000066400000000000000000001114331276320170200133700ustar00rootroot00000000000000// Copyright 2010 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package main import ( "bytes" "fmt" "go/parser" "go/printer" "go/token" "io" "math" "os" "strconv" "strings" "text/template" "github.com/pointlander/jetset" ) const pegHeaderTemplate = `package {{.PackageName}} import ( {{range .Imports}}"{{.}}" {{end}} ) const endSymbol rune = {{.EndSymbol}} /* The rule types inferred from the grammar are below. */ type pegRule {{.PegRuleType}} const ( ruleUnknown pegRule = iota {{range .RuleNames}}rule{{.String}} {{end}} rulePre ruleIn ruleSuf ) var rul3s = [...]string { "Unknown", {{range .RuleNames}}"{{.String}}", {{end}} "Pre_", "_In_", "_Suf", } type node32 struct { token32 up, next *node32 } func (node *node32) print(depth int, buffer string) { for node != nil { for c := 0; c < depth; c++ { fmt.Printf(" ") } fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[node.pegRule], strconv.Quote(string(([]rune(buffer)[node.begin:node.end])))) if node.up != nil { node.up.print(depth + 1, buffer) } node = node.next } } func (node *node32) Print(buffer string) { node.print(0, buffer) } type element struct { node *node32 down *element } {{range .Sizes}} /* ${@} bit structure for abstract syntax tree */ type token{{.}} struct { pegRule begin, end, next uint{{.}} } func (t *token{{.}}) isZero() bool { return t.pegRule == ruleUnknown && t.begin == 0 && t.end == 0 && t.next == 0 } func (t *token{{.}}) isParentOf(u token{{.}}) bool { return t.begin <= u.begin && t.end >= u.end && t.next > u.next } func (t *token{{.}}) getToken32() token32 { return token32{pegRule: t.pegRule, begin: uint32(t.begin), end: uint32(t.end), next: uint32(t.next)} } func (t *token{{.}}) String() string { return fmt.Sprintf("\x1B[34m%v\x1B[m %v %v %v", rul3s[t.pegRule], t.begin, t.end, t.next) } type tokens{{.}} struct { tree []token{{.}} ordered [][]token{{.}} } func (t *tokens{{.}}) trim(length int) { t.tree = t.tree[0:length] } func (t *tokens{{.}}) Print() { for _, token := range t.tree { fmt.Println(token.String()) } } func (t *tokens{{.}}) Order() [][]token{{.}} { if t.ordered != nil { return t.ordered } depths := make([]int{{.}}, 1, math.MaxInt16) for i, token := range t.tree { if token.pegRule == ruleUnknown { t.tree = t.tree[:i] break } depth := int(token.next) if length := len(depths); depth >= length { depths = depths[:depth + 1] } depths[depth]++ } depths = append(depths, 0) ordered, pool := make([][]token{{.}}, len(depths)), make([]token{{.}}, len(t.tree) + len(depths)) for i, depth := range depths { depth++ ordered[i], pool, depths[i] = pool[:depth], pool[depth:], 0 } for i, token := range t.tree { depth := token.next token.next = uint{{.}}(i) ordered[depth][depths[depth]] = token depths[depth]++ } t.ordered = ordered return ordered } type state{{.}} struct { token{{.}} depths []int{{.}} leaf bool } func (t *tokens{{.}}) AST() *node32 { tokens := t.Tokens() stack := &element{node: &node32{token32:<-tokens}} for token := range tokens { if token.begin == token.end { continue } node := &node32{token32: token} for stack != nil && stack.node.begin >= token.begin && stack.node.end <= token.end { stack.node.next = node.up node.up = stack.node stack = stack.down } stack = &element{node: node, down: stack} } return stack.node } func (t *tokens{{.}}) PreOrder() (<-chan state{{.}}, [][]token{{.}}) { s, ordered := make(chan state{{.}}, 6), t.Order() go func() { var states [8]state{{.}} for i := range states { states[i].depths = make([]int{{.}}, len(ordered)) } depths, state, depth := make([]int{{.}}, len(ordered)), 0, 1 write := func(t token{{.}}, leaf bool) { S := states[state] state, S.pegRule, S.begin, S.end, S.next, S.leaf = (state + 1) % 8, t.pegRule, t.begin, t.end, uint{{.}}(depth), leaf copy(S.depths, depths) s <- S } states[state].token{{.}} = ordered[0][0] depths[0]++ state++ a, b := ordered[depth - 1][depths[depth - 1] - 1], ordered[depth][depths[depth]] depthFirstSearch: for { for { if i := depths[depth]; i > 0 { if c, j := ordered[depth][i - 1], depths[depth - 1]; a.isParentOf(c) && (j < 2 || !ordered[depth - 1][j - 2].isParentOf(c)) { if c.end != b.begin { write(token{{.}} {pegRule: ruleIn, begin: c.end, end: b.begin}, true) } break } } if a.begin < b.begin { write(token{{.}} {pegRule: rulePre, begin: a.begin, end: b.begin}, true) } break } next := depth + 1 if c := ordered[next][depths[next]]; c.pegRule != ruleUnknown && b.isParentOf(c) { write(b, false) depths[depth]++ depth, a, b = next, b, c continue } write(b, true) depths[depth]++ c, parent := ordered[depth][depths[depth]], true for { if c.pegRule != ruleUnknown && a.isParentOf(c) { b = c continue depthFirstSearch } else if parent && b.end != a.end { write(token{{.}} {pegRule: ruleSuf, begin: b.end, end: a.end}, true) } depth-- if depth > 0 { a, b, c = ordered[depth - 1][depths[depth - 1] - 1], a, ordered[depth][depths[depth]] parent = a.isParentOf(b) continue } break depthFirstSearch } } close(s) }() return s, ordered } func (t *tokens{{.}}) PrintSyntax() { tokens, ordered := t.PreOrder() max := -1 for token := range tokens { if !token.leaf { fmt.Printf("%v", token.begin) for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { fmt.Printf(" \x1B[36m%v\x1B[m", rul3s[ordered[i][depths[i] - 1].pegRule]) } fmt.Printf(" \x1B[36m%v\x1B[m\n", rul3s[token.pegRule]) } else if token.begin == token.end { fmt.Printf("%v", token.begin) for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { fmt.Printf(" \x1B[31m%v\x1B[m", rul3s[ordered[i][depths[i] - 1].pegRule]) } fmt.Printf(" \x1B[31m%v\x1B[m\n", rul3s[token.pegRule]) } else { for c, end := token.begin, token.end; c < end; c++ { if i := int(c); max + 1 < i { for j := max; j < i; j++ { fmt.Printf("skip %v %v\n", j, token.String()) } max = i } else if i := int(c); i <= max { for j := i; j <= max; j++ { fmt.Printf("dupe %v %v\n", j, token.String()) } } else { max = int(c) } fmt.Printf("%v", c) for i, leaf, depths := 0, int(token.next), token.depths; i < leaf; i++ { fmt.Printf(" \x1B[34m%v\x1B[m", rul3s[ordered[i][depths[i] - 1].pegRule]) } fmt.Printf(" \x1B[34m%v\x1B[m\n", rul3s[token.pegRule]) } fmt.Printf("\n") } } } func (t *tokens{{.}}) PrintSyntaxTree(buffer string) { tokens, _ := t.PreOrder() for token := range tokens { for c := 0; c < int(token.next); c++ { fmt.Printf(" ") } fmt.Printf("\x1B[34m%v\x1B[m %v\n", rul3s[token.pegRule], strconv.Quote(string(([]rune(buffer)[token.begin:token.end])))) } } func (t *tokens{{.}}) Add(rule pegRule, begin, end, depth uint32, index int) { t.tree[index] = token{{.}}{pegRule: rule, begin: uint{{.}}(begin), end: uint{{.}}(end), next: uint{{.}}(depth)} } func (t *tokens{{.}}) Tokens() <-chan token32 { s := make(chan token32, 16) go func() { for _, v := range t.tree { s <- v.getToken32() } close(s) }() return s } func (t *tokens{{.}}) Error() []token32 { ordered := t.Order() length := len(ordered) tokens, length := make([]token32, length), length - 1 for i := range tokens { o := ordered[length - i] if len(o) > 1 { tokens[i] = o[len(o) - 2].getToken32() } } return tokens } {{end}} func (t *tokens32) Expand(index int) { tree := t.tree if index >= len(tree) { expanded := make([]token32, 2 * len(tree)) copy(expanded, tree) t.tree = expanded } } type {{.StructName}} struct { {{.StructVariables}} Buffer string buffer []rune rules [{{.RulesCount}}]func() bool Parse func(rule ...int) error Reset func() Pretty bool tokens32 } type textPosition struct { line, symbol int } type textPositionMap map[int] textPosition func translatePositions(buffer []rune, positions []int) textPositionMap { length, translations, j, line, symbol := len(positions), make(textPositionMap, len(positions)), 0, 1, 0 sort.Ints(positions) search: for i, c := range buffer { if c == '\n' {line, symbol = line + 1, 0} else {symbol++} if i == positions[j] { translations[positions[j]] = textPosition{line, symbol} for j++; j < length; j++ {if i != positions[j] {continue search}} break search } } return translations } type parseError struct { p *{{.StructName}} max token32 } func (e *parseError) Error() string { tokens, error := []token32{e.max}, "\n" positions, p := make([]int, 2 * len(tokens)), 0 for _, token := range tokens { positions[p], p = int(token.begin), p + 1 positions[p], p = int(token.end), p + 1 } translations := translatePositions(e.p.buffer, positions) format := "parse error near %v (line %v symbol %v - line %v symbol %v):\n%v\n" if e.p.Pretty { format = "parse error near \x1B[34m%v\x1B[m (line %v symbol %v - line %v symbol %v):\n%v\n" } for _, token := range tokens { begin, end := int(token.begin), int(token.end) error += fmt.Sprintf(format, rul3s[token.pegRule], translations[begin].line, translations[begin].symbol, translations[end].line, translations[end].symbol, strconv.Quote(string(e.p.buffer[begin:end]))) } return error } func (p *{{.StructName}}) PrintSyntaxTree() { p.tokens32.PrintSyntaxTree(p.Buffer) } func (p *{{.StructName}}) Highlighter() { p.PrintSyntax() } {{if .HasActions}} func (p *{{.StructName}}) Execute() { buffer, _buffer, text, begin, end := p.Buffer, p.buffer, "", 0, 0 for token := range p.Tokens() { switch (token.pegRule) { {{if .HasPush}} case rulePegText: begin, end = int(token.begin), int(token.end) text = string(_buffer[begin:end]) {{end}} {{range .Actions}}case ruleAction{{.GetId}}: {{.String}} {{end}} } } _, _, _, _, _ = buffer, _buffer, text, begin, end } {{end}} func (p *{{.StructName}}) Init() { p.buffer = []rune(p.Buffer) if len(p.buffer) == 0 || p.buffer[len(p.buffer) - 1] != endSymbol { p.buffer = append(p.buffer, endSymbol) } tree := tokens32{tree: make([]token32, math.MaxInt16)} var max token32 position, depth, tokenIndex, buffer, _rules := uint32(0), uint32(0), 0, p.buffer, p.rules p.Parse = func(rule ...int) error { r := 1 if len(rule) > 0 { r = rule[0] } matches := p.rules[r]() p.tokens32 = tree if matches { p.trim(tokenIndex) return nil } return &parseError{p, max} } p.Reset = func() { position, tokenIndex, depth = 0, 0, 0 } add := func(rule pegRule, begin uint32) { tree.Expand(tokenIndex) tree.Add(rule, begin, position, depth, tokenIndex) tokenIndex++ if begin != position && position > max.end { max = token32{rule, begin, position, depth} } } {{if .HasDot}} matchDot := func() bool { if buffer[position] != endSymbol { position++ return true } return false } {{end}} {{if .HasCharacter}} /*matchChar := func(c byte) bool { if buffer[position] == c { position++ return true } return false }*/ {{end}} {{if .HasString}} matchString := func(s string) bool { i := position for _, c := range s { if buffer[i] != c { return false } i++ } position = i return true } {{end}} {{if .HasRange}} /*matchRange := func(lower byte, upper byte) bool { if c := buffer[position]; c >= lower && c <= upper { position++ return true } return false }*/ {{end}} _rules = [...]func() bool { nil,` type Type uint8 const ( TypeUnknown Type = iota TypeRule TypeName TypeDot TypeCharacter TypeRange TypeString TypePredicate TypeStateChange TypeCommit TypeAction TypePackage TypeImport TypeState TypeAlternate TypeUnorderedAlternate TypeSequence TypePeekFor TypePeekNot TypeQuery TypeStar TypePlus TypePeg TypePush TypeImplicitPush TypeNil TypeLast ) var TypeMap = [...]string{ "TypeUnknown", "TypeRule", "TypeName", "TypeDot", "TypeCharacter", "TypeRange", "TypeString", "TypePredicate", "TypeCommit", "TypeAction", "TypePackage", "TypeImport", "TypeState", "TypeAlternate", "TypeUnorderedAlternate", "TypeSequence", "TypePeekFor", "TypePeekNot", "TypeQuery", "TypeStar", "TypePlus", "TypePeg", "TypePush", "TypeImplicitPush", "TypeNil", "TypeLast"} func (t Type) GetType() Type { return t } type Node interface { fmt.Stringer debug() Escaped() string SetString(s string) GetType() Type SetType(t Type) GetId() int SetId(id int) Init() Front() *node Next() *node PushFront(value *node) PopFront() *node PushBack(value *node) Len() int Copy() *node Slice() []*node } type node struct { Type string id int front *node back *node length int /* use hash table here instead of Copy? */ next *node } func (n *node) String() string { return n.string } func (n *node) debug() { if len(n.string) == 1 { fmt.Printf("%v %v '%v' %d\n", n.id, TypeMap[n.Type], n.string, n.string[0]) } else { fmt.Printf("%v %v '%v'\n", n.id, TypeMap[n.Type], n.string) } } func (n *node) Escaped() string { return escape(n.string) } func (n *node) SetString(s string) { n.string = s } func (n *node) SetType(t Type) { n.Type = t } func (n *node) GetId() int { return n.id } func (n *node) SetId(id int) { n.id = id } func (n *node) Init() { n.front = nil n.back = nil n.length = 0 } func (n *node) Front() *node { return n.front } func (n *node) Next() *node { return n.next } func (n *node) PushFront(value *node) { if n.back == nil { n.back = value } else { value.next = n.front } n.front = value n.length++ } func (n *node) PopFront() *node { front := n.front switch true { case front == nil: panic("tree is empty") case front == n.back: n.front, n.back = nil, nil default: n.front, front.next = front.next, nil } n.length-- return front } func (n *node) PushBack(value *node) { if n.front == nil { n.front = value } else { n.back.next = value } n.back = value n.length++ } func (n *node) Len() (c int) { return n.length } func (n *node) Copy() *node { return &node{Type: n.Type, string: n.string, id: n.id, front: n.front, back: n.back, length: n.length} } func (n *node) Slice() []*node { s := make([]*node, n.length) for element, i := n.Front(), 0; element != nil; element, i = element.Next(), i+1 { s[i] = element } return s } /* A tree data structure into which a PEG can be parsed. */ type Tree struct { Rules map[string]Node rulesCount map[string]uint node inline, _switch bool RuleNames []Node Sizes [1]int PackageName string Imports []string EndSymbol rune PegRuleType string StructName string StructVariables string RulesCount int Bits int HasActions bool Actions []Node HasPush bool HasCommit bool HasDot bool HasCharacter bool HasString bool HasRange bool } func New(inline, _switch bool) *Tree { return &Tree{Rules: make(map[string]Node), Sizes: [1]int{32}, rulesCount: make(map[string]uint), inline: inline, _switch: _switch} } func (t *Tree) AddRule(name string) { t.PushFront(&node{Type: TypeRule, string: name, id: t.RulesCount}) t.RulesCount++ } func (t *Tree) AddExpression() { expression := t.PopFront() rule := t.PopFront() rule.PushBack(expression) t.PushBack(rule) } func (t *Tree) AddName(text string) { t.PushFront(&node{Type: TypeName, string: text}) } func (t *Tree) AddDot() { t.PushFront(&node{Type: TypeDot, string: "."}) } func (t *Tree) AddCharacter(text string) { t.PushFront(&node{Type: TypeCharacter, string: text}) } func (t *Tree) AddDoubleCharacter(text string) { t.PushFront(&node{Type: TypeCharacter, string: strings.ToLower(text)}) t.PushFront(&node{Type: TypeCharacter, string: strings.ToUpper(text)}) t.AddAlternate() } func (t *Tree) AddHexaCharacter(text string) { hexa, _ := strconv.ParseInt(text, 16, 32) t.PushFront(&node{Type: TypeCharacter, string: string(hexa)}) } func (t *Tree) AddOctalCharacter(text string) { octal, _ := strconv.ParseInt(text, 8, 8) t.PushFront(&node{Type: TypeCharacter, string: string(octal)}) } func (t *Tree) AddPredicate(text string) { t.PushFront(&node{Type: TypePredicate, string: text}) } func (t *Tree) AddStateChange(text string) { t.PushFront(&node{Type: TypeStateChange, string: text}) } func (t *Tree) AddNil() { t.PushFront(&node{Type: TypeNil, string: ""}) } func (t *Tree) AddAction(text string) { t.PushFront(&node{Type: TypeAction, string: text}) } func (t *Tree) AddPackage(text string) { t.PushBack(&node{Type: TypePackage, string: text}) } func (t *Tree) AddImport(text string) { t.PushBack(&node{Type: TypeImport, string: text}) } func (t *Tree) AddState(text string) { peg := t.PopFront() peg.PushBack(&node{Type: TypeState, string: text}) t.PushBack(peg) } func (t *Tree) addList(listType Type) { a := t.PopFront() b := t.PopFront() var l *node if b.GetType() == listType { l = b } else { l = &node{Type: listType} l.PushBack(b) } l.PushBack(a) t.PushFront(l) } func (t *Tree) AddAlternate() { t.addList(TypeAlternate) } func (t *Tree) AddSequence() { t.addList(TypeSequence) } func (t *Tree) AddRange() { t.addList(TypeRange) } func (t *Tree) AddDoubleRange() { a := t.PopFront() b := t.PopFront() t.AddCharacter(strings.ToLower(b.String())) t.AddCharacter(strings.ToLower(a.String())) t.addList(TypeRange) t.AddCharacter(strings.ToUpper(b.String())) t.AddCharacter(strings.ToUpper(a.String())) t.addList(TypeRange) t.AddAlternate() } func (t *Tree) addFix(fixType Type) { n := &node{Type: fixType} n.PushBack(t.PopFront()) t.PushFront(n) } func (t *Tree) AddPeekFor() { t.addFix(TypePeekFor) } func (t *Tree) AddPeekNot() { t.addFix(TypePeekNot) } func (t *Tree) AddQuery() { t.addFix(TypeQuery) } func (t *Tree) AddStar() { t.addFix(TypeStar) } func (t *Tree) AddPlus() { t.addFix(TypePlus) } func (t *Tree) AddPush() { t.addFix(TypePush) } func (t *Tree) AddPeg(text string) { t.PushFront(&node{Type: TypePeg, string: text}) } func join(tasks []func()) { length := len(tasks) done := make(chan int, length) for _, task := range tasks { go func(task func()) { task(); done <- 1 }(task) } for d := <-done; d < length; d += <-done { } } func escape(c string) string { switch c { case "'": return "\\'" case "\"": return "\"" default: c = strconv.Quote(c) return c[1 : len(c)-1] } } func (t *Tree) Compile(file string, out io.Writer) { t.AddImport("fmt") t.AddImport("math") t.AddImport("sort") t.AddImport("strconv") t.EndSymbol = 0x110000 t.RulesCount++ counts := [TypeLast]uint{} { var rule *node var link func(node Node) link = func(n Node) { nodeType := n.GetType() id := counts[nodeType] counts[nodeType]++ switch nodeType { case TypeAction: n.SetId(int(id)) copy, name := n.Copy(), fmt.Sprintf("Action%v", id) t.Actions = append(t.Actions, copy) n.Init() n.SetType(TypeName) n.SetString(name) n.SetId(t.RulesCount) emptyRule := &node{Type: TypeRule, string: name, id: t.RulesCount} implicitPush := &node{Type: TypeImplicitPush} emptyRule.PushBack(implicitPush) implicitPush.PushBack(copy) implicitPush.PushBack(emptyRule.Copy()) t.PushBack(emptyRule) t.RulesCount++ t.Rules[name] = emptyRule t.RuleNames = append(t.RuleNames, emptyRule) case TypeName: name := n.String() if _, ok := t.Rules[name]; !ok { emptyRule := &node{Type: TypeRule, string: name, id: t.RulesCount} implicitPush := &node{Type: TypeImplicitPush} emptyRule.PushBack(implicitPush) implicitPush.PushBack(&node{Type: TypeNil, string: ""}) implicitPush.PushBack(emptyRule.Copy()) t.PushBack(emptyRule) t.RulesCount++ t.Rules[name] = emptyRule t.RuleNames = append(t.RuleNames, emptyRule) } case TypePush: copy, name := rule.Copy(), "PegText" copy.SetString(name) if _, ok := t.Rules[name]; !ok { emptyRule := &node{Type: TypeRule, string: name, id: t.RulesCount} emptyRule.PushBack(&node{Type: TypeNil, string: ""}) t.PushBack(emptyRule) t.RulesCount++ t.Rules[name] = emptyRule t.RuleNames = append(t.RuleNames, emptyRule) } n.PushBack(copy) fallthrough case TypeImplicitPush: link(n.Front()) case TypeRule, TypeAlternate, TypeUnorderedAlternate, TypeSequence, TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: for _, node := range n.Slice() { link(node) } } } /* first pass */ for _, node := range t.Slice() { switch node.GetType() { case TypePackage: t.PackageName = node.String() case TypeImport: t.Imports = append(t.Imports, node.String()) case TypePeg: t.StructName = node.String() t.StructVariables = node.Front().String() case TypeRule: if _, ok := t.Rules[node.String()]; !ok { expression := node.Front() copy := expression.Copy() expression.Init() expression.SetType(TypeImplicitPush) expression.PushBack(copy) expression.PushBack(node.Copy()) t.Rules[node.String()] = node t.RuleNames = append(t.RuleNames, node) } } } /* second pass */ for _, node := range t.Slice() { if node.GetType() == TypeRule { rule = node link(node) } } } join([]func(){ func() { var countRules func(node Node) ruleReached := make([]bool, t.RulesCount) countRules = func(node Node) { switch node.GetType() { case TypeRule: name, id := node.String(), node.GetId() if count, ok := t.rulesCount[name]; ok { t.rulesCount[name] = count + 1 } else { t.rulesCount[name] = 1 } if ruleReached[id] { return } ruleReached[id] = true countRules(node.Front()) case TypeName: countRules(t.Rules[node.String()]) case TypeImplicitPush, TypePush: countRules(node.Front()) case TypeAlternate, TypeUnorderedAlternate, TypeSequence, TypePeekFor, TypePeekNot, TypeQuery, TypeStar, TypePlus: for _, element := range node.Slice() { countRules(element) } } } for _, node := range t.Slice() { if node.GetType() == TypeRule { countRules(node) break } } }, func() { var checkRecursion func(node Node) bool ruleReached := make([]bool, t.RulesCount) checkRecursion = func(node Node) bool { switch node.GetType() { case TypeRule: id := node.GetId() if ruleReached[id] { fmt.Fprintf(os.Stderr, "possible infinite left recursion in rule '%v'\n", node) return false } ruleReached[id] = true consumes := checkRecursion(node.Front()) ruleReached[id] = false return consumes case TypeAlternate: for _, element := range node.Slice() { if !checkRecursion(element) { return false } } return true case TypeSequence: for _, element := range node.Slice() { if checkRecursion(element) { return true } } case TypeName: return checkRecursion(t.Rules[node.String()]) case TypePlus, TypePush, TypeImplicitPush: return checkRecursion(node.Front()) case TypeCharacter, TypeString: return len(node.String()) > 0 case TypeDot, TypeRange: return true } return false } for _, node := range t.Slice() { if node.GetType() == TypeRule { checkRecursion(node) } } }}) if t._switch { var optimizeAlternates func(node Node) (consumes bool, s jetset.Set) cache, firstPass := make([]struct { reached, consumes bool s jetset.Set }, t.RulesCount), true optimizeAlternates = func(n Node) (consumes bool, s jetset.Set) { /*n.debug()*/ switch n.GetType() { case TypeRule: cache := &cache[n.GetId()] if cache.reached { consumes, s = cache.consumes, cache.s return } cache.reached = true consumes, s = optimizeAlternates(n.Front()) cache.consumes, cache.s = consumes, s case TypeName: consumes, s = optimizeAlternates(t.Rules[n.String()]) case TypeDot: consumes = true /* TypeDot set doesn't include the EndSymbol */ s = s.Add(uint64(t.EndSymbol)) s = s.Complement(uint64(t.EndSymbol)) case TypeString, TypeCharacter: consumes = true s = s.Add(uint64([]rune(n.String())[0])) case TypeRange: consumes = true element := n.Front() lower := []rune(element.String())[0] element = element.Next() upper := []rune(element.String())[0] s = s.AddRange(uint64(lower), uint64(upper)) case TypeAlternate: consumes = true mconsumes, properties, c := consumes, make([]struct { intersects bool s jetset.Set }, n.Len()), 0 for _, element := range n.Slice() { mconsumes, properties[c].s = optimizeAlternates(element) consumes = consumes && mconsumes s = s.Union(properties[c].s) c++ } if firstPass { break } intersections := 2 compare: for ai, a := range properties[0 : len(properties)-1] { for _, b := range properties[ai+1:] { if a.s.Intersects(b.s) { intersections++ properties[ai].intersects = true continue compare } } } if intersections >= len(properties) { break } c, unordered, ordered, max := 0, &node{Type: TypeUnorderedAlternate}, &node{Type: TypeAlternate}, 0 for _, element := range n.Slice() { if properties[c].intersects { ordered.PushBack(element.Copy()) } else { class := &node{Type: TypeUnorderedAlternate} for d := 0; d < 256; d++ { if properties[c].s.Has(uint64(d)) { class.PushBack(&node{Type: TypeCharacter, string: string(d)}) } } sequence, predicate, length := &node{Type: TypeSequence}, &node{Type: TypePeekFor}, properties[c].s.Len() if length == 0 { class.PushBack(&node{Type: TypeNil, string: ""}) } predicate.PushBack(class) sequence.PushBack(predicate) sequence.PushBack(element.Copy()) if element.GetType() == TypeNil { unordered.PushBack(sequence) } else if length > max { unordered.PushBack(sequence) max = length } else { unordered.PushFront(sequence) } } c++ } n.Init() if ordered.Front() == nil { n.SetType(TypeUnorderedAlternate) for _, element := range unordered.Slice() { n.PushBack(element.Copy()) } } else { for _, element := range ordered.Slice() { n.PushBack(element.Copy()) } n.PushBack(unordered) } case TypeSequence: classes, elements := make([]struct { s jetset.Set }, n.Len()), n.Slice() for c, element := range elements { consumes, classes[c].s = optimizeAlternates(element) if consumes { elements, classes = elements[c+1:], classes[:c+1] break } } for c := len(classes) - 1; c >= 0; c-- { s = s.Union(classes[c].s) } for _, element := range elements { optimizeAlternates(element) } case TypePeekNot, TypePeekFor: optimizeAlternates(n.Front()) case TypeQuery, TypeStar: _, s = optimizeAlternates(n.Front()) case TypePlus, TypePush, TypeImplicitPush: consumes, s = optimizeAlternates(n.Front()) case TypeAction, TypeNil: //empty } return } for _, element := range t.Slice() { if element.GetType() == TypeRule { optimizeAlternates(element) break } } for i, _ := range cache { cache[i].reached = false } firstPass = false for _, element := range t.Slice() { if element.GetType() == TypeRule { optimizeAlternates(element) break } } } var buffer bytes.Buffer defer func() { fileSet := token.NewFileSet() code, error := parser.ParseFile(fileSet, file, &buffer, parser.ParseComments) if error != nil { buffer.WriteTo(out) fmt.Printf("%v: %v\n", file, error) return } formatter := printer.Config{Mode: printer.TabIndent | printer.UseSpaces, Tabwidth: 8} error = formatter.Fprint(out, fileSet, code) if error != nil { buffer.WriteTo(out) fmt.Printf("%v: %v\n", file, error) return } }() _print := func(format string, a ...interface{}) { fmt.Fprintf(&buffer, format, a...) } printSave := func(n uint) { _print("\n position%d, tokenIndex%d, depth%d := position, tokenIndex, depth", n, n, n) } printRestore := func(n uint) { _print("\n position, tokenIndex, depth = position%d, tokenIndex%d, depth%d", n, n, n) } printTemplate := func(s string) { if error := template.Must(template.New("peg").Parse(s)).Execute(&buffer, t); error != nil { panic(error) } } t.HasActions = counts[TypeAction] > 0 t.HasPush = counts[TypePush] > 0 t.HasCommit = counts[TypeCommit] > 0 t.HasDot = counts[TypeDot] > 0 t.HasCharacter = counts[TypeCharacter] > 0 t.HasString = counts[TypeString] > 0 t.HasRange = counts[TypeRange] > 0 var printRule func(n Node) var compile func(expression Node, ko uint) var label uint labels := make(map[uint]bool) printBegin := func() { _print("\n {") } printEnd := func() { _print("\n }") } printLabel := func(n uint) { _print("\n") if labels[n] { _print(" l%d:\t", n) } } printJump := func(n uint) { _print("\n goto l%d", n) labels[n] = true } printRule = func(n Node) { switch n.GetType() { case TypeRule: _print("%v <- ", n) printRule(n.Front()) case TypeDot: _print(".") case TypeName: _print("%v", n) case TypeCharacter: _print("'%v'", escape(n.String())) case TypeString: s := escape(n.String()) _print("'%v'", s[1:len(s)-1]) case TypeRange: element := n.Front() lower := element element = element.Next() upper := element _print("[%v-%v]", escape(lower.String()), escape(upper.String())) case TypePredicate: _print("&{%v}", n) case TypeStateChange: _print("!{%v}", n) case TypeAction: _print("{%v}", n) case TypeCommit: _print("commit") case TypeAlternate: _print("(") elements := n.Slice() printRule(elements[0]) for _, element := range elements[1:] { _print(" / ") printRule(element) } _print(")") case TypeUnorderedAlternate: _print("(") elements := n.Slice() printRule(elements[0]) for _, element := range elements[1:] { _print(" | ") printRule(element) } _print(")") case TypeSequence: _print("(") elements := n.Slice() printRule(elements[0]) for _, element := range elements[1:] { _print(" ") printRule(element) } _print(")") case TypePeekFor: _print("&") printRule(n.Front()) case TypePeekNot: _print("!") printRule(n.Front()) case TypeQuery: printRule(n.Front()) _print("?") case TypeStar: printRule(n.Front()) _print("*") case TypePlus: printRule(n.Front()) _print("+") case TypePush, TypeImplicitPush: _print("<") printRule(n.Front()) _print(">") case TypeNil: default: fmt.Fprintf(os.Stderr, "illegal node type: %v\n", n.GetType()) } } compile = func(n Node, ko uint) { switch n.GetType() { case TypeRule: fmt.Fprintf(os.Stderr, "internal error #1 (%v)\n", n) case TypeDot: _print("\n if !matchDot() {") /*print("\n if buffer[position] == endSymbol {")*/ printJump(ko) /*print("}\nposition++")*/ _print("}") case TypeName: name := n.String() rule := t.Rules[name] if t.inline && t.rulesCount[name] == 1 { compile(rule.Front(), ko) return } _print("\n if !_rules[rule%v]() {", name /*rule.GetId()*/) printJump(ko) _print("}") case TypeRange: element := n.Front() lower := element element = element.Next() upper := element /*print("\n if !matchRange('%v', '%v') {", escape(lower.String()), escape(upper.String()))*/ _print("\n if c := buffer[position]; c < rune('%v') || c > rune('%v') {", escape(lower.String()), escape(upper.String())) printJump(ko) _print("}\nposition++") case TypeCharacter: /*print("\n if !matchChar('%v') {", escape(n.String()))*/ _print("\n if buffer[position] != rune('%v') {", escape(n.String())) printJump(ko) _print("}\nposition++") case TypeString: _print("\n if !matchString(%v) {", strconv.Quote(n.String())) printJump(ko) _print("}") case TypePredicate: _print("\n if !(%v) {", n) printJump(ko) _print("}") case TypeStateChange: _print("\n %v", n) case TypeAction: case TypeCommit: case TypePush: fallthrough case TypeImplicitPush: ok, element := label, n.Front() label++ nodeType, rule := element.GetType(), element.Next() printBegin() if nodeType == TypeAction { _print("\nadd(rule%v, position)", rule) } else { _print("\nposition%d := position", ok) _print("\ndepth++") compile(element, ko) _print("\ndepth--") _print("\nadd(rule%v, position%d)", rule, ok) } printEnd() case TypeAlternate: ok := label label++ printBegin() elements := n.Slice() printSave(ok) for _, element := range elements[:len(elements)-1] { next := label label++ compile(element, next) printJump(ok) printLabel(next) printRestore(ok) } compile(elements[len(elements)-1], ko) printEnd() printLabel(ok) case TypeUnorderedAlternate: done, ok := ko, label label++ printBegin() _print("\n switch buffer[position] {") elements := n.Slice() elements, last := elements[:len(elements)-1], elements[len(elements)-1].Front().Next() for _, element := range elements { sequence := element.Front() class := sequence.Front() sequence = sequence.Next() _print("\n case") comma := false for _, character := range class.Slice() { if comma { _print(",") } else { comma = true } _print(" '%s'", escape(character.String())) } _print(":") compile(sequence, done) _print("\nbreak") } _print("\n default:") compile(last, done) _print("\nbreak") _print("\n }") printEnd() printLabel(ok) case TypeSequence: for _, element := range n.Slice() { compile(element, ko) } case TypePeekFor: ok := label label++ printBegin() printSave(ok) compile(n.Front(), ko) printRestore(ok) printEnd() case TypePeekNot: ok := label label++ printBegin() printSave(ok) compile(n.Front(), ok) printJump(ko) printLabel(ok) printRestore(ok) printEnd() case TypeQuery: qko := label label++ qok := label label++ printBegin() printSave(qko) compile(n.Front(), qko) printJump(qok) printLabel(qko) printRestore(qko) printEnd() printLabel(qok) case TypeStar: again := label label++ out := label label++ printLabel(again) printBegin() printSave(out) compile(n.Front(), out) printJump(again) printLabel(out) printRestore(out) printEnd() case TypePlus: again := label label++ out := label label++ compile(n.Front(), ko) printLabel(again) printBegin() printSave(out) compile(n.Front(), out) printJump(again) printLabel(out) printRestore(out) printEnd() case TypeNil: default: fmt.Fprintf(os.Stderr, "illegal node type: %v\n", n.GetType()) } } /* lets figure out which jump labels are going to be used with this dry compile */ printTemp, _print := _print, func(format string, a ...interface{}) {} for _, element := range t.Slice() { if element.GetType() != TypeRule { continue } expression := element.Front() if expression.GetType() == TypeNil { continue } ko := label label++ if count, ok := t.rulesCount[element.String()]; !ok { continue } else if t.inline && count == 1 && ko != 0 { continue } compile(expression, ko) } _print, label = printTemp, 0 /* now for the real compile pass */ t.PegRuleType = "uint8" if length := int64(t.Len()); length > math.MaxUint32 { t.PegRuleType = "uint64" } else if length > math.MaxUint16 { t.PegRuleType = "uint32" } else if length > math.MaxUint8 { t.PegRuleType = "uint16" } printTemplate(pegHeaderTemplate) for _, element := range t.Slice() { if element.GetType() != TypeRule { continue } expression := element.Front() if implicit := expression.Front(); expression.GetType() == TypeNil || implicit.GetType() == TypeNil { if element.String() != "PegText" { fmt.Fprintf(os.Stderr, "rule '%v' used but not defined\n", element) } _print("\n nil,") continue } ko := label label++ _print("\n /* %v ", element.GetId()) printRule(element) _print(" */") if count, ok := t.rulesCount[element.String()]; !ok { fmt.Fprintf(os.Stderr, "rule '%v' defined but not used\n", element) _print("\n nil,") continue } else if t.inline && count == 1 && ko != 0 { _print("\n nil,") continue } _print("\n func() bool {") if labels[ko] { printSave(ko) } compile(expression, ko) //print("\n fmt.Printf(\"%v\\n\")", element.String()) _print("\n return true") if labels[ko] { printLabel(ko) printRestore(ko) _print("\n return false") } _print("\n },") } _print("\n }\n p.rules = _rules") _print("\n}\n") } peg-1.0.0/peg.peg000066400000000000000000000121461276320170200135370ustar00rootroot00000000000000# PE Grammar for PE Grammars # # Adapted from [1] by Ian Piumarta . # # Best viewed using 140 columns monospaced with tabs every 8. # # [1] Bryan Ford. "Parsing Expression Grammars: A Recognition-Based Syntactic # Foundation." Symposium on Principles of Programming Languages, # January 14--16, 2004, Venice, Italy. package main # parser declaration type Peg Peg { *Tree } # Hierarchical syntax Grammar <- Spacing 'package' MustSpacing Identifier { p.AddPackage(text) } Import* 'type' MustSpacing Identifier { p.AddPeg(text) } 'Peg' Spacing Action { p.AddState(text) } Definition+ EndOfFile Import <- 'import' Spacing ["] < [a-zA-Z_/.\-]+ > ["] Spacing { p.AddImport(text) } Definition <- Identifier { p.AddRule(text) } LeftArrow Expression { p.AddExpression() } &(Identifier LeftArrow / !.) Expression <- Sequence (Slash Sequence { p.AddAlternate() } )* (Slash { p.AddNil(); p.AddAlternate() } )? / { p.AddNil() } Sequence <- Prefix (Prefix { p.AddSequence() } )* Prefix <- And Action { p.AddPredicate(text) } / Not Action { p.AddStateChange(text) } / And Suffix { p.AddPeekFor() } / Not Suffix { p.AddPeekNot() } / Suffix Suffix <- Primary (Question { p.AddQuery() } / Star { p.AddStar() } / Plus { p.AddPlus() } )? Primary <- Identifier !LeftArrow { p.AddName(text) } / Open Expression Close / Literal / Class / Dot { p.AddDot() } / Action { p.AddAction(text) } / Begin Expression End { p.AddPush() } # Lexical syntax #PrivateIdentifier <- < [a-z_] IdentCont* > Spacing Identifier <- < IdentStart IdentCont* > Spacing IdentStart <- [[a-z_]] IdentCont <- IdentStart / [0-9] Literal <- ['] (!['] Char)? (!['] Char { p.AddSequence() } )* ['] Spacing / ["] (!["] DoubleChar)? (!["] DoubleChar { p.AddSequence() } )* ["] Spacing Class <- ( '[[' ( '^' DoubleRanges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } / DoubleRanges )? ']]' / '[' ( '^' Ranges { p.AddPeekNot(); p.AddDot(); p.AddSequence() } / Ranges )? ']' ) Spacing Ranges <- !']' Range (!']' Range { p.AddAlternate() } )* DoubleRanges <- !']]' DoubleRange (!']]' DoubleRange { p.AddAlternate() } )* Range <- Char '-' Char { p.AddRange() } / Char DoubleRange <- Char '-' Char { p.AddDoubleRange() } / DoubleChar Char <- Escape / !'\\' <.> { p.AddCharacter(text) } DoubleChar <- Escape / <[a-zA-Z]> { p.AddDoubleCharacter(text) } / !'\\' <.> { p.AddCharacter(text) } Escape <- "\\a" { p.AddCharacter("\a") } # bell / "\\b" { p.AddCharacter("\b") } # bs / "\\e" { p.AddCharacter("\x1B") } # esc / "\\f" { p.AddCharacter("\f") } # ff / "\\n" { p.AddCharacter("\n") } # nl / "\\r" { p.AddCharacter("\r") } # cr / "\\t" { p.AddCharacter("\t") } # ht / "\\v" { p.AddCharacter("\v") } # vt / "\\'" { p.AddCharacter("'") } / '\\"' { p.AddCharacter("\"") } / '\\[' { p.AddCharacter("[") } / '\\]' { p.AddCharacter("]") } / '\\-' { p.AddCharacter("-") } / '\\' "0x"<[0-9a-fA-F]+> { p.AddHexaCharacter(text) } / '\\' <[0-3][0-7][0-7]> { p.AddOctalCharacter(text) } / '\\' <[0-7][0-7]?> { p.AddOctalCharacter(text) } / '\\\\' { p.AddCharacter("\\") } LeftArrow <- ('<-' / '\0x2190') Spacing Slash <- '/' Spacing And <- '&' Spacing Not <- '!' Spacing Question <- '?' Spacing Star <- '*' Spacing Plus <- '+' Spacing Open <- '(' Spacing Close <- ')' Spacing Dot <- '.' Spacing SpaceComment <- (Space / Comment) Spacing <- SpaceComment* MustSpacing <- SpaceComment+ Comment <- '#' (!EndOfLine .)* EndOfLine Space <- ' ' / '\t' / EndOfLine EndOfLine <- '\r\n' / '\n' / '\r' EndOfFile <- !. Action <- '{' < ActionBody* > '}' Spacing ActionBody <- [^{}] / '{' ActionBody* '}' Begin <- '<' Spacing End <- '>' Spacing peg-1.0.0/peg_test.go000066400000000000000000000037501276320170200144310ustar00rootroot00000000000000package main import ( "bytes" "io/ioutil" "testing" ) func TestCorrect(t *testing.T) { buffer := `package p type T Peg {} Grammar <- !. ` p := &Peg{Tree: New(false, false), Buffer: buffer} p.Init() err := p.Parse() if err != nil { t.Error(err) } } func TestNoSpacePackage(t *testing.T) { buffer := `packagenospace type T Peg {} Grammar <- !. ` p := &Peg{Tree: New(false, false), Buffer: buffer} p.Init() err := p.Parse() if err == nil { t.Error("packagenospace was parsed without error") } } func TestNoSpaceType(t *testing.T) { buffer := ` package p typenospace Peg {} Grammar <- !. ` p := &Peg{Tree: New(false, false), Buffer: buffer} p.Init() err := p.Parse() if err == nil { t.Error("typenospace was parsed without error") } } func TestSame(t *testing.T) { buffer, err := ioutil.ReadFile("peg.peg") if err != nil { t.Error(err) } p := &Peg{Tree: New(true, true), Buffer: string(buffer)} p.Init() if err := p.Parse(); err != nil { t.Error(err) } p.Execute() out := &bytes.Buffer{} p.Compile("peg.peg.go", out) bootstrap, err := ioutil.ReadFile("bootstrap.peg.go") if err != nil { t.Error(err) } if len(out.Bytes()) != len(bootstrap) { t.Error("code generated from peg.peg is not the same as bootstrap.peg.go") return } for i, v := range out.Bytes() { if v != bootstrap[i] { t.Error("code generated from peg.peg is not the same as bootstrap.peg.go") return } } } func BenchmarkParse(b *testing.B) { files := [...]string{ "peg.peg", "grammars/c/c.peg", "grammars/calculator/calculator.peg", "grammars/fexl/fexl.peg", "grammars/java/java_1_7.peg", } pegs := make([]*Peg, len(files)) for i, file := range files { input, err := ioutil.ReadFile(file) if err != nil { b.Error(err) } p := &Peg{Tree: New(true, true), Buffer: string(input)} p.Init() pegs[i] = p } b.ResetTimer() for i := 0; i < b.N; i++ { for _, peg := range pegs { peg.Reset() if err := peg.Parse(); err != nil { b.Error(err) } } } }