File: peg.go

package info (click to toggle)
golang-github-badgerodon-peg 0.0~git20130729.9e5f7f4-3
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 92 kB
  • sloc: makefile: 15
file content (104 lines) | stat: -rw-r--r-- 2,594 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
package peg

import(
	//"fmt"
)

type (
	Parser struct {
		working string
		rules map[string]*NonTerminal
	}
	Result struct {
		*Parser
		Valid bool
		Offset int
		Length int
		Expression Exp
		Children []*Result
	}
)

// Result
func (this *Result) toTree() *ExpressionTree {
	children := make([]*ExpressionTree, 0)
	if this.Valid {
		for _, r := range this.Children {
			children = append(children, r.toTree())
		}
		switch exp := this.Expression.(type) {
		case *Terminal:
			return &ExpressionTree{"",children,exp.Character}
		case *NonTerminal:
			return &ExpressionTree{exp.Name,children,-1}
		}
	}
	return &ExpressionTree{"",children,-1}
}


// Create a new PEG Parser
func NewParser() *Parser {
	return &Parser{"",make(map[string]*NonTerminal)}
}
func (this *Parser) pass(offset, length int, exp Exp, children []*Result) *Result {
	if children == nil {
		children = make([]*Result, 0)
	}
	return &Result{this,true,offset,length,exp,children}
}
func (this *Parser) fail(offset, length int, exp Exp, children []*Result) *Result {
	if children == nil {
		children = make([]*Result, 0)
	}
	return &Result{this,false,offset,length,exp,children}
}
func (this *Parser) Terminal(ch int) *Terminal {
	return &Terminal{this,ch}
}
func (this *Parser) NonTerminal(name string) *NonTerminal {
	e := &NonTerminal{this,name,nil}
	this.rules[name] = e
	return e
}
func (this *Parser) Sequence(exps ... Exp) *Sequence {
	return &Sequence{this,exps}
}
func (this *Parser) OrderedChoice(exps ... Exp) *OrderedChoice {
	return &OrderedChoice{this,exps}
}
func (this *Parser) ZeroOrMore(exp Exp) *ZeroOrMore {
	return &ZeroOrMore{this,exp}
}
func (this *Parser) OneOrMore(exp Exp) *OneOrMore {
	return &OneOrMore{this,exp}
}
func (this *Parser) Optional(exp Exp) *Optional {
	return &Optional{this,exp}
}
func (this *Parser) AndPredicate(exp Exp) *AndPredicate {
	return &AndPredicate{this,exp}
}
func (this *Parser) NotPredicate(exp Exp) *NotPredicate {
	return &NotPredicate{this,exp}
}

// Extensions for easier construction
func (this *Parser) Range(start, end int) *OrderedChoice {
	exps := make([]Exp, (end - start)+1)
	for i := start; i <= end; i++ {
		exps[i-start] = &Terminal{this,i}
	}
	return &OrderedChoice{this,exps}
}

func (this *Parser) Parse(text string) *ExpressionTree {
	this.working = text
	if start, ok := this.rules["Start"]; ok {
		_, r := start.Match(0)
		t := r.toTree()
		t.collapse()
		return t
	} 
	panic("No starting rule defined. Create a non terminal named \"Start\"")
}