diff options
author | Robert Griesemer <gri@golang.org> | 2009-02-03 17:44:01 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2009-02-03 17:44:01 -0800 |
commit | 6cf98e2fac82bf23405d65e9f12ff8ef4d9eccbd (patch) | |
tree | 7623ee690fee937783d444c5c81aed4e4733d552 /usr/gri/pretty/parser.go | |
parent | 0c7951cc9ca7792155bd78bd8bbb5220281cb6f1 (diff) | |
download | golang-6cf98e2fac82bf23405d65e9f12ff8ef4d9eccbd.tar.gz |
- converted expr representation of ast into a new representation
using interfaces properly => much cleaner code
- converted tracing code to use 'defer' statement
- next steps: convert rest of ast as well
R=r
OCL=24277
CL=24277
Diffstat (limited to 'usr/gri/pretty/parser.go')
-rw-r--r-- | usr/gri/pretty/parser.go | 714 |
1 files changed, 391 insertions, 323 deletions
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index 8f08bcb30..ae904a651 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -64,26 +64,22 @@ func assert(pred bool) { func (P *Parser) PrintIndent() { for i := P.indent; i > 0; i-- { - print(". "); + fmt.Printf(". "); } } func (P *Parser) Trace(msg string) { - if P.verbose { - P.PrintIndent(); - print(msg, " {\n"); - } - P.indent++; // always check proper identation + P.PrintIndent(); + fmt.Printf("%s {\n", msg); + P.indent++; } func (P *Parser) Ecart() { - P.indent--; // always check proper identation - if P.verbose { - P.PrintIndent(); - print("}\n"); - } + P.indent--; + P.PrintIndent(); + fmt.Printf("}\n"); } @@ -105,7 +101,7 @@ func (P *Parser) Next0() { case "{": s = "LBRACE"; case "}": s = "RBRACE"; } - print("[", P.pos, "] ", s, "\n"); + fmt.Printf("[%d] %s\n", P.pos, s); } } @@ -171,13 +167,12 @@ func (P *Parser) CloseScope() { } -func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int, typ *AST.Type) { +func (P *Parser) DeclareInScope(scope *AST.Scope, x AST.Expr, kind int, typ *AST.Type) { if P.scope_lev < 0 { panic("cannot declare objects in other packages"); } - if x.Tok != Scanner.ILLEGAL { // ignore bad exprs - assert(x.Tok == Scanner.IDENT); - obj := x.Obj; + if ident, ok := x.(*AST.Ident); ok { // ignore bad exprs + obj := ident.Obj; obj.Kind = kind; obj.Typ = typ; obj.Pnolev = P.scope_lev; @@ -196,47 +191,54 @@ func (P *Parser) DeclareInScope(scope *AST.Scope, x *AST.Expr, kind int, typ *AS // Declare a comma-separated list of idents or a single ident. -func (P *Parser) Declare(p *AST.Expr, kind int, typ *AST.Type) { - for p.Tok == Scanner.COMMA { - P.DeclareInScope(P.top_scope, p.X, kind, typ); - p = p.Y; +func (P *Parser) Declare(x AST.Expr, kind int, typ *AST.Type) { + for { + p, ok := x.(*AST.BinaryExpr); + if ok && p.Tok == Scanner.COMMA { + P.DeclareInScope(P.top_scope, p.X, kind, typ); + x = p.Y; + } else { + break; + } } - P.DeclareInScope(P.top_scope, p, kind, typ); + P.DeclareInScope(P.top_scope, x, kind, typ); } // ---------------------------------------------------------------------------- // AST support -func exprType(x *AST.Expr) *AST.Type { - var t *AST.Type; - if x.Tok == Scanner.TYPE { - t = x.Typ; - } else if x.Tok == Scanner.IDENT { +func exprType(x AST.Expr) *AST.Type { + var typ *AST.Type; + if t, is_type := x.(*AST.TypeLit); is_type { + typ = t.Typ + } else if t, is_ident := x.(*AST.Ident); is_ident { // assume a type name - t = AST.NewType(x.Pos, AST.TYPENAME); - t.Expr = x; - } else if x.Tok == Scanner.PERIOD && x.Y != nil && exprType(x.X) != nil { + typ = AST.NewType(t.Pos(), AST.TYPENAME); + typ.Expr = x; + } else if t, is_selector := x.(*AST.Selector); is_selector && exprType(t.Sel) != nil { // possibly a qualified (type) identifier - t = AST.NewType(x.Pos, AST.TYPENAME); - t.Expr = x; + typ = AST.NewType(t.Pos(), AST.TYPENAME); + typ.Expr = x; } - return t; + return typ; } -func (P *Parser) NoType(x *AST.Expr) *AST.Expr { - if x != nil && x.Tok == Scanner.TYPE { - P.Error(x.Pos, "expected expression, found type"); - val := AST.NewObject(x.Pos, AST.NONE, "0"); - x = AST.NewLit(Scanner.INT, val); +func (P *Parser) NoType(x AST.Expr) AST.Expr { + if x != nil { + lit, ok := x.(*AST.TypeLit); + if ok { + P.Error(lit.Typ.Pos, "expected expression, found type"); + x = &AST.BasicLit{lit.Typ.Pos, Scanner.STRING, ""}; + } } return x; } -func (P *Parser) NewExpr(pos, tok int, x, y *AST.Expr) *AST.Expr { - return AST.NewExpr(pos, tok, P.NoType(x), P.NoType(y)); +func (P *Parser) NewBinary(pos, tok int, x, y AST.Expr) *AST.BinaryExpr { + return &AST.BinaryExpr{pos, tok, P.NoType(x), P.NoType(y)}; } @@ -244,16 +246,18 @@ func (P *Parser) NewExpr(pos, tok int, x, y *AST.Expr) *AST.Expr { // Common productions func (P *Parser) TryType() *AST.Type; -func (P *Parser) ParseExpression(prec int) *AST.Expr; +func (P *Parser) ParseExpression(prec int) AST.Expr; func (P *Parser) ParseStatement() *AST.Stat; func (P *Parser) ParseDeclaration() *AST.Decl; // If scope != nil, lookup identifier in scope. Otherwise create one. -func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Expr { - P.Trace("Ident"); +func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Ident { + if P.verbose { + P.Trace("Ident"); + defer P.Ecart(); + } - x := AST.BadExpr; if P.tok == Scanner.IDENT { var obj *AST.Object; if scope != nil { @@ -264,41 +268,41 @@ func (P *Parser) ParseIdent(scope *AST.Scope) *AST.Expr { } else { assert(obj.Kind != AST.NONE); } - x = AST.NewLit(Scanner.IDENT, obj); - x.Pos = P.pos; // override obj.pos (incorrect if object was looked up!) + x := &AST.Ident{P.pos, obj}; if P.verbose { P.PrintIndent(); - print("Ident = \"", P.val, "\"\n"); + fmt.Printf("ident = \"%s\"\n", P.val); } P.Next(); - } else { - P.Expect(Scanner.IDENT); // use Expect() error handling + return x; } - - P.Ecart(); - return x; + + P.Expect(Scanner.IDENT); // use Expect() error handling + return &AST.Ident{P.pos, nil}; } -func (P *Parser) ParseIdentList() *AST.Expr { - P.Trace("IdentList"); +func (P *Parser) ParseIdentList() AST.Expr { + if P.verbose { + P.Trace("IdentList"); + defer P.Ecart(); + } - var last *AST.Expr; - x := P.ParseIdent(nil); + var last *AST.BinaryExpr; + var x AST.Expr = P.ParseIdent(nil); for P.tok == Scanner.COMMA { pos := P.pos; P.Next(); y := P.ParseIdent(nil); if last == nil { - x = P.NewExpr(pos, Scanner.COMMA, x, y); - last = x; + last = P.NewBinary(pos, Scanner.COMMA, x, y); + x = last; } else { - last.Y = P.NewExpr(pos, Scanner.COMMA, last.Y, y); + last.Y = P.NewBinary(pos, Scanner.COMMA, last.Y, y); last = last.Y; } } - P.Ecart(); return x; } @@ -307,7 +311,10 @@ func (P *Parser) ParseIdentList() *AST.Expr { // Types func (P *Parser) ParseType() *AST.Type { - P.Trace("Type"); + if P.verbose { + P.Trace("Type"); + defer P.Ecart(); + } t := P.TryType(); if t == nil { @@ -315,56 +322,61 @@ func (P *Parser) ParseType() *AST.Type { t = AST.BadType; } - P.Ecart(); return t; } func (P *Parser) ParseVarType() *AST.Type { - P.Trace("VarType"); - - typ := P.ParseType(); + if P.verbose { + P.Trace("VarType"); + defer P.Ecart(); + } - P.Ecart(); - return typ; + return P.ParseType(); } -func (P *Parser) ParseQualifiedIdent() *AST.Expr { - P.Trace("QualifiedIdent"); +func (P *Parser) ParseQualifiedIdent() AST.Expr { + if P.verbose { + P.Trace("QualifiedIdent"); + defer P.Ecart(); + } - x := P.ParseIdent(P.top_scope); + var x AST.Expr = P.ParseIdent(P.top_scope); for P.tok == Scanner.PERIOD { pos := P.pos; P.Next(); y := P.ParseIdent(nil); - x = P.NewExpr(pos, Scanner.PERIOD, x, y); + x = &AST.Selector{pos, x, y}; } - P.Ecart(); return x; } func (P *Parser) ParseTypeName() *AST.Type { - P.Trace("TypeName"); + if P.verbose { + P.Trace("TypeName"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.TYPENAME); t.Expr = P.ParseQualifiedIdent(); - t.Elt = t.Expr.Typ; - P.Ecart(); return t; } func (P *Parser) ParseArrayType() *AST.Type { - P.Trace("ArrayType"); + if P.verbose { + P.Trace("ArrayType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.ARRAY); P.Expect(Scanner.LBRACK); if P.tok == Scanner.ELLIPSIS { - t.Expr = P.NewExpr(P.pos, Scanner.ELLIPSIS, nil, nil); + t.Expr = P.NewBinary(P.pos, Scanner.ELLIPSIS, nil, nil); P.Next(); } else if P.tok != Scanner.RBRACK { t.Expr = P.ParseExpression(1); @@ -372,13 +384,15 @@ func (P *Parser) ParseArrayType() *AST.Type { P.Expect(Scanner.RBRACK); t.Elt = P.ParseType(); - P.Ecart(); return t; } func (P *Parser) ParseChannelType() *AST.Type { - P.Trace("ChannelType"); + if P.verbose { + P.Trace("ChannelType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.CHANNEL); t.Mode = AST.FULL; @@ -395,7 +409,6 @@ func (P *Parser) ParseChannelType() *AST.Type { } t.Elt = P.ParseVarType(); - P.Ecart(); return t; } @@ -404,7 +417,7 @@ func (P *Parser) ParseVar(expect_ident bool) *AST.Type { t := AST.BadType; if expect_ident { x := P.ParseIdent(nil); - t = AST.NewType(x.Pos, AST.TYPENAME); + t = AST.NewType(x.Pos(), AST.TYPENAME); t.Expr = x; } else if P.tok == Scanner.ELLIPSIS { t = AST.NewType(P.pos, AST.ELLIPSIS); @@ -417,7 +430,10 @@ func (P *Parser) ParseVar(expect_ident bool) *AST.Type { func (P *Parser) ParseVarList(list *array.Array, ellipsis_ok bool) { - P.Trace("VarList"); + if P.verbose { + P.Trace("VarList"); + defer P.Ecart(); + } // assume a list of types // (a list of identifiers looks like a list of type names) @@ -450,31 +466,34 @@ func (P *Parser) ParseVarList(list *array.Array, ellipsis_ok bool) { // convert the type entries into identifiers for i, n := i0, list.Len(); i < n; i++ { t := list.At(i).(*AST.Type); - if t.Form == AST.TYPENAME && t.Expr.Tok == Scanner.IDENT { - list.Set(i, t.Expr); - } else { - list.Set(i, AST.BadExpr); - P.Error(t.Pos, "identifier expected"); + if t.Form == AST.TYPENAME { + if ident, ok := t.Expr.(*AST.Ident); ok { + list.Set(i, ident); + continue; + } } + list.Set(i, &AST.BadExpr{0}); + P.Error(t.Pos, "identifier expected"); } // add type - list.Push(AST.NewTypeExpr(typ)); + list.Push(&AST.TypeLit{typ}); } else { // all list entries are types // convert all type entries into type expressions for i, n := i0, list.Len(); i < n; i++ { t := list.At(i).(*AST.Type); - list.Set(i, AST.NewTypeExpr(t)); + list.Set(i, &AST.TypeLit{t}); } } - - P.Ecart(); } func (P *Parser) ParseParameterList(ellipsis_ok bool) *array.Array { - P.Trace("ParameterList"); + if P.verbose { + P.Trace("ParameterList"); + defer P.Ecart(); + } list := array.New(0); P.ParseVarList(list, ellipsis_ok); @@ -483,13 +502,15 @@ func (P *Parser) ParseParameterList(ellipsis_ok bool) *array.Array { P.ParseVarList(list, ellipsis_ok); } - P.Ecart(); return list; } func (P *Parser) ParseParameters(ellipsis_ok bool) *AST.Type { - P.Trace("Parameters"); + if P.verbose { + P.Trace("Parameters"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.STRUCT); P.Expect(Scanner.LPAREN); @@ -499,13 +520,15 @@ func (P *Parser) ParseParameters(ellipsis_ok bool) *AST.Type { t.End = P.pos; P.Expect(Scanner.RPAREN); - P.Ecart(); return t; } func (P *Parser) ParseResultList() { - P.Trace("ResultList"); + if P.verbose { + P.Trace("ResultList"); + defer P.Ecart(); + } P.ParseType(); for P.tok == Scanner.COMMA { @@ -515,13 +538,14 @@ func (P *Parser) ParseResultList() { if P.tok != Scanner.RPAREN { P.ParseType(); } - - P.Ecart(); } func (P *Parser) ParseResult(ftyp *AST.Type) *AST.Type { - P.Trace("Result"); + if P.verbose { + P.Trace("Result"); + defer P.Ecart(); + } var t *AST.Type; if P.tok == Scanner.LPAREN { @@ -531,12 +555,11 @@ func (P *Parser) ParseResult(ftyp *AST.Type) *AST.Type { if typ != nil { t = AST.NewType(P.pos, AST.STRUCT); t.List = array.New(0); - t.List.Push(AST.NewTypeExpr(typ)); + t.List.Push(&AST.TypeLit{typ}); t.End = P.pos; } } - P.Ecart(); return t; } @@ -548,7 +571,10 @@ func (P *Parser) ParseResult(ftyp *AST.Type) *AST.Type { // (params) (results) func (P *Parser) ParseSignature() *AST.Type { - P.Trace("Signature"); + if P.verbose { + P.Trace("Signature"); + defer P.Ecart(); + } P.OpenScope(); P.scope_lev++; @@ -562,35 +588,38 @@ func (P *Parser) ParseSignature() *AST.Type { P.scope_lev--; P.CloseScope(); - P.Ecart(); return t; } func (P *Parser) ParseFunctionType() *AST.Type { - P.Trace("FunctionType"); + if P.verbose { + P.Trace("FunctionType"); + defer P.Ecart(); + } P.Expect(Scanner.FUNC); - t := P.ParseSignature(); - - P.Ecart(); - return t; + return P.ParseSignature(); } func (P *Parser) ParseMethodSpec(list *array.Array) { - P.Trace("MethodDecl"); + if P.verbose { + P.Trace("MethodDecl"); + defer P.Ecart(); + } list.Push(P.ParseIdentList()); t := P.ParseSignature(); - list.Push(AST.NewTypeExpr(t)); - - P.Ecart(); + list.Push(&AST.TypeLit{t}); } func (P *Parser) ParseInterfaceType() *AST.Type { - P.Trace("InterfaceType"); + if P.verbose { + P.Trace("InterfaceType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.INTERFACE); P.Expect(Scanner.INTERFACE); @@ -613,13 +642,15 @@ func (P *Parser) ParseInterfaceType() *AST.Type { P.Expect(Scanner.RBRACE); } - P.Ecart(); return t; } func (P *Parser) ParseMapType() *AST.Type { - P.Trace("MapType"); + if P.verbose { + P.Trace("MapType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.MAP); P.Expect(Scanner.MAP); @@ -628,15 +659,17 @@ func (P *Parser) ParseMapType() *AST.Type { P.Expect(Scanner.RBRACK); t.Elt = P.ParseVarType(); - P.Ecart(); return t; } -func (P *Parser) ParseOperand() *AST.Expr +func (P *Parser) ParseOperand() AST.Expr func (P *Parser) ParseStructType() *AST.Type { - P.Trace("StructType"); + if P.verbose { + P.Trace("StructType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.STRUCT); P.Expect(Scanner.STRUCT); @@ -664,32 +697,35 @@ func (P *Parser) ParseStructType() *AST.Type { // enter fields into struct scope for i, n := 0, t.List.Len(); i < n; i++ { - x := t.List.At(i).(*AST.Expr); - if x.Tok == Scanner.IDENT { + if x, ok := t.List.At(i).(*AST.Ident); ok { P.DeclareInScope(t.Scope, x, AST.FIELD, nil); } } } - P.Ecart(); return t; } func (P *Parser) ParsePointerType() *AST.Type { - P.Trace("PointerType"); + if P.verbose { + P.Trace("PointerType"); + defer P.Ecart(); + } t := AST.NewType(P.pos, AST.POINTER); P.Expect(Scanner.MUL); t.Elt = P.ParseType(); - P.Ecart(); return t; } func (P *Parser) TryType() *AST.Type { - P.Trace("Type (try)"); + if P.verbose { + P.Trace("Type (try)"); + defer P.Ecart(); + } t := AST.BadType; switch P.tok { @@ -703,8 +739,6 @@ func (P *Parser) TryType() *AST.Type { case Scanner.MUL: t = P.ParsePointerType(); default: t = nil; // no type found } - - P.Ecart(); return t; } @@ -713,7 +747,10 @@ func (P *Parser) TryType() *AST.Type { // Blocks func (P *Parser) ParseStatementList(list *array.Array) { - P.Trace("StatementList"); + if P.verbose { + P.Trace("StatementList"); + defer P.Ecart(); + } for P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { s := P.ParseStatement(); @@ -734,13 +771,14 @@ func (P *Parser) ParseStatementList(list *array.Array) { if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { P.Error(P.pos, "expected end of statement list (semicolon missing?)"); } - - P.Ecart(); } func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { - P.Trace("Block"); + if P.verbose { + P.Trace("Block"); + defer P.Ecart(); + } b := AST.NewBlock(P.pos, tok); P.Expect(tok); @@ -753,8 +791,7 @@ func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { } if ftyp.List != nil { for i, n := 0, ftyp.List.Len(); i < n; i++ { - x := ftyp.List.At(i).(*AST.Expr); - if x.Tok == Scanner.IDENT { + if x, ok := ftyp.List.At(i).(*AST.Ident); ok { P.DeclareInScope(P.top_scope, x, AST.VAR, nil); } } @@ -770,7 +807,6 @@ func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { P.opt_semi = true; } - P.Ecart(); return b; } @@ -778,8 +814,11 @@ func (P *Parser) ParseBlock(ftyp *AST.Type, tok int) *AST.Block { // ---------------------------------------------------------------------------- // Expressions -func (P *Parser) ParseExpressionList() *AST.Expr { - P.Trace("ExpressionList"); +func (P *Parser) ParseExpressionList() AST.Expr { + if P.verbose { + P.Trace("ExpressionList"); + defer P.Ecart(); + } x := P.ParseExpression(1); for first := true; P.tok == Scanner.COMMA; { @@ -787,111 +826,112 @@ func (P *Parser) ParseExpressionList() *AST.Expr { P.Next(); y := P.ParseExpression(1); if first { - x = P.NewExpr(pos, Scanner.COMMA, x, y); + x = P.NewBinary(pos, Scanner.COMMA, x, y); first = false; } else { - x.Y = P.NewExpr(pos, Scanner.COMMA, x.Y, y); + x.(*AST.BinaryExpr).Y = P.NewBinary(pos, Scanner.COMMA, x.(*AST.BinaryExpr).Y, y); } } - P.Ecart(); return x; } -func (P *Parser) ParseFunctionLit() *AST.Expr { - P.Trace("FunctionLit"); +func (P *Parser) ParseFunctionLit() AST.Expr { + if P.verbose { + P.Trace("FunctionLit"); + defer P.Ecart(); + } - f := AST.NewObject(P.pos, AST.FUNC, ""); + pos := P.pos; P.Expect(Scanner.FUNC); - f.Typ = P.ParseSignature(); + typ := P.ParseSignature(); P.expr_lev++; P.scope_lev++; - f.Body = P.ParseBlock(f.Typ, Scanner.LBRACE); + body := P.ParseBlock(typ, Scanner.LBRACE); P.scope_lev--; P.expr_lev--; - P.Ecart(); - return AST.NewLit(Scanner.FUNC, f); + return &AST.FunctionLit{pos, typ, body}; } -func (P *Parser) ParseOperand() *AST.Expr { - P.Trace("Operand"); +func (P *Parser) ParseOperand() AST.Expr { + if P.verbose { + P.Trace("Operand"); + defer P.Ecart(); + } - x := AST.BadExpr; switch P.tok { case Scanner.IDENT: - x = P.ParseIdent(P.top_scope); + return P.ParseIdent(P.top_scope); case Scanner.LPAREN: // TODO we could have a function type here as in: new(()) // (currently not working) P.Next(); P.expr_lev++; - x = P.ParseExpression(1); + x := P.ParseExpression(1); P.expr_lev--; P.Expect(Scanner.RPAREN); + return x; case Scanner.INT, Scanner.FLOAT, Scanner.STRING: - val := AST.NewObject(P.pos, AST.NONE, P.val); - x = AST.NewLit(P.tok, val); + x := &AST.BasicLit{P.pos, P.tok, P.val}; P.Next(); if x.Tok == Scanner.STRING { // TODO should remember the list instead of // concatenate the strings here for ; P.tok == Scanner.STRING; P.Next() { - x.Obj.Ident += P.val; + x.Val += P.val; } } + return x; case Scanner.FUNC: - x = P.ParseFunctionLit(); + return P.ParseFunctionLit(); default: t := P.TryType(); if t != nil { - x = AST.NewTypeExpr(t); + return &AST.TypeLit{t}; } else { P.Error(P.pos, "operand expected"); P.Next(); // make progress } } - P.Ecart(); - return x; + return &AST.BadExpr{P.pos}; } -func (P *Parser) ParseSelectorOrTypeGuard(x *AST.Expr) *AST.Expr { - P.Trace("SelectorOrTypeGuard"); +func (P *Parser) ParseSelectorOrTypeGuard(x AST.Expr) AST.Expr { + if P.verbose { + P.Trace("SelectorOrTypeGuard"); + defer P.Ecart(); + } - x = P.NewExpr(P.pos, Scanner.PERIOD, x, nil); + pos := P.pos; P.Expect(Scanner.PERIOD); if P.tok == Scanner.IDENT { - // TODO should always guarantee x.Typ != nil - var scope *AST.Scope; - if x.X.Typ != nil { - scope = x.X.Typ.Scope; - } - x.Y = P.ParseIdent(scope); - x.Typ = x.Y.Obj.Typ; + x = &AST.Selector{pos, x, P.ParseIdent(nil)}; } else { P.Expect(Scanner.LPAREN); - x.Y = AST.NewTypeExpr(P.ParseType()); - x.Typ = x.Y.Typ; + x = &AST.TypeGuard{pos, x, P.ParseType()}; P.Expect(Scanner.RPAREN); } - P.Ecart(); return x; } -func (P *Parser) ParseIndex(x *AST.Expr) *AST.Expr { - P.Trace("IndexOrSlice"); +func (P *Parser) ParseIndex(x AST.Expr) AST.Expr { + if P.verbose { + P.Trace("IndexOrSlice"); + defer P.Ecart(); + } pos := P.pos; P.Expect(Scanner.LBRACK); @@ -900,51 +940,51 @@ func (P *Parser) ParseIndex(x *AST.Expr) *AST.Expr { P.expr_lev--; P.Expect(Scanner.RBRACK); - P.Ecart(); - return P.NewExpr(pos, Scanner.LBRACK, x, i); + return &AST.Index{pos, x, i}; } -func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr +func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr -func (P *Parser) ParseCall(x0 *AST.Expr) *AST.Expr { - P.Trace("Call"); +func (P *Parser) ParseCall(f AST.Expr) AST.Expr { + if P.verbose { + P.Trace("Call"); + defer P.Ecart(); + } - x := P.NewExpr(P.pos, Scanner.LPAREN, x0, nil); + call := &AST.Call{P.pos, f, nil}; P.Expect(Scanner.LPAREN); if P.tok != Scanner.RPAREN { P.expr_lev++; var t *AST.Type; - if x0.Tok == Scanner.IDENT && (x0.Obj.Ident == "new" || x0.Obj.Ident == "make") { + if x0, ok := f.(*AST.Ident); ok && (x0.Obj.Ident == "new" || x0.Obj.Ident == "make") { // heuristic: assume it's a new(T) or make(T, ...) call, try to parse a type t = P.TryType(); } if t != nil { // we found a type - x.Y = AST.NewTypeExpr(t); + args := &AST.TypeLit{t}; if P.tok == Scanner.COMMA { pos := P.pos; P.Next(); y := P.ParseExpressionList(); // create list manually because NewExpr checks for type expressions - z := AST.NewExpr(pos, Scanner.COMMA, nil, y); - z.X = x.Y; - x.Y = z; + args := &AST.BinaryExpr{pos, Scanner.COMMA, args, y}; } + call.Args = args; } else { // normal argument list - x.Y = P.ParseExpressionList(); + call.Args = P.ParseExpressionList(); } P.expr_lev--; } P.Expect(Scanner.RPAREN); - P.Ecart(); - return x; + return call; } -func (P *Parser) ParseCompositeElements() *AST.Expr { +func (P *Parser) ParseCompositeElements() AST.Expr { x := P.ParseExpression(0); if P.tok == Scanner.COMMA { pos := P.pos; @@ -952,29 +992,29 @@ func (P *Parser) ParseCompositeElements() *AST.Expr { // first element determines mode singles := true; - if x.Tok == Scanner.COLON { + if t, is_binary := x.(*AST.BinaryExpr); is_binary && t.Tok == Scanner.COLON { singles = false; } - var last *AST.Expr; + var last *AST.BinaryExpr; for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { y := P.ParseExpression(0); if singles { - if y.Tok == Scanner.COLON { - P.Error(y.X.Pos, "single value expected; found pair"); + if t, is_binary := y.(*AST.BinaryExpr); is_binary && t.Tok == Scanner.COLON { + P.Error(t.X.Pos(), "single value expected; found pair"); } } else { - if y.Tok != Scanner.COLON { - P.Error(y.Pos, "key:value pair expected; found single value"); + if t, is_binary := y.(*AST.BinaryExpr); !is_binary || t.Tok != Scanner.COLON { + P.Error(y.Pos(), "key:value pair expected; found single value"); } } if last == nil { - x = P.NewExpr(pos, Scanner.COMMA, x, y); - last = x; + last = P.NewBinary(pos, Scanner.COMMA, x, y); + x = last; } else { - last.Y = P.NewExpr(pos, Scanner.COMMA, last.Y, y); + last.Y = P.NewBinary(pos, Scanner.COMMA, last.Y, y); last = last.Y; } @@ -991,25 +1031,29 @@ func (P *Parser) ParseCompositeElements() *AST.Expr { } -func (P *Parser) ParseCompositeLit(t *AST.Type) *AST.Expr { - P.Trace("CompositeLit"); +func (P *Parser) ParseCompositeLit(t *AST.Type) AST.Expr { + if P.verbose { + P.Trace("CompositeLit"); + defer P.Ecart(); + } - x := P.NewExpr(P.pos, Scanner.LBRACE, nil, nil); - x.Obj = AST.NewObject(t.Pos, AST.TYPE, ""); - x.Obj.Typ = t; + pos := P.pos; P.Expect(Scanner.LBRACE); + var elts AST.Expr; if P.tok != Scanner.RBRACE { - x.Y = P.ParseCompositeElements(); + elts = P.ParseCompositeElements(); } P.Expect(Scanner.RBRACE); - P.Ecart(); - return x; + return &AST.CompositeLit{pos, t, elts}; } -func (P *Parser) ParsePrimaryExpr() *AST.Expr { - P.Trace("PrimaryExpr"); +func (P *Parser) ParsePrimaryExpr() AST.Expr { + if P.verbose { + P.Trace("PrimaryExpr"); + defer P.Ecart(); + } x := P.ParseOperand(); for { @@ -1028,47 +1072,48 @@ func (P *Parser) ParsePrimaryExpr() *AST.Expr { if t != nil { x = P.ParseCompositeLit(t); } else { - goto exit; + return x; } - default: goto exit; + default: + return x; } } -exit: - P.Ecart(); - return x; + unreachable(); + return nil; } -func (P *Parser) ParseUnaryExpr() *AST.Expr { - P.Trace("UnaryExpr"); +func (P *Parser) ParseUnaryExpr() AST.Expr { + if P.verbose { + P.Trace("UnaryExpr"); + defer P.Ecart(); + } - x := AST.BadExpr; switch P.tok { case Scanner.ADD, Scanner.SUB, Scanner.MUL, Scanner.NOT, Scanner.XOR, Scanner.ARROW, Scanner.AND: pos, tok := P.pos, P.tok; P.Next(); y := P.ParseUnaryExpr(); - if tok == Scanner.MUL && y.Tok == Scanner.TYPE { + if lit, ok := y.(*AST.TypeLit); ok && tok == Scanner.MUL { // pointer type t := AST.NewType(pos, AST.POINTER); - t.Elt = y.Obj.Typ; - x = AST.NewTypeExpr(t); + t.Elt = lit.Typ; + return &AST.TypeLit{t}; } else { - x = P.NewExpr(pos, tok, nil, y); + return &AST.UnaryExpr{pos, tok, y}; } - - default: - x = P.ParsePrimaryExpr(); } - P.Ecart(); - return x; + return P.ParsePrimaryExpr(); } -func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr { - P.Trace("BinaryExpr"); +func (P *Parser) ParseBinaryExpr(prec1 int) AST.Expr { + if P.verbose { + P.Trace("BinaryExpr"); + defer P.Ecart(); + } x := P.ParseUnaryExpr(); for prec := Scanner.Precedence(P.tok); prec >= prec1; prec-- { @@ -1076,28 +1121,29 @@ func (P *Parser) ParseBinaryExpr(prec1 int) *AST.Expr { pos, tok := P.pos, P.tok; P.Next(); y := P.ParseBinaryExpr(prec + 1); - x = P.NewExpr(pos, tok, x, y); + x = P.NewBinary(pos, tok, x, y); } } - P.Ecart(); return x; } -func (P *Parser) ParseExpression(prec int) *AST.Expr { - P.Trace("Expression"); - indent := P.indent; +func (P *Parser) ParseExpression(prec int) AST.Expr { + if P.verbose { + P.Trace("Expression"); + defer P.Ecart(); + } + indent := P.indent; if prec < 0 { panic("precedence must be >= 0"); } x := P.NoType(P.ParseBinaryExpr(prec)); - if indent != P.indent { panic("imbalanced tracing code (Expression)"); } - P.Ecart(); + return x; } @@ -1106,35 +1152,25 @@ func (P *Parser) ParseExpression(prec int) *AST.Expr { // Statements func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { - P.Trace("SimpleStat"); + if P.verbose { + P.Trace("SimpleStat"); + defer P.Ecart(); + } s := AST.BadStat; x := P.ParseExpressionList(); - is_range := false; - if range_ok && P.tok == Scanner.COLON { - pos := P.pos; - P.Next(); - y := P.ParseExpression(1); - if x.Len() == 1 { - x = P.NewExpr(pos, Scanner.COLON, x, y); - is_range = true; - } else { - P.Error(pos, "expected initialization, found ':'"); - } - } - switch P.tok { case Scanner.COLON: // label declaration s = AST.NewStat(P.pos, Scanner.COLON); s.Expr = x; - if x.Len() != 1 { - P.Error(x.Pos, "illegal label declaration"); + if AST.ExprLen(x) != 1 { + P.Error(x.Pos(), "illegal label declaration"); } P.Next(); // consume ":" P.opt_semi = true; - + case Scanner.DEFINE, Scanner.ASSIGN, Scanner.ADD_ASSIGN, Scanner.SUB_ASSIGN, Scanner.MUL_ASSIGN, Scanner.QUO_ASSIGN, @@ -1143,34 +1179,31 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { // declaration/assignment pos, tok := P.pos, P.tok; P.Next(); - y := AST.BadExpr; + var y AST.Expr = &AST.BadExpr{pos}; if P.tok == Scanner.RANGE { range_pos := P.pos; P.Next(); y = P.ParseExpression(1); - y = P.NewExpr(range_pos, Scanner.RANGE, nil, y); + y = P.NewBinary(range_pos, Scanner.RANGE, nil, y); if tok != Scanner.DEFINE && tok != Scanner.ASSIGN { P.Error(pos, "expected '=' or ':=', found '" + Scanner.TokenString(tok) + "'"); } } else { y = P.ParseExpressionList(); - if is_range { - P.Error(y.Pos, "expected 'range', found expression"); - } - if xl, yl := x.Len(), y.Len(); xl > 1 && yl > 1 && xl != yl { - P.Error(x.Pos, "arity of lhs doesn't match rhs"); + if xl, yl := AST.ExprLen(x), AST.ExprLen(y); xl > 1 && yl > 1 && xl != yl { + P.Error(x.Pos(), "arity of lhs doesn't match rhs"); } } - s = AST.NewStat(x.Pos, Scanner.EXPRSTAT); - s.Expr = AST.NewExpr(pos, tok, x, y); - + s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT); + s.Expr = P.NewBinary(pos, tok, x, y); + case Scanner.RANGE: pos := P.pos; P.Next(); y := P.ParseExpression(1); - y = P.NewExpr(pos, Scanner.RANGE, nil, y); - s = AST.NewStat(x.Pos, Scanner.EXPRSTAT); - s.Expr = AST.NewExpr(pos, Scanner.DEFINE, x, y); + y = &AST.UnaryExpr{pos, Scanner.RANGE, y}; + s = AST.NewStat(x.Pos(), Scanner.EXPRSTAT); + s.Expr = P.NewBinary(pos, Scanner.DEFINE, x, y); default: var pos, tok int; @@ -1178,34 +1211,39 @@ func (P *Parser) ParseSimpleStat(range_ok bool) *AST.Stat { pos, tok = P.pos, P.tok; P.Next(); } else { - pos, tok = x.Pos, Scanner.EXPRSTAT; + pos, tok = x.Pos(), Scanner.EXPRSTAT; } s = AST.NewStat(pos, tok); s.Expr = x; - if x.Len() != 1 { - P.Error(x.Pos, "only one expression allowed"); + if AST.ExprLen(x) != 1 { + P.Error(pos, "only one expression allowed"); + panic(); // fix position } } - P.Ecart(); return s; } func (P *Parser) ParseInvocationStat(keyword int) *AST.Stat { - P.Trace("InvocationStat"); + if P.verbose { + P.Trace("InvocationStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, keyword); P.Expect(keyword); s.Expr = P.ParseExpression(1); - P.Ecart(); return s; } func (P *Parser) ParseReturnStat() *AST.Stat { - P.Trace("ReturnStat"); + if P.verbose { + P.Trace("ReturnStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, Scanner.RETURN); P.Expect(Scanner.RETURN); @@ -1213,13 +1251,15 @@ func (P *Parser) ParseReturnStat() *AST.Stat { s.Expr = P.ParseExpressionList(); } - P.Ecart(); return s; } func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { - P.Trace("ControlFlowStat"); + if P.verbose { + P.Trace("ControlFlowStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, tok); P.Expect(tok); @@ -1227,13 +1267,15 @@ func (P *Parser) ParseControlFlowStat(tok int) *AST.Stat { s.Expr = P.ParseIdent(P.top_scope); } - P.Ecart(); return s; } func (P *Parser) ParseControlClause(keyword int) *AST.Stat { - P.Trace("ControlClause"); + if P.verbose { + P.Trace("ControlClause"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, keyword); P.Expect(keyword); @@ -1263,13 +1305,15 @@ func (P *Parser) ParseControlClause(keyword int) *AST.Stat { P.expr_lev = prev_lev; } - P.Ecart(); return s; } func (P *Parser) ParseIfStat() *AST.Stat { - P.Trace("IfStat"); + if P.verbose { + P.Trace("IfStat"); + defer P.Ecart(); + } P.OpenScope(); s := P.ParseControlClause(Scanner.IF); @@ -1297,26 +1341,30 @@ func (P *Parser) ParseIfStat() *AST.Stat { } P.CloseScope(); - P.Ecart(); return s; } func (P *Parser) ParseForStat() *AST.Stat { - P.Trace("ForStat"); + if P.verbose { + P.Trace("ForStat"); + defer P.Ecart(); + } P.OpenScope(); s := P.ParseControlClause(Scanner.FOR); s.Body = P.ParseBlock(nil, Scanner.LBRACE); P.CloseScope(); - P.Ecart(); return s; } func (P *Parser) ParseSwitchCase() *AST.Stat { - P.Trace("SwitchCase"); + if P.verbose { + P.Trace("SwitchCase"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, P.tok); if P.tok == Scanner.CASE { @@ -1326,24 +1374,28 @@ func (P *Parser) ParseSwitchCase() *AST.Stat { P.Expect(Scanner.DEFAULT); } - P.Ecart(); return s; } func (P *Parser) ParseCaseClause() *AST.Stat { - P.Trace("CaseClause"); + if P.verbose { + P.Trace("CaseClause"); + defer P.Ecart(); + } s := P.ParseSwitchCase(); s.Body = P.ParseBlock(nil, Scanner.COLON); - P.Ecart(); return s; } func (P *Parser) ParseSwitchStat() *AST.Stat { - P.Trace("SwitchStat"); + if P.verbose { + P.Trace("SwitchStat"); + defer P.Ecart(); + } P.OpenScope(); s := P.ParseControlClause(Scanner.SWITCH); @@ -1358,13 +1410,15 @@ func (P *Parser) ParseSwitchStat() *AST.Stat { P.CloseScope(); s.Body = b; - P.Ecart(); return s; } func (P *Parser) ParseCommCase() *AST.Stat { - P.Trace("CommCase"); + if P.verbose { + P.Trace("CommCase"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, P.tok); if P.tok == Scanner.CASE { @@ -1375,7 +1429,7 @@ func (P *Parser) ParseCommCase() *AST.Stat { P.Next(); if P.tok == Scanner.ARROW { y := P.ParseExpression(1); - x = AST.NewExpr(pos, tok, x, y); + x = P.NewBinary(pos, tok, x, y); } else { P.Expect(Scanner.ARROW); // use Expect() error handling } @@ -1385,24 +1439,28 @@ func (P *Parser) ParseCommCase() *AST.Stat { P.Expect(Scanner.DEFAULT); } - P.Ecart(); return s; } func (P *Parser) ParseCommClause() *AST.Stat { - P.Trace("CommClause"); + if P.verbose { + P.Trace("CommClause"); + defer P.Ecart(); + } s := P.ParseCommCase(); s.Body = P.ParseBlock(nil, Scanner.COLON); - P.Ecart(); return s; } func (P *Parser) ParseSelectStat() *AST.Stat { - P.Trace("SelectStat"); + if P.verbose { + P.Trace("SelectStat"); + defer P.Ecart(); + } s := AST.NewStat(P.pos, Scanner.SELECT); P.Expect(Scanner.SELECT); @@ -1416,13 +1474,15 @@ func (P *Parser) ParseSelectStat() *AST.Stat { P.opt_semi = true; s.Body = b; - P.Ecart(); return s; } func (P *Parser) ParseStatement() *AST.Stat { - P.Trace("Statement"); + if P.verbose { + P.Trace("Statement"); + defer P.Ecart(); + } indent := P.indent; s := AST.BadStat; @@ -1465,7 +1525,6 @@ func (P *Parser) ParseStatement() *AST.Stat { if indent != P.indent { panic("imbalanced tracing code (Statement)"); } - P.Ecart(); return s; } @@ -1474,7 +1533,10 @@ func (P *Parser) ParseStatement() *AST.Stat { // Declarations func (P *Parser) ParseImportSpec(d *AST.Decl) { - P.Trace("ImportSpec"); + if P.verbose { + P.Trace("ImportSpec"); + defer P.Ecart(); + } if P.tok == Scanner.PERIOD { P.Error(P.pos, `"import ." not yet handled properly`); @@ -1485,19 +1547,19 @@ func (P *Parser) ParseImportSpec(d *AST.Decl) { if P.tok == Scanner.STRING { // TODO eventually the scanner should strip the quotes - val := AST.NewObject(P.pos, AST.NONE, P.val); - d.Val = AST.NewLit(Scanner.STRING, val); + d.Val = &AST.BasicLit{P.pos, Scanner.STRING, P.val}; P.Next(); } else { P.Expect(Scanner.STRING); // use Expect() error handling } - - P.Ecart(); } func (P *Parser) ParseConstSpec(d *AST.Decl) { - P.Trace("ConstSpec"); + if P.verbose { + P.Trace("ConstSpec"); + defer P.Ecart(); + } d.Ident = P.ParseIdentList(); d.Typ = P.TryType(); @@ -1505,24 +1567,26 @@ func (P *Parser) ParseConstSpec(d *AST.Decl) { P.Next(); d.Val = P.ParseExpressionList(); } - - P.Ecart(); } func (P *Parser) ParseTypeSpec(d *AST.Decl) { - P.Trace("TypeSpec"); + if P.verbose { + P.Trace("TypeSpec"); + defer P.Ecart(); + } d.Ident = P.ParseIdent(nil); d.Typ = P.ParseType(); P.opt_semi = true; - - P.Ecart(); } func (P *Parser) ParseVarSpec(d *AST.Decl) { - P.Trace("VarSpec"); + if P.verbose { + P.Trace("VarSpec"); + defer P.Ecart(); + } d.Ident = P.ParseIdentList(); if P.tok == Scanner.ASSIGN { @@ -1535,8 +1599,6 @@ func (P *Parser) ParseVarSpec(d *AST.Decl) { d.Val = P.ParseExpressionList(); } } - - P.Ecart(); } @@ -1560,17 +1622,17 @@ func (P *Parser) ParseSpec(d *AST.Decl) { P.Declare(d.Ident, kind, d.Typ); if d.Val != nil { // initialization/assignment - llen := d.Ident.Len(); - rlen := d.Val.Len(); + llen := AST.ExprLen(d.Ident); + rlen := AST.ExprLen(d.Val); if llen == rlen { // TODO } else if rlen == 1 { // TODO } else { if llen < rlen { - P.Error(d.Val.At(llen).Pos, "more expressions than variables"); + P.Error(AST.ExprAt(d.Val, llen).Pos(), "more expressions than variables"); } else { - P.Error(d.Ident.At(rlen).Pos, "more variables than expressions"); + P.Error(AST.ExprAt(d.Ident, rlen).Pos(), "more variables than expressions"); } } } else { @@ -1581,7 +1643,10 @@ func (P *Parser) ParseSpec(d *AST.Decl) { func (P *Parser) ParseDecl(keyword int) *AST.Decl { - P.Trace("Decl"); + if P.verbose { + P.Trace("Decl"); + defer P.Ecart(); + } d := AST.NewDecl(P.pos, keyword); P.Expect(keyword); @@ -1606,7 +1671,6 @@ func (P *Parser) ParseDecl(keyword int) *AST.Decl { P.ParseSpec(d); } - P.Ecart(); return d; } @@ -1621,7 +1685,10 @@ func (P *Parser) ParseDecl(keyword int) *AST.Decl { // func (recv) ident (params) (results) func (P *Parser) ParseFunctionDecl() *AST.Decl { - P.Trace("FunctionDecl"); + if P.verbose { + P.Trace("FunctionDecl"); + defer P.Ecart(); + } d := AST.NewDecl(P.pos, Scanner.FUNC); P.Expect(Scanner.FUNC); @@ -1635,24 +1702,24 @@ func (P *Parser) ParseFunctionDecl() *AST.Decl { } } - d.Ident = P.ParseIdent(nil); + ident := P.ParseIdent(nil); + d.Ident = ident; d.Typ = P.ParseSignature(); d.Typ.Key = recv; if P.tok == Scanner.LBRACE { - f := AST.NewObject(d.Pos, AST.FUNC, d.Ident.Obj.Ident); - f.Typ = d.Typ; - f.Body = P.ParseBlock(d.Typ, Scanner.LBRACE); - d.Val = AST.NewLit(Scanner.FUNC, f); + d.Body = P.ParseBlock(d.Typ, Scanner.LBRACE); } - P.Ecart(); return d; } func (P *Parser) ParseDeclaration() *AST.Decl { - P.Trace("Declaration"); + if P.verbose { + P.Trace("Declaration"); + defer P.Ecart(); + } indent := P.indent; d := AST.BadDecl; @@ -1670,7 +1737,6 @@ func (P *Parser) ParseDeclaration() *AST.Decl { if indent != P.indent { panic("imbalanced tracing code (Declaration)"); } - P.Ecart(); return d; } @@ -1679,7 +1745,10 @@ func (P *Parser) ParseDeclaration() *AST.Decl { // Program func (P *Parser) ParseProgram() *AST.Program { - P.Trace("Program"); + if P.verbose { + P.Trace("Program"); + defer P.Ecart(); + } P.OpenScope(); p := AST.NewProgram(P.pos); @@ -1705,6 +1774,5 @@ func (P *Parser) ParseProgram() *AST.Program { p.Comments = P.comments; P.CloseScope(); - P.Ecart(); return p; } |