Commit d1f5e5f4 authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile/internal/syntax: always construct a correct syntax tree

- parser creates sensible nodes in case of syntax errors instead of nil
- a new BadExpr node is used in places where we can't do better
- fixed error message for incorrect type switch guard
- minor cleanups

Fixes #19663.

Change-Id: I028394c6db9cba7371f0e417ebf93f594659786a
Reviewed-on: https://go-review.googlesource.com/38653
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarMatthew Dempsky <mdempsky@google.com>
parent ecc6a816
...@@ -646,7 +646,6 @@ var knownFormats = map[string]string{ ...@@ -646,7 +646,6 @@ var knownFormats = map[string]string{
"cmd/compile/internal/ssa.regMask %d": "", "cmd/compile/internal/ssa.regMask %d": "",
"cmd/compile/internal/ssa.register %d": "", "cmd/compile/internal/ssa.register %d": "",
"cmd/compile/internal/syntax.Expr %#v": "", "cmd/compile/internal/syntax.Expr %#v": "",
"cmd/compile/internal/syntax.Expr %s": "",
"cmd/compile/internal/syntax.Node %T": "", "cmd/compile/internal/syntax.Node %T": "",
"cmd/compile/internal/syntax.Operator %d": "", "cmd/compile/internal/syntax.Operator %d": "",
"cmd/compile/internal/syntax.Operator %s": "", "cmd/compile/internal/syntax.Operator %s": "",
......
...@@ -416,7 +416,7 @@ func (p *noder) exprs(exprs []syntax.Expr) []*Node { ...@@ -416,7 +416,7 @@ func (p *noder) exprs(exprs []syntax.Expr) []*Node {
func (p *noder) expr(expr syntax.Expr) *Node { func (p *noder) expr(expr syntax.Expr) *Node {
p.lineno(expr) p.lineno(expr)
switch expr := expr.(type) { switch expr := expr.(type) {
case nil: case nil, *syntax.BadExpr:
return nil return nil
case *syntax.Name: case *syntax.Name:
return p.mkname(expr) return p.mkname(expr)
......
...@@ -125,6 +125,12 @@ type ( ...@@ -125,6 +125,12 @@ type (
aExpr() aExpr()
} }
// Placeholder for an expression that failed to parse
// correctly and where we can't provide a better node.
BadExpr struct {
expr
}
// Value // Value
Name struct { Name struct {
Value string Value string
......
...@@ -235,9 +235,12 @@ func (p *parser) trace(msg string) func() { ...@@ -235,9 +235,12 @@ func (p *parser) trace(msg string) func() {
// Parse methods are annotated with matching Go productions as appropriate. // Parse methods are annotated with matching Go productions as appropriate.
// The annotations are intended as guidelines only since a single Go grammar // The annotations are intended as guidelines only since a single Go grammar
// rule may be covered by multiple parse methods and vice versa. // rule may be covered by multiple parse methods and vice versa.
//
// Excluding methods returning slices, parse methods named xOrNil may return
// nil; all others are expected to return a valid non-nil node.
// SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } . // SourceFile = PackageClause ";" { ImportDecl ";" } { TopLevelDecl ";" } .
func (p *parser) file() *File { func (p *parser) fileOrNil() *File {
if trace { if trace {
defer p.trace("file")() defer p.trace("file")()
} }
...@@ -281,10 +284,12 @@ func (p *parser) file() *File { ...@@ -281,10 +284,12 @@ func (p *parser) file() *File {
case _Func: case _Func:
p.next() p.next()
f.DeclList = appendDecl(f.DeclList, p.funcDecl()) if d := p.funcDeclOrNil(); d != nil {
f.DeclList = append(f.DeclList, d)
}
default: default:
if p.tok == _Lbrace && len(f.DeclList) > 0 && emptyFuncDecl(f.DeclList[len(f.DeclList)-1]) { if p.tok == _Lbrace && len(f.DeclList) > 0 && isEmptyFuncDecl(f.DeclList[len(f.DeclList)-1]) {
// opening { of function declaration on next line // opening { of function declaration on next line
p.syntax_error("unexpected semicolon or newline before {") p.syntax_error("unexpected semicolon or newline before {")
} else { } else {
...@@ -310,7 +315,7 @@ func (p *parser) file() *File { ...@@ -310,7 +315,7 @@ func (p *parser) file() *File {
return f return f
} }
func emptyFuncDecl(dcl Decl) bool { func isEmptyFuncDecl(dcl Decl) bool {
f, ok := dcl.(*FuncDecl) f, ok := dcl.(*FuncDecl)
return ok && f.Body == nil return ok && f.Body == nil
} }
...@@ -323,25 +328,29 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl { ...@@ -323,25 +328,29 @@ func (p *parser) appendGroup(list []Decl, f func(*Group) Decl) []Decl {
if p.got(_Lparen) { if p.got(_Lparen) {
g := new(Group) g := new(Group)
for p.tok != _EOF && p.tok != _Rparen { for p.tok != _EOF && p.tok != _Rparen {
list = appendDecl(list, f(g)) list = append(list, f(g))
if !p.osemi(_Rparen) { if !p.osemi(_Rparen) {
break break
} }
} }
p.want(_Rparen) p.want(_Rparen)
return list } else {
list = append(list, f(nil))
} }
return appendDecl(list, f(nil)) if debug {
} for _, d := range list {
if d == nil {
func appendDecl(list []Decl, d Decl) []Decl { panic("nil list entry")
if d != nil { }
return append(list, d) }
} }
return list return list
} }
// ImportSpec = [ "." | PackageName ] ImportPath .
// ImportPath = string_lit .
func (p *parser) importDecl(group *Group) Decl { func (p *parser) importDecl(group *Group) Decl {
if trace { if trace {
defer p.trace("importDecl")() defer p.trace("importDecl")()
...@@ -354,10 +363,7 @@ func (p *parser) importDecl(group *Group) Decl { ...@@ -354,10 +363,7 @@ func (p *parser) importDecl(group *Group) Decl {
case _Name: case _Name:
d.LocalPkgName = p.name() d.LocalPkgName = p.name()
case _Dot: case _Dot:
n := new(Name) d.LocalPkgName = p.newName(".")
n.pos = p.pos()
n.Value = "."
d.LocalPkgName = n
p.next() p.next()
} }
d.Path = p.oliteral() d.Path = p.oliteral()
...@@ -382,7 +388,7 @@ func (p *parser) constDecl(group *Group) Decl { ...@@ -382,7 +388,7 @@ func (p *parser) constDecl(group *Group) Decl {
d.NameList = p.nameList(p.name()) d.NameList = p.nameList(p.name())
if p.tok != _EOF && p.tok != _Semi && p.tok != _Rparen { if p.tok != _EOF && p.tok != _Semi && p.tok != _Rparen {
d.Type = p.tryType() d.Type = p.typeOrNil()
if p.got(_Assign) { if p.got(_Assign) {
d.Values = p.exprList() d.Values = p.exprList()
} }
...@@ -403,11 +409,11 @@ func (p *parser) typeDecl(group *Group) Decl { ...@@ -403,11 +409,11 @@ func (p *parser) typeDecl(group *Group) Decl {
d.Name = p.name() d.Name = p.name()
d.Alias = p.got(_Assign) d.Alias = p.got(_Assign)
d.Type = p.tryType() d.Type = p.typeOrNil()
if d.Type == nil { if d.Type == nil {
d.Type = p.bad()
p.syntax_error("in type declaration") p.syntax_error("in type declaration")
p.advance(_Semi, _Rparen) p.advance(_Semi, _Rparen)
return nil
} }
d.Group = group d.Group = group
d.Pragma = p.pragma d.Pragma = p.pragma
...@@ -443,7 +449,7 @@ func (p *parser) varDecl(group *Group) Decl { ...@@ -443,7 +449,7 @@ func (p *parser) varDecl(group *Group) Decl {
// Function = Signature FunctionBody . // Function = Signature FunctionBody .
// MethodDecl = "func" Receiver MethodName ( Function | Signature ) . // MethodDecl = "func" Receiver MethodName ( Function | Signature ) .
// Receiver = Parameters . // Receiver = Parameters .
func (p *parser) funcDecl() *FuncDecl { func (p *parser) funcDeclOrNil() *FuncDecl {
if trace { if trace {
defer p.trace("funcDecl")() defer p.trace("funcDecl")()
} }
...@@ -633,18 +639,23 @@ func (p *parser) callStmt() *CallStmt { ...@@ -633,18 +639,23 @@ func (p *parser) callStmt() *CallStmt {
p.next() p.next()
x := p.pexpr(p.tok == _Lparen) // keep_parens so we can report error below x := p.pexpr(p.tok == _Lparen) // keep_parens so we can report error below
switch x := x.(type) { if t := unparen(x); t != x {
case *CallExpr:
s.Call = x
case *ParenExpr:
p.error(fmt.Sprintf("expression in %s must not be parenthesized", s.Tok)) p.error(fmt.Sprintf("expression in %s must not be parenthesized", s.Tok))
// already progressed, no need to advance // already progressed, no need to advance
default: x = t
}
cx, ok := x.(*CallExpr)
if !ok {
p.error(fmt.Sprintf("expression in %s must be function call", s.Tok)) p.error(fmt.Sprintf("expression in %s must be function call", s.Tok))
// already progressed, no need to advance // already progressed, no need to advance
cx := new(CallExpr)
cx.pos = x.Pos()
cx.Fun = p.bad()
} }
return s // TODO(gri) should we return nil in case of failure? s.Call = cx
return s
} }
// Operand = Literal | OperandName | MethodExpr | "(" Expression ")" . // Operand = Literal | OperandName | MethodExpr | "(" Expression ")" .
...@@ -721,9 +732,10 @@ func (p *parser) operand(keep_parens bool) Expr { ...@@ -721,9 +732,10 @@ func (p *parser) operand(keep_parens bool) Expr {
return p.type_() // othertype return p.type_() // othertype
default: default:
x := p.bad()
p.syntax_error("expecting expression") p.syntax_error("expecting expression")
p.advance() p.advance()
return nil return x
} }
// Syntactically, composite literals are operands. Because a complit // Syntactically, composite literals are operands. Because a complit
...@@ -936,16 +948,17 @@ func (p *parser) type_() Expr { ...@@ -936,16 +948,17 @@ func (p *parser) type_() Expr {
defer p.trace("type_")() defer p.trace("type_")()
} }
if typ := p.tryType(); typ != nil { typ := p.typeOrNil()
return typ if typ == nil {
typ = p.bad()
p.syntax_error("expecting type")
p.advance()
} }
p.syntax_error("expecting type") return typ
p.advance()
return nil
} }
func indirect(pos src.Pos, typ Expr) Expr { func newIndirect(pos src.Pos, typ Expr) Expr {
o := new(Operation) o := new(Operation)
o.pos = pos o.pos = pos
o.Op = Mul o.Op = Mul
...@@ -953,16 +966,16 @@ func indirect(pos src.Pos, typ Expr) Expr { ...@@ -953,16 +966,16 @@ func indirect(pos src.Pos, typ Expr) Expr {
return o return o
} }
// tryType is like type_ but it returns nil if there was no type // typeOrNil is like type_ but it returns nil if there was no type
// instead of reporting an error. // instead of reporting an error.
// //
// Type = TypeName | TypeLit | "(" Type ")" . // Type = TypeName | TypeLit | "(" Type ")" .
// TypeName = identifier | QualifiedIdent . // TypeName = identifier | QualifiedIdent .
// TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType | // TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
// SliceType | MapType | Channel_Type . // SliceType | MapType | Channel_Type .
func (p *parser) tryType() Expr { func (p *parser) typeOrNil() Expr {
if trace { if trace {
defer p.trace("tryType")() defer p.trace("typeOrNil")()
} }
pos := p.pos() pos := p.pos()
...@@ -970,7 +983,7 @@ func (p *parser) tryType() Expr { ...@@ -970,7 +983,7 @@ func (p *parser) tryType() Expr {
case _Star: case _Star:
// ptrtype // ptrtype
p.next() p.next()
return indirect(pos, p.type_()) return newIndirect(pos, p.type_())
case _Arrow: case _Arrow:
// recvchantype // recvchantype
...@@ -1072,13 +1085,14 @@ func (p *parser) chanElem() Expr { ...@@ -1072,13 +1085,14 @@ func (p *parser) chanElem() Expr {
defer p.trace("chanElem")() defer p.trace("chanElem")()
} }
if typ := p.tryType(); typ != nil { typ := p.typeOrNil()
return typ if typ == nil {
typ = p.bad()
p.syntax_error("missing channel element type")
// assume element type is simply absent - don't advance
} }
p.syntax_error("missing channel element type") return typ
// assume element type is simply absent - don't advance
return nil
} }
func (p *parser) dotname(name *Name) Expr { func (p *parser) dotname(name *Name) Expr {
...@@ -1170,10 +1184,10 @@ func (p *parser) funcResult() []*Field { ...@@ -1170,10 +1184,10 @@ func (p *parser) funcResult() []*Field {
} }
pos := p.pos() pos := p.pos()
if result := p.tryType(); result != nil { if typ := p.typeOrNil(); typ != nil {
f := new(Field) f := new(Field)
f.pos = pos f.pos = pos
f.Type = result f.Type = typ
return []*Field{f} return []*Field{f}
} }
...@@ -1234,7 +1248,7 @@ func (p *parser) fieldDecl(styp *StructType) { ...@@ -1234,7 +1248,7 @@ func (p *parser) fieldDecl(styp *StructType) {
// '(' '*' embed ')' oliteral // '(' '*' embed ')' oliteral
pos := p.pos() pos := p.pos()
p.next() p.next()
typ := indirect(pos, p.qualifiedName(nil)) typ := newIndirect(pos, p.qualifiedName(nil))
p.want(_Rparen) p.want(_Rparen)
tag := p.oliteral() tag := p.oliteral()
p.addField(styp, pos, nil, typ, tag) p.addField(styp, pos, nil, typ, tag)
...@@ -1253,7 +1267,7 @@ func (p *parser) fieldDecl(styp *StructType) { ...@@ -1253,7 +1267,7 @@ func (p *parser) fieldDecl(styp *StructType) {
p.next() p.next()
if p.got(_Lparen) { if p.got(_Lparen) {
// '*' '(' embed ')' oliteral // '*' '(' embed ')' oliteral
typ := indirect(pos, p.qualifiedName(nil)) typ := newIndirect(pos, p.qualifiedName(nil))
p.want(_Rparen) p.want(_Rparen)
tag := p.oliteral() tag := p.oliteral()
p.addField(styp, pos, nil, typ, tag) p.addField(styp, pos, nil, typ, tag)
...@@ -1261,7 +1275,7 @@ func (p *parser) fieldDecl(styp *StructType) { ...@@ -1261,7 +1275,7 @@ func (p *parser) fieldDecl(styp *StructType) {
} else { } else {
// '*' embed oliteral // '*' embed oliteral
typ := indirect(pos, p.qualifiedName(nil)) typ := newIndirect(pos, p.qualifiedName(nil))
tag := p.oliteral() tag := p.oliteral()
p.addField(styp, pos, nil, typ, tag) p.addField(styp, pos, nil, typ, tag)
} }
...@@ -1336,7 +1350,7 @@ func (p *parser) methodDecl() *Field { ...@@ -1336,7 +1350,7 @@ func (p *parser) methodDecl() *Field {
} }
// ParameterDecl = [ IdentifierList ] [ "..." ] Type . // ParameterDecl = [ IdentifierList ] [ "..." ] Type .
func (p *parser) paramDecl() *Field { func (p *parser) paramDeclOrNil() *Field {
if trace { if trace {
defer p.trace("paramDecl")() defer p.trace("paramDecl")()
} }
...@@ -1390,8 +1404,9 @@ func (p *parser) dotsType() *DotsType { ...@@ -1390,8 +1404,9 @@ func (p *parser) dotsType() *DotsType {
t.pos = p.pos() t.pos = p.pos()
p.want(_DotDotDot) p.want(_DotDotDot)
t.Elem = p.tryType() t.Elem = p.typeOrNil()
if t.Elem == nil { if t.Elem == nil {
t.Elem = p.bad()
p.syntax_error("final argument in variadic function missing type") p.syntax_error("final argument in variadic function missing type")
} }
...@@ -1405,11 +1420,12 @@ func (p *parser) paramList() (list []*Field) { ...@@ -1405,11 +1420,12 @@ func (p *parser) paramList() (list []*Field) {
defer p.trace("paramList")() defer p.trace("paramList")()
} }
pos := p.pos()
p.want(_Lparen) p.want(_Lparen)
var named int // number of parameters that have an explicit name and type var named int // number of parameters that have an explicit name and type
for p.tok != _EOF && p.tok != _Rparen { for p.tok != _EOF && p.tok != _Rparen {
if par := p.paramDecl(); par != nil { if par := p.paramDeclOrNil(); par != nil {
if debug && par.Name == nil && par.Type == nil { if debug && par.Name == nil && par.Type == nil {
panic("parameter without name or type") panic("parameter without name or type")
} }
...@@ -1434,20 +1450,29 @@ func (p *parser) paramList() (list []*Field) { ...@@ -1434,20 +1450,29 @@ func (p *parser) paramList() (list []*Field) {
} }
} else if named != len(list) { } else if named != len(list) {
// some named => all must be named // some named => all must be named
ok := true
var typ Expr var typ Expr
for i := len(list) - 1; i >= 0; i-- { for i := len(list) - 1; i >= 0; i-- {
if par := list[i]; par.Type != nil { if par := list[i]; par.Type != nil {
typ = par.Type typ = par.Type
if par.Name == nil { if par.Name == nil {
typ = nil // error ok = false
n := p.newName("_")
n.pos = typ.Pos() // correct position
par.Name = n
} }
} else { } else if typ != nil {
par.Type = typ par.Type = typ
} else {
// par.Type == nil && typ == nil => we only have a par.Name
ok = false
t := p.bad()
t.pos = par.Name.Pos() // correct position
par.Type = t
} }
if typ == nil { }
p.syntax_error("mixed named and unnamed function parameters") if !ok {
break p.syntax_error_at(pos, "mixed named and unnamed function parameters")
}
} }
} }
...@@ -1455,6 +1480,12 @@ func (p *parser) paramList() (list []*Field) { ...@@ -1455,6 +1480,12 @@ func (p *parser) paramList() (list []*Field) {
return return
} }
func (p *parser) bad() *BadExpr {
b := new(BadExpr)
b.pos = p.pos()
return b
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Statements // Statements
...@@ -1475,7 +1506,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { ...@@ -1475,7 +1506,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
if debug && lhs != nil { if debug && lhs != nil {
panic("invalid call of simpleStmt") panic("invalid call of simpleStmt")
} }
return p.rangeClause(nil, false) return p.newRangeClause(nil, false)
} }
if lhs == nil { if lhs == nil {
...@@ -1510,11 +1541,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { ...@@ -1510,11 +1541,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
default: default:
// expr // expr
s := new(ExprStmt) s := new(ExprStmt)
if lhs != nil { // be cautious (test/syntax/semi4.go) s.pos = lhs.Pos()
s.pos = lhs.Pos()
} else {
s.pos = p.pos()
}
s.X = lhs s.X = lhs
return s return s
} }
...@@ -1528,7 +1555,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { ...@@ -1528,7 +1555,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
if rangeOk && p.tok == _Range { if rangeOk && p.tok == _Range {
// expr_list '=' _Range expr // expr_list '=' _Range expr
return p.rangeClause(lhs, false) return p.newRangeClause(lhs, false)
} }
// expr_list '=' expr_list // expr_list '=' expr_list
...@@ -1539,7 +1566,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { ...@@ -1539,7 +1566,7 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
if rangeOk && p.tok == _Range { if rangeOk && p.tok == _Range {
// expr_list ':=' range expr // expr_list ':=' range expr
return p.rangeClause(lhs, true) return p.newRangeClause(lhs, true)
} }
// expr_list ':=' expr_list // expr_list ':=' expr_list
...@@ -1550,10 +1577,13 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { ...@@ -1550,10 +1577,13 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
case *Name: case *Name:
x.Lhs = lhs x.Lhs = lhs
case *ListExpr: case *ListExpr:
p.error(fmt.Sprintf("argument count mismatch: %d = %d", len(lhs.ElemList), 1)) p.error_at(lhs.Pos(), fmt.Sprintf("cannot assign 1 value to %d variables", len(lhs.ElemList)))
// make the best of what we have
if lhs, ok := lhs.ElemList[0].(*Name); ok {
x.Lhs = lhs
}
default: default:
// TODO(mdempsky): Have Expr types implement Stringer? p.error_at(lhs.Pos(), fmt.Sprintf("invalid variable name %s in type switch", String(lhs)))
p.error(fmt.Sprintf("invalid variable name %s in type switch", lhs))
} }
s := new(ExprStmt) s := new(ExprStmt)
s.pos = x.Pos() s.pos = x.Pos()
...@@ -1562,17 +1592,23 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt { ...@@ -1562,17 +1592,23 @@ func (p *parser) simpleStmt(lhs Expr, rangeOk bool) SimpleStmt {
} }
as := p.newAssignStmt(pos, Def, lhs, rhs) as := p.newAssignStmt(pos, Def, lhs, rhs)
as.pos = pos // TODO(gri) pass this into newAssignStmt
return as return as
default: default:
p.syntax_error("expecting := or = or comma") p.syntax_error("expecting := or = or comma")
p.advance(_Semi, _Rbrace) p.advance(_Semi, _Rbrace)
return nil // make the best of what we have
if x, ok := lhs.(*ListExpr); ok {
lhs = x.ElemList[0]
}
s := new(ExprStmt)
s.pos = lhs.Pos()
s.X = lhs
return s
} }
} }
func (p *parser) rangeClause(lhs Expr, def bool) *RangeClause { func (p *parser) newRangeClause(lhs Expr, def bool) *RangeClause {
r := new(RangeClause) r := new(RangeClause)
r.pos = p.pos() r.pos = p.pos()
p.next() // consume _Range p.next() // consume _Range
...@@ -2050,21 +2086,25 @@ func (p *parser) call(fun Expr) *CallExpr { ...@@ -2050,21 +2086,25 @@ func (p *parser) call(fun Expr) *CallExpr {
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Common productions // Common productions
func (p *parser) name() *Name { func (p *parser) newName(value string) *Name {
// no tracing to avoid overly verbose output
n := new(Name) n := new(Name)
n.pos = p.pos() n.pos = p.pos()
n.Value = value
return n
}
func (p *parser) name() *Name {
// no tracing to avoid overly verbose output
if p.tok == _Name { if p.tok == _Name {
n.Value = p.lit n := p.newName(p.lit)
p.next() p.next()
} else { return n
n.Value = "_"
p.syntax_error("expecting name")
p.advance()
} }
n := p.newName("_")
p.syntax_error("expecting name")
p.advance()
return n return n
} }
...@@ -2099,8 +2139,7 @@ func (p *parser) qualifiedName(name *Name) Expr { ...@@ -2099,8 +2139,7 @@ func (p *parser) qualifiedName(name *Name) Expr {
case p.tok == _Name: case p.tok == _Name:
name = p.name() name = p.name()
default: default:
name = new(Name) name = p.newName("_")
name.pos = p.pos()
p.syntax_error("expecting name") p.syntax_error("expecting name")
p.advance(_Dot, _Semi, _Rbrace) p.advance(_Dot, _Semi, _Rbrace)
} }
......
...@@ -345,6 +345,9 @@ func (p *printer) printRawNode(n Node) { ...@@ -345,6 +345,9 @@ func (p *printer) printRawNode(n Node) {
// we should not reach here but don't crash // we should not reach here but don't crash
// expressions and types // expressions and types
case *BadExpr:
p.print(_Name, "<bad expr>")
case *Name: case *Name:
p.print(_Name, n.Value) // _Name requires actual value following immediately p.print(_Name, n.Value) // _Name requires actual value following immediately
......
...@@ -65,7 +65,7 @@ func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHand ...@@ -65,7 +65,7 @@ func Parse(base *src.PosBase, src io.Reader, errh ErrorHandler, pragh PragmaHand
var p parser var p parser
p.init(base, src, errh, pragh) p.init(base, src, errh, pragh)
p.next() p.next()
return p.file(), p.first return p.fileOrNil(), p.first
} }
// ParseBytes behaves like Parse but it reads the source from the []byte slice provided. // ParseBytes behaves like Parse but it reads the source from the []byte slice provided.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment