Commit 9214016b authored by Robert Griesemer's avatar Robert Griesemer

go/ast: provide complete node text range info

- add End() method to all nodes; the text range of a node n is [n.Pos(), n.End())
- various small bug fixes in the process
- fixed several comments

R=r, rsc
CC=golang-dev
https://golang.org/cl/3769042
parent 71793d4b
...@@ -241,9 +241,11 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{} ...@@ -241,9 +241,11 @@ func (f *File) walk(x interface{}, context string, visit func(*File, interface{}
f.walk(&n.Index, "expr", visit) f.walk(&n.Index, "expr", visit)
case *ast.SliceExpr: case *ast.SliceExpr:
f.walk(&n.X, "expr", visit) f.walk(&n.X, "expr", visit)
f.walk(&n.Index, "expr", visit) if n.Low != nil {
if n.End != nil { f.walk(&n.Low, "expr", visit)
f.walk(&n.End, "expr", visit) }
if n.High != nil {
f.walk(&n.High, "expr", visit)
} }
case *ast.TypeAssertExpr: case *ast.TypeAssertExpr:
f.walk(&n.X, "expr", visit) f.walk(&n.X, "expr", visit)
......
...@@ -597,19 +597,19 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr { ...@@ -597,19 +597,19 @@ func (a *exprCompiler) compile(x ast.Expr, callCtx bool) *expr {
case *ast.SliceExpr: case *ast.SliceExpr:
var lo, hi *expr var lo, hi *expr
arr := a.compile(x.X, false) arr := a.compile(x.X, false)
if x.Index == nil { if x.Low == nil {
// beginning was omitted, so we need to provide it // beginning was omitted, so we need to provide it
ei := &exprInfo{a.compiler, x.Pos()} ei := &exprInfo{a.compiler, x.Pos()}
lo = ei.compileIntLit("0") lo = ei.compileIntLit("0")
} else { } else {
lo = a.compile(x.Index, false) lo = a.compile(x.Low, false)
} }
if x.End == nil { if x.High == nil {
// End was omitted, so we need to compute len(x.X) // End was omitted, so we need to compute len(x.X)
ei := &exprInfo{a.compiler, x.Pos()} ei := &exprInfo{a.compiler, x.Pos()}
hi = ei.compileBuiltinCallExpr(a.block, lenType, []*expr{arr}) hi = ei.compileBuiltinCallExpr(a.block, lenType, []*expr{arr})
} else { } else {
hi = a.compile(x.End, false) hi = a.compile(x.High, false)
} }
if arr == nil || lo == nil || hi == nil { if arr == nil || lo == nil || hi == nil {
return nil return nil
......
This diff is collapsed.
...@@ -90,9 +90,14 @@ func Walk(v Visitor, node Node) { ...@@ -90,9 +90,14 @@ func Walk(v Visitor, node Node) {
} }
// Expressions // Expressions
case *BadExpr, *Ident, *Ellipsis, *BasicLit: case *BadExpr, *Ident, *BasicLit:
// nothing to do // nothing to do
case *Ellipsis:
if n.Elt != nil {
Walk(v, n.Elt)
}
case *FuncLit: case *FuncLit:
Walk(v, n.Type) Walk(v, n.Type)
Walk(v, n.Body) Walk(v, n.Body)
...@@ -116,11 +121,11 @@ func Walk(v Visitor, node Node) { ...@@ -116,11 +121,11 @@ func Walk(v Visitor, node Node) {
case *SliceExpr: case *SliceExpr:
Walk(v, n.X) Walk(v, n.X)
if n.Index != nil { if n.Low != nil {
Walk(v, n.Index) Walk(v, n.Low)
} }
if n.End != nil { if n.High != nil {
Walk(v, n.End) Walk(v, n.High)
} }
case *TypeAssertExpr: case *TypeAssertExpr:
......
...@@ -251,7 +251,7 @@ func (p *parser) expect(tok token.Token) token.Pos { ...@@ -251,7 +251,7 @@ func (p *parser) expect(tok token.Token) token.Pos {
if p.tok != tok { if p.tok != tok {
p.errorExpected(pos, "'"+tok.String()+"'") p.errorExpected(pos, "'"+tok.String()+"'")
} }
p.next() // make progress in any case p.next() // make progress
return pos return pos
} }
...@@ -323,9 +323,10 @@ func (p *parser) parseType() ast.Expr { ...@@ -323,9 +323,10 @@ func (p *parser) parseType() ast.Expr {
typ := p.tryType() typ := p.tryType()
if typ == nil { if typ == nil {
p.errorExpected(p.pos, "type") pos := p.pos
p.errorExpected(pos, "type")
p.next() // make progress p.next() // make progress
return &ast.BadExpr{p.pos} return &ast.BadExpr{pos, p.pos}
} }
return typ return typ
...@@ -417,10 +418,10 @@ func (p *parser) parseFieldDecl() *ast.Field { ...@@ -417,10 +418,10 @@ func (p *parser) parseFieldDecl() *ast.Field {
} else { } else {
// ["*"] TypeName (AnonymousField) // ["*"] TypeName (AnonymousField)
typ = list[0] // we always have at least one element typ = list[0] // we always have at least one element
if len(list) > 1 || !isTypeName(deref(typ)) { if n := len(list); n > 1 || !isTypeName(deref(typ)) {
pos := typ.Pos() pos := typ.Pos()
p.errorExpected(pos, "anonymous field") p.errorExpected(pos, "anonymous field")
typ = &ast.BadExpr{pos} typ = &ast.BadExpr{pos, list[n-1].End()}
} }
} }
...@@ -469,7 +470,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr { ...@@ -469,7 +470,7 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
typ := p.tryType() // don't use parseType so we can provide better error message typ := p.tryType() // don't use parseType so we can provide better error message
if typ == nil { if typ == nil {
p.error(pos, "'...' parameter is missing type") p.error(pos, "'...' parameter is missing type")
typ = &ast.BadExpr{pos} typ = &ast.BadExpr{pos, p.pos}
} }
if p.tok != token.RPAREN { if p.tok != token.RPAREN {
p.error(pos, "can use '...' with last parameter type only") p.error(pos, "can use '...' with last parameter type only")
...@@ -483,9 +484,10 @@ func (p *parser) tryVarType(isParam bool) ast.Expr { ...@@ -483,9 +484,10 @@ func (p *parser) tryVarType(isParam bool) ast.Expr {
func (p *parser) parseVarType(isParam bool) ast.Expr { func (p *parser) parseVarType(isParam bool) ast.Expr {
typ := p.tryVarType(isParam) typ := p.tryVarType(isParam)
if typ == nil { if typ == nil {
p.errorExpected(p.pos, "type") pos := p.pos
p.errorExpected(pos, "type")
p.next() // make progress p.next() // make progress
typ = &ast.BadExpr{p.pos} typ = &ast.BadExpr{pos, p.pos}
} }
return typ return typ
} }
...@@ -826,9 +828,10 @@ func (p *parser) parseOperand() ast.Expr { ...@@ -826,9 +828,10 @@ func (p *parser) parseOperand() ast.Expr {
} }
} }
p.errorExpected(p.pos, "operand") pos := p.pos
p.errorExpected(pos, "operand")
p.next() // make progress p.next() // make progress
return &ast.BadExpr{p.pos} return &ast.BadExpr{pos, p.pos}
} }
...@@ -984,7 +987,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { ...@@ -984,7 +987,7 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr {
if t.Type == nil { if t.Type == nil {
// the form X.(type) is only allowed in type switch expressions // the form X.(type) is only allowed in type switch expressions
p.errorExpected(x.Pos(), "expression") p.errorExpected(x.Pos(), "expression")
x = &ast.BadExpr{x.Pos()} x = &ast.BadExpr{x.Pos(), x.End()}
} }
case *ast.CallExpr: case *ast.CallExpr:
case *ast.StarExpr: case *ast.StarExpr:
...@@ -992,13 +995,13 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr { ...@@ -992,13 +995,13 @@ func (p *parser) checkExpr(x ast.Expr) ast.Expr {
if t.Op == token.RANGE { if t.Op == token.RANGE {
// the range operator is only allowed at the top of a for statement // the range operator is only allowed at the top of a for statement
p.errorExpected(x.Pos(), "expression") p.errorExpected(x.Pos(), "expression")
x = &ast.BadExpr{x.Pos()} x = &ast.BadExpr{x.Pos(), x.End()}
} }
case *ast.BinaryExpr: case *ast.BinaryExpr:
default: default:
// all other nodes are not proper expressions // all other nodes are not proper expressions
p.errorExpected(x.Pos(), "expression") p.errorExpected(x.Pos(), "expression")
x = &ast.BadExpr{x.Pos()} x = &ast.BadExpr{x.Pos(), x.End()}
} }
return x return x
} }
...@@ -1066,12 +1069,12 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr { ...@@ -1066,12 +1069,12 @@ func (p *parser) checkExprOrType(x ast.Expr) ast.Expr {
if t.Op == token.RANGE { if t.Op == token.RANGE {
// the range operator is only allowed at the top of a for statement // the range operator is only allowed at the top of a for statement
p.errorExpected(x.Pos(), "expression") p.errorExpected(x.Pos(), "expression")
x = &ast.BadExpr{x.Pos()} x = &ast.BadExpr{x.Pos(), x.End()}
} }
case *ast.ArrayType: case *ast.ArrayType:
if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis { if len, isEllipsis := t.Len.(*ast.Ellipsis); isEllipsis {
p.error(len.Pos(), "expected array length, found '...'") p.error(len.Pos(), "expected array length, found '...'")
x = &ast.BadExpr{x.Pos()} x = &ast.BadExpr{x.Pos(), x.End()}
} }
} }
...@@ -1190,14 +1193,15 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt { ...@@ -1190,14 +1193,15 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
switch p.tok { switch p.tok {
case token.COLON: case token.COLON:
// labeled statement // labeled statement
colon := p.pos
p.next() p.next()
if labelOk && len(x) == 1 { if labelOk && len(x) == 1 {
if label, isIdent := x[0].(*ast.Ident); isIdent { if label, isIdent := x[0].(*ast.Ident); isIdent {
return &ast.LabeledStmt{label, p.parseStmt()} return &ast.LabeledStmt{label, colon, p.parseStmt()}
} }
} }
p.error(x[0].Pos(), "illegal label declaration") p.error(x[0].Pos(), "illegal label declaration")
return &ast.BadStmt{x[0].Pos()} return &ast.BadStmt{x[0].Pos(), colon + 1}
case case
token.DEFINE, token.ASSIGN, token.ADD_ASSIGN, token.DEFINE, token.ASSIGN, token.ADD_ASSIGN,
...@@ -1218,7 +1222,7 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt { ...@@ -1218,7 +1222,7 @@ func (p *parser) parseSimpleStmt(labelOk bool) ast.Stmt {
if p.tok == token.INC || p.tok == token.DEC { if p.tok == token.INC || p.tok == token.DEC {
// increment or decrement // increment or decrement
s := &ast.IncDecStmt{x[0], p.tok} s := &ast.IncDecStmt{x[0], p.pos, p.tok}
p.next() // consume "++" or "--" p.next() // consume "++" or "--"
return s return s
} }
...@@ -1247,7 +1251,7 @@ func (p *parser) parseGoStmt() ast.Stmt { ...@@ -1247,7 +1251,7 @@ func (p *parser) parseGoStmt() ast.Stmt {
call := p.parseCallExpr() call := p.parseCallExpr()
p.expectSemi() p.expectSemi()
if call == nil { if call == nil {
return &ast.BadStmt{pos} return &ast.BadStmt{pos, pos + 2} // len("go")
} }
return &ast.GoStmt{pos, call} return &ast.GoStmt{pos, call}
...@@ -1263,7 +1267,7 @@ func (p *parser) parseDeferStmt() ast.Stmt { ...@@ -1263,7 +1267,7 @@ func (p *parser) parseDeferStmt() ast.Stmt {
call := p.parseCallExpr() call := p.parseCallExpr()
p.expectSemi() p.expectSemi()
if call == nil { if call == nil {
return &ast.BadStmt{pos} return &ast.BadStmt{pos, pos + 5} // len("defer")
} }
return &ast.DeferStmt{pos, call} return &ast.DeferStmt{pos, call}
...@@ -1311,7 +1315,7 @@ func (p *parser) makeExpr(s ast.Stmt) ast.Expr { ...@@ -1311,7 +1315,7 @@ func (p *parser) makeExpr(s ast.Stmt) ast.Expr {
return p.checkExpr(es.X) return p.checkExpr(es.X)
} }
p.error(s.Pos(), "expected condition, found simple statement") p.error(s.Pos(), "expected condition, found simple statement")
return &ast.BadExpr{s.Pos()} return &ast.BadExpr{s.Pos(), s.End()}
} }
...@@ -1547,7 +1551,7 @@ func (p *parser) parseForStmt() ast.Stmt { ...@@ -1547,7 +1551,7 @@ func (p *parser) parseForStmt() ast.Stmt {
// possibly a for statement with a range clause; check assignment operator // possibly a for statement with a range clause; check assignment operator
if as.Tok != token.ASSIGN && as.Tok != token.DEFINE { if as.Tok != token.ASSIGN && as.Tok != token.DEFINE {
p.errorExpected(as.TokPos, "'=' or ':='") p.errorExpected(as.TokPos, "'=' or ':='")
return &ast.BadStmt{pos} return &ast.BadStmt{pos, body.End()}
} }
// check lhs // check lhs
var key, value ast.Expr var key, value ast.Expr
...@@ -1558,19 +1562,19 @@ func (p *parser) parseForStmt() ast.Stmt { ...@@ -1558,19 +1562,19 @@ func (p *parser) parseForStmt() ast.Stmt {
key = as.Lhs[0] key = as.Lhs[0]
default: default:
p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions") p.errorExpected(as.Lhs[0].Pos(), "1 or 2 expressions")
return &ast.BadStmt{pos} return &ast.BadStmt{pos, body.End()}
} }
// check rhs // check rhs
if len(as.Rhs) != 1 { if len(as.Rhs) != 1 {
p.errorExpected(as.Rhs[0].Pos(), "1 expressions") p.errorExpected(as.Rhs[0].Pos(), "1 expressions")
return &ast.BadStmt{pos} return &ast.BadStmt{pos, body.End()}
} }
if rhs, isUnary := as.Rhs[0].(*ast.UnaryExpr); isUnary && rhs.Op == token.RANGE { if rhs, isUnary := as.Rhs[0].(*ast.UnaryExpr); isUnary && rhs.Op == token.RANGE {
// rhs is range expression; check lhs // rhs is range expression; check lhs
return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body} return &ast.RangeStmt{pos, key, value, as.TokPos, as.Tok, rhs.X, body}
} else { } else {
p.errorExpected(s2.Pos(), "range clause") p.errorExpected(s2.Pos(), "range clause")
return &ast.BadStmt{pos} return &ast.BadStmt{pos, body.End()}
} }
} else { } else {
// regular for statement // regular for statement
...@@ -1628,9 +1632,10 @@ func (p *parser) parseStmt() (s ast.Stmt) { ...@@ -1628,9 +1632,10 @@ func (p *parser) parseStmt() (s ast.Stmt) {
s = &ast.EmptyStmt{p.pos} s = &ast.EmptyStmt{p.pos}
default: default:
// no statement found // no statement found
p.errorExpected(p.pos, "statement") pos := p.pos
p.errorExpected(pos, "statement")
p.next() // make progress p.next() // make progress
s = &ast.BadStmt{p.pos} s = &ast.BadStmt{pos, p.pos}
} }
return return
...@@ -1754,7 +1759,8 @@ func (p *parser) parseReceiver() *ast.FieldList { ...@@ -1754,7 +1759,8 @@ func (p *parser) parseReceiver() *ast.FieldList {
// must have exactly one receiver // must have exactly one receiver
if par.NumFields() != 1 { if par.NumFields() != 1 {
p.errorExpected(pos, "exactly one receiver") p.errorExpected(pos, "exactly one receiver")
par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{token.NoPos}}} // TODO determine a better range for BadExpr below
par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{pos, pos}}}
return par return par
} }
...@@ -1763,7 +1769,7 @@ func (p *parser) parseReceiver() *ast.FieldList { ...@@ -1763,7 +1769,7 @@ func (p *parser) parseReceiver() *ast.FieldList {
base := deref(recv.Type) base := deref(recv.Type)
if _, isIdent := base.(*ast.Ident); !isIdent { if _, isIdent := base.(*ast.Ident); !isIdent {
p.errorExpected(base.Pos(), "(unqualified) identifier") p.errorExpected(base.Pos(), "(unqualified) identifier")
par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos()}}} par.List = []*ast.Field{&ast.Field{Type: &ast.BadExpr{recv.Pos(), recv.End()}}}
} }
return par return par
...@@ -1818,8 +1824,8 @@ func (p *parser) parseDecl() ast.Decl { ...@@ -1818,8 +1824,8 @@ func (p *parser) parseDecl() ast.Decl {
default: default:
pos := p.pos pos := p.pos
p.errorExpected(pos, "declaration") p.errorExpected(pos, "declaration")
decl := &ast.BadDecl{pos} p.next() // make progress
p.next() // make progress in any case decl := &ast.BadDecl{pos, p.pos}
return decl return decl
} }
......
...@@ -714,7 +714,7 @@ func splitSelector(expr ast.Expr) (body, suffix ast.Expr) { ...@@ -714,7 +714,7 @@ func splitSelector(expr ast.Expr) (body, suffix ast.Expr) {
case *ast.SliceExpr: case *ast.SliceExpr:
body, suffix = splitSelector(x.X) body, suffix = splitSelector(x.X)
if body != nil { if body != nil {
suffix = &ast.SliceExpr{suffix, x.Index, x.End} suffix = &ast.SliceExpr{suffix, x.Low, x.High}
return return
} }
case *ast.TypeAssertExpr: case *ast.TypeAssertExpr:
...@@ -845,17 +845,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi ...@@ -845,17 +845,17 @@ func (p *printer) expr1(expr ast.Expr, prec1, depth int, ctxt exprContext, multi
// TODO(gri): should treat[] like parentheses and undo one level of depth // TODO(gri): should treat[] like parentheses and undo one level of depth
p.expr1(x.X, token.HighestPrec, 1, 0, multiLine) p.expr1(x.X, token.HighestPrec, 1, 0, multiLine)
p.print(token.LBRACK) p.print(token.LBRACK)
if x.Index != nil { if x.Low != nil {
p.expr0(x.Index, depth+1, multiLine) p.expr0(x.Low, depth+1, multiLine)
} }
// blanks around ":" if both sides exist and either side is a binary expression // blanks around ":" if both sides exist and either side is a binary expression
if depth <= 1 && x.Index != nil && x.End != nil && (isBinary(x.Index) || isBinary(x.End)) { if depth <= 1 && x.Low != nil && x.High != nil && (isBinary(x.Low) || isBinary(x.High)) {
p.print(blank, token.COLON, blank) p.print(blank, token.COLON, blank)
} else { } else {
p.print(token.COLON) p.print(token.COLON)
} }
if x.End != nil { if x.High != nil {
p.expr0(x.End, depth+1, multiLine) p.expr0(x.High, depth+1, multiLine)
} }
p.print(token.RBRACK) p.print(token.RBRACK)
...@@ -1071,7 +1071,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1071,7 +1071,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
// between (see writeWhitespace) // between (see writeWhitespace)
p.print(unindent) p.print(unindent)
p.expr(s.Label, multiLine) p.expr(s.Label, multiLine)
p.print(token.COLON, indent) p.print(s.Colon, token.COLON, indent)
if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty { if e, isEmpty := s.Stmt.(*ast.EmptyStmt); isEmpty {
if !nextIsRBrace { if !nextIsRBrace {
p.print(newline, e.Pos(), token.SEMICOLON) p.print(newline, e.Pos(), token.SEMICOLON)
...@@ -1089,7 +1089,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) { ...@@ -1089,7 +1089,7 @@ func (p *printer) stmt(stmt ast.Stmt, nextIsRBrace bool, multiLine *bool) {
case *ast.IncDecStmt: case *ast.IncDecStmt:
const depth = 1 const depth = 1
p.expr0(s.X, depth+1, multiLine) p.expr0(s.X, depth+1, multiLine)
p.print(s.Tok) p.print(s.TokPos, s.Tok)
case *ast.AssignStmt: case *ast.AssignStmt:
var depth = 1 var depth = 1
......
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