1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 scanner scanner
.Scanner
18 pos token
.Position
// token position
19 tok token
.Token
// one token look-ahead
20 lit
[]byte // token literal
24 func (p
*parser
) next() {
25 p
.pos
, p
.tok
, p
.lit
= p
.scanner
.Scan()
26 if p
.tok
.IsKeyword() {
27 // TODO Should keyword mapping always happen outside scanner?
28 // Or should there be a flag to scanner to enable keyword mapping?
34 func (p
*parser
) errorExpected(pos token
.Position
, msg
string) {
35 msg
= "expected " + msg
36 if pos
.Offset
== p
.pos
.Offset
{
37 // the error happened at the current position;
38 // make the error message more specific
39 msg
+= ", found '" + p
.tok
.String() + "'"
40 if p
.tok
.IsLiteral() {
41 msg
+= " " + string(p
.lit
)
48 func (p
*parser
) expect(tok token
.Token
) token
.Position
{
51 p
.errorExpected(pos
, "'"+tok
.String()+"'")
53 p
.next() // make progress in any case
58 func (p
*parser
) parseIdentifier() *Name
{
62 return &Name
{pos
, name
}
66 func (p
*parser
) parseToken() *Token
{
69 if p
.tok
== token
.STRING
{
70 value
, _
= strconv
.Unquote(string(p
.lit
))
71 // Unquote may fail with an error, but only if the scanner found
72 // an illegal string in the first place. In this case the error
73 // has already been reported.
76 p
.expect(token
.STRING
)
78 return &Token
{pos
, value
}
82 func (p
*parser
) parseTerm() (x Expression
) {
87 x
= p
.parseIdentifier()
92 if p
.tok
== token
.ELLIPSIS
{
94 x
= &Range
{tok
, p
.parseToken()}
99 x
= &Group
{pos
, p
.parseExpression()}
100 p
.expect(token
.RPAREN
)
104 x
= &Option
{pos
, p
.parseExpression()}
105 p
.expect(token
.RBRACK
)
109 x
= &Repetition
{pos
, p
.parseExpression()}
110 p
.expect(token
.RBRACE
)
117 func (p
*parser
) parseSequence() Expression
{
120 for x
:= p
.parseTerm(); x
!= nil; x
= p
.parseTerm() {
121 list
= append(list
, x
)
124 // no need for a sequence if list.Len() < 2
136 func (p
*parser
) parseExpression() Expression
{
140 if x
:= p
.parseSequence(); x
!= nil {
141 list
= append(list
, x
)
143 if p
.tok
!= token
.OR
{
149 // no need for an Alternative node if list.Len() < 2
161 func (p
*parser
) parseProduction() *Production
{
162 name
:= p
.parseIdentifier()
163 p
.expect(token
.ASSIGN
)
164 expr
:= p
.parseExpression()
165 p
.expect(token
.PERIOD
)
166 return &Production
{name
, expr
}
170 func (p
*parser
) parse(filename
string, src
[]byte) Grammar
{
172 p
.ErrorVector
.Reset()
173 p
.scanner
.Init(filename
, src
, p
, 0)
174 p
.next() // initializes pos, tok, lit
176 grammar
:= make(Grammar
)
177 for p
.tok
!= token
.EOF
{
178 prod
:= p
.parseProduction()
179 name
:= prod
.Name
.String
180 if _
, found
:= grammar
[name
]; !found
{
183 p
.Error(prod
.Pos(), name
+" declared already")
191 // Parse parses a set of EBNF productions from source src.
192 // It returns a set of productions. Errors are reported
193 // for incorrect syntax and if a production is declared
196 func Parse(filename
string, src
[]byte) (Grammar
, os
.Error
) {
198 grammar
:= p
.parse(filename
, src
)
199 return grammar
, p
.GetError(scanner
.Sorted
)