diff options
author | Robert Griesemer <gri@golang.org> | 2009-02-27 15:40:17 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2009-02-27 15:40:17 -0800 |
commit | 4d08ae6898c3d97bbbca88be04524604869597f2 (patch) | |
tree | b5c5e8c1c022004ea7c9457fe9372f31e684f755 /usr/gri/pretty/parser.go | |
parent | b0e32c728af176fc2759c24d51302c5c4bcd1ec9 (diff) | |
download | golang-4d08ae6898c3d97bbbca88be04524604869597f2.tar.gz |
Steps towards a general scanner/parser library for Go:
- converted more of AST and parser to use interfaces and explicit
structs for individual Go constructs (can be replaced now with
interface calls such that the parser becomes AST structure
independent, as suggested by rsc)
- added more tests (find all .go files under GOROOT)
- (temporarily) lost html links for identifiers when generating
html output
- TODO: lots of cleanups
R=r
OCL=25518
CL=25518
Diffstat (limited to 'usr/gri/pretty/parser.go')
-rw-r--r-- | usr/gri/pretty/parser.go | 575 |
1 files changed, 339 insertions, 236 deletions
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go index c2af6ce20..0eced7fdb 100644 --- a/usr/gri/pretty/parser.go +++ b/usr/gri/pretty/parser.go @@ -29,7 +29,7 @@ type Parser struct { val string; // token value (for IDENT, NUMBER, STRING only) // Non-syntactic parser control - opt_semi bool; // true if semicolon is optional + opt_semi bool; // true if semicolon separator is optional in statement list // Nesting levels scope_lev int; // 0 = global scope, 1 = function scope of global functions, etc. @@ -170,6 +170,7 @@ func (P *Parser) closeScope() { } +/* func (P *Parser) declareInScope(scope *SymbolTable.Scope, x AST.Expr, kind int, typ *AST.Type) { if P.scope_lev < 0 { panic("cannot declare objects in other packages"); @@ -207,15 +208,16 @@ func (P *Parser) declare(x AST.Expr, kind int, typ *AST.Type) { } P.declareInScope(P.top_scope, x, kind, typ); } +*/ // ---------------------------------------------------------------------------- // Common productions -func (P *Parser) tryType() *AST.Type; +func (P *Parser) tryType() AST.Expr; func (P *Parser) parseExpression(prec int) AST.Expr; func (P *Parser) parseStatement() AST.Stat; -func (P *Parser) parseDeclaration() *AST.Decl; +func (P *Parser) parseDeclaration() AST.Decl; // If scope != nil, lookup identifier in scope. Otherwise create one. @@ -270,10 +272,34 @@ func (P *Parser) parseIdentList(x AST.Expr) AST.Expr { } +func (P *Parser) parseIdentList2(x AST.Expr) []*AST.Ident { + if P.trace { + defer un(trace(P, "IdentList")); + } + + list := vector.New(0); + if x == nil { + x = P.parseIdent(nil); + } + list.Push(x); + for P.tok == Scanner.COMMA { + P.next(); + list.Push(P.parseIdent(nil)); + } + + // convert vector + idents := make([]*AST.Ident, list.Len()); + for i := 0; i < list.Len(); i++ { + idents[i] = list.At(i).(*AST.Ident); + } + return idents; +} + + // ---------------------------------------------------------------------------- // Types -func (P *Parser) parseType() *AST.Type { +func (P *Parser) parseType() AST.Expr { if P.trace { defer un(trace(P, "Type")); } @@ -281,14 +307,14 @@ func (P *Parser) parseType() *AST.Type { t := P.tryType(); if t == nil { P.error(P.pos, "type expected"); - t = AST.BadType; + t = &AST.BadExpr(P.pos); } return t; } -func (P *Parser) parseVarType() *AST.Type { +func (P *Parser) parseVarType() AST.Expr { if P.trace { defer un(trace(P, "VarType")); } @@ -314,88 +340,90 @@ func (P *Parser) parseQualifiedIdent() AST.Expr { } -func (P *Parser) parseTypeName() *AST.Type { +func (P *Parser) parseTypeName() AST.Expr { if P.trace { defer un(trace(P, "TypeName")); } - t := AST.NewType(P.pos, AST.TYPENAME); - t.Expr = P.parseQualifiedIdent(); - - return t; + return P.parseQualifiedIdent(); } -func (P *Parser) parseArrayType() *AST.Type { +func (P *Parser) parseArrayType() *AST.ArrayType { if P.trace { defer un(trace(P, "ArrayType")); } - t := AST.NewType(P.pos, AST.ARRAY); + pos := P.pos; P.expect(Scanner.LBRACK); + var len AST.Expr; if P.tok == Scanner.ELLIPSIS { - t.Expr = &AST.BinaryExpr(P.pos, Scanner.ELLIPSIS, nil, nil); + len = &AST.Ellipsis(P.pos); P.next(); } else if P.tok != Scanner.RBRACK { - t.Expr = P.parseExpression(1); + len = P.parseExpression(1); } P.expect(Scanner.RBRACK); - t.Elt = P.parseType(); + elt := P.parseType(); - return t; + return &AST.ArrayType(pos, len, elt); } -func (P *Parser) parseChannelType() *AST.Type { +func (P *Parser) parseChannelType() *AST.ChannelType { if P.trace { defer un(trace(P, "ChannelType")); } - t := AST.NewType(P.pos, AST.CHANNEL); - t.Mode = AST.FULL; + pos := P.pos; + mode := AST.FULL; if P.tok == Scanner.CHAN { P.next(); if P.tok == Scanner.ARROW { P.next(); - t.Mode = AST.SEND; + mode = AST.SEND; } } else { P.expect(Scanner.ARROW); P.expect(Scanner.CHAN); - t.Mode = AST.RECV; + mode = AST.RECV; } - t.Elt = P.parseVarType(); + val := P.parseVarType(); - return t; + return &AST.ChannelType(pos, mode, val); } -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.Expr = x; - } else if P.tok == Scanner.ELLIPSIS { - t = AST.NewType(P.pos, AST.ELLIPSIS); +func (P *Parser) tryParameterType() AST.Expr { + if P.tok == Scanner.ELLIPSIS { + pos := P.tok; P.next(); - } else { - t = P.parseType(); + return &AST.Ellipsis(pos); } - return t; + return P.tryType(); +} + + +func (P *Parser) parseParameterType() AST.Expr { + typ := P.tryParameterType(); + if typ == nil { + P.error(P.tok, "type expected"); + typ = &AST.BadExpr(P.pos); + } + return typ; } -func (P *Parser) parseVarList(list *vector.Vector, ellipsis_ok bool) { +func (P *Parser) parseParameterDecl(ellipsis_ok bool) (*vector.Vector, AST.Expr) { if P.trace { - defer un(trace(P, "VarList")); + defer un(trace(P, "ParameterDecl")); } - // assume a list of types - // (a list of identifiers looks like a list of type names) - i0 := list.Len(); + // a list of identifiers looks like a list of type names + list := vector.New(0); for { - list.Push(P.parseVar(ellipsis_ok /* param list */ && i0 > 0)); + // TODO do not allow ()'s here + list.Push(P.parseParameterType()); if P.tok == Scanner.COMMA { P.next(); } else { @@ -404,115 +432,87 @@ func (P *Parser) parseVarList(list *vector.Vector, ellipsis_ok bool) { } // if we had a list of identifiers, it must be followed by a type - typ := P.tryType(); - if typ == nil && P.tok == Scanner.ELLIPSIS { - typ = AST.NewType(P.pos, AST.ELLIPSIS); - P.next(); - } + typ := P.tryParameterType(); + + return list, typ; +} - if ellipsis_ok /* param list */ && i0 > 0 && typ == nil { - // not the first parameter section; we must have a type - P.error(P.pos, "type expected"); - typ = AST.BadType; + +func (P *Parser) parseParameterList(ellipsis_ok bool) []*AST.Field { + if P.trace { + defer un(trace(P, "ParameterList")); } - // convert the list into a list of (type) expressions + list, typ := P.parseParameterDecl(false); if typ != nil { - // all list entries must be identifiers - // 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 { - 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"); + // IdentifierList Type + // convert list of identifiers into []*Ident + idents := make([]*AST.Ident, list.Len()); + for i := 0; i < list.Len(); i++ { + idents[i] = list.At(i).(*AST.Ident); + } + list.Init(0); + list.Push(&AST.Field(idents, typ, nil)); + + for P.tok == Scanner.COMMA { + P.next(); + idents := P.parseIdentList2(nil); + typ := P.parseParameterType(); + list.Push(&AST.Field(idents, typ, nil)); } - // add type - 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.TypeLit(t)); + // Type { "," Type } + // convert list of types into list of *Param + for i := 0; i < list.Len(); i++ { + list.Set(i, &AST.Field(nil, list.At(i).(AST.Expr), nil)); } } -} - -func (P *Parser) parseParameterList(ellipsis_ok bool) *vector.Vector { - if P.trace { - defer un(trace(P, "ParameterList")); + // convert list + params := make([]*AST.Field, list.Len()); + for i := 0; i < list.Len(); i++ { + params[i] = list.At(i).(*AST.Field); } - list := vector.New(0); - P.parseVarList(list, ellipsis_ok); - for P.tok == Scanner.COMMA { - P.next(); - P.parseVarList(list, ellipsis_ok); - } - - return list; + return params; } -func (P *Parser) parseParameters(ellipsis_ok bool) *AST.Type { +// TODO make sure Go spec is updated +func (P *Parser) parseParameters(ellipsis_ok bool) []*AST.Field { if P.trace { defer un(trace(P, "Parameters")); } - t := AST.NewType(P.pos, AST.STRUCT); + var params []*AST.Field; P.expect(Scanner.LPAREN); if P.tok != Scanner.RPAREN { - t.List = P.parseParameterList(ellipsis_ok); + params = P.parseParameterList(ellipsis_ok); } - t.End = P.pos; P.expect(Scanner.RPAREN); - return t; + return params; } -func (P *Parser) parseResultList() { - if P.trace { - defer un(trace(P, "ResultList")); - } - - P.parseType(); - for P.tok == Scanner.COMMA { - P.next(); - P.parseType(); - } - if P.tok != Scanner.RPAREN { - P.parseType(); - } -} - - -func (P *Parser) parseResult(ftyp *AST.Type) *AST.Type { +func (P *Parser) parseResult() []*AST.Field { if P.trace { defer un(trace(P, "Result")); } - var t *AST.Type; + var result []*AST.Field; if P.tok == Scanner.LPAREN { - t = P.parseParameters(false); + result = P.parseParameters(false); } else if P.tok != Scanner.FUNC { typ := P.tryType(); if typ != nil { - t = AST.NewType(P.pos, AST.STRUCT); - t.List = vector.New(0); - t.List.Push(&AST.TypeLit(typ)); - t.End = P.pos; + result = make([]*AST.Field, 1); + result[0] = &AST.Field(nil, typ, nil); } } - return t; + return result; } @@ -522,120 +522,189 @@ func (P *Parser) parseResult(ftyp *AST.Type) *AST.Type { // (params) type // (params) (results) -func (P *Parser) parseSignature() *AST.Type { +func (P *Parser) parseSignature() *AST.Signature { if P.trace { defer un(trace(P, "Signature")); } - P.openScope(); - P.scope_lev++; + //P.openScope(); + //P.scope_lev++; - t := AST.NewType(P.pos, AST.FUNCTION); - t.Scope = P.top_scope; - t.List = P.parseParameters(true).List; // TODO find better solution - t.End = P.pos; - t.Elt = P.parseResult(t); + //t.Scope = P.top_scope; + params := P.parseParameters(true); // TODO find better solution + //t.End = P.pos; + result := P.parseResult(); - P.scope_lev--; - P.closeScope(); + //P.scope_lev--; + //P.closeScope(); - return t; + return &AST.Signature(params, result); } -func (P *Parser) parseFunctionType() *AST.Type { +func (P *Parser) parseFunctionType() *AST.FunctionType { if P.trace { defer un(trace(P, "FunctionType")); } + pos := P.pos; P.expect(Scanner.FUNC); - return P.parseSignature(); + sig := P.parseSignature(); + + return &AST.FunctionType(pos, sig); } -func (P *Parser) parseMethodOrInterfaceSpec(list *vector.Vector) { +func (P *Parser) parseMethodSpec() *AST.Field { if P.trace { - defer un(trace(P, "MethodOrInterfaceSpec")); + defer un(trace(P, "MethodSpec")); } + var idents []*AST.Ident; + var typ AST.Expr; x := P.parseQualifiedIdent(); if tmp, is_ident := x.(*AST.Ident); is_ident && (P.tok == Scanner.COMMA || P.tok == Scanner.LPAREN) { // method(s) - list.Push(P.parseIdentList(x)); - list.Push(&AST.TypeLit(P.parseSignature())); + idents = P.parseIdentList2(x); + typ = &AST.FunctionType(0, P.parseSignature()); } else { // embedded interface - list.Push(x); + typ = x; } + + return &AST.Field(idents, typ, nil); } -func (P *Parser) parseInterfaceType() *AST.Type { +func (P *Parser) parseInterfaceType() *AST.InterfaceType { if P.trace { defer un(trace(P, "InterfaceType")); } - t := AST.NewType(P.pos, AST.INTERFACE); + pos := P.pos; + end := 0; + var methods []*AST.Field; + P.expect(Scanner.INTERFACE); if P.tok == Scanner.LBRACE { P.next(); - P.openScope(); - P.scope_lev++; + //P.openScope(); + //P.scope_lev++; - t.List = vector.New(0); + list := vector.New(0); for P.tok == Scanner.IDENT { - P.parseMethodOrInterfaceSpec(t.List); + list.Push(P.parseMethodSpec()); if P.tok != Scanner.RBRACE { P.expect(Scanner.SEMICOLON); } } - t.End = P.pos; + //t.End = P.pos; - P.scope_lev--; - P.closeScope(); + //P.scope_lev--; + //P.closeScope(); + end = P.pos; P.expect(Scanner.RBRACE); + P.opt_semi = true; + + // convert vector + methods = make([]*AST.Field, list.Len()); + for i := list.Len() - 1; i >= 0; i-- { + methods[i] = list.At(i).(*AST.Field); + } } - return t; + return &AST.InterfaceType(pos, methods, end); } -func (P *Parser) parseMapType() *AST.Type { +func (P *Parser) parseMapType() *AST.MapType { if P.trace { defer un(trace(P, "MapType")); } - t := AST.NewType(P.pos, AST.MAP); + pos := P.pos; P.expect(Scanner.MAP); P.expect(Scanner.LBRACK); - t.Key = P.parseVarType(); + key := P.parseVarType(); P.expect(Scanner.RBRACK); - t.Elt = P.parseVarType(); + val := P.parseVarType(); - return t; + return &AST.MapType(pos, key, val); } func (P *Parser) parseOperand() AST.Expr -func (P *Parser) parseStructType() *AST.Type { + +func (P *Parser) parseFieldDecl() *AST.Field { + if P.trace { + defer un(trace(P, "FieldDecl")); + } + + // a list of identifiers looks like a list of type names + list := vector.New(0); + for { + // TODO do not allow ()'s here + list.Push(P.parseType()); + if P.tok == Scanner.COMMA { + P.next(); + } else { + break; + } + } + + // if we had a list of identifiers, it must be followed by a type + typ := P.tryType(); + + // optional tag + var tag AST.Expr; + if P.tok == Scanner.STRING { + // ParseOperand takes care of string concatenation + tag = P.parseOperand(); + } + + // analyze case + var idents []*AST.Ident; + if typ != nil { + // non-empty identifier list followed by a type + idents = make([]*AST.Ident, list.Len()); + for i := 0; i < list.Len(); i++ { + if ident, is_ident := list.At(i).(*AST.Ident); is_ident { + idents[i] = ident; + } else { + P.error(list.At(i).(AST.Expr).Pos(), "identifier expected"); + } + } + } else { + // anonymous field + if list.Len() == 1 { + // TODO should do more checks here + typ = list.At(0).(AST.Expr); + } else { + P.error(P.pos, "anonymous field expected"); + } + } + + return &AST.Field(idents, typ, tag); +} + + +func (P *Parser) parseStructType() AST.Expr { if P.trace { defer un(trace(P, "StructType")); } - t := AST.NewType(P.pos, AST.STRUCT); + pos := P.pos; + end := 0; + var fields []*AST.Field; + P.expect(Scanner.STRUCT); if P.tok == Scanner.LBRACE { P.next(); - t.List = vector.New(0); - t.Scope = SymbolTable.NewScope(nil); + list := vector.New(0); for P.tok != Scanner.RBRACE && P.tok != Scanner.EOF { - P.parseVarList(t.List, false); - if P.tok == Scanner.STRING { - // ParseOperand takes care of string concatenation - t.List.Push(P.parseOperand()); - } + list.Push(P.parseFieldDecl()); if P.tok == Scanner.SEMICOLON { P.next(); } else { @@ -643,36 +712,36 @@ func (P *Parser) parseStructType() *AST.Type { } } P.OptSemicolon(); - t.End = P.pos; + end = P.pos; P.expect(Scanner.RBRACE); + P.opt_semi = true; - // enter fields into struct scope - for i, n := 0, t.List.Len(); i < n; i++ { - if x, ok := t.List.At(i).(*AST.Ident); ok { - P.declareInScope(t.Scope, x, SymbolTable.FIELD, nil); - } + // convert vector + fields = make([]*AST.Field, list.Len()); + for i := list.Len() - 1; i >= 0; i-- { + fields[i] = list.At(i).(*AST.Field); } } - return t; + return AST.StructType(pos, fields, end); } -func (P *Parser) parsePointerType() *AST.Type { +func (P *Parser) parsePointerType() AST.Expr { if P.trace { defer un(trace(P, "PointerType")); } - t := AST.NewType(P.pos, AST.POINTER); + pos := P.pos; P.expect(Scanner.MUL); - t.Elt = P.parseType(); + base := P.parseType(); - return t; + return &AST.PointerType(pos, base); } -func (P *Parser) tryType() *AST.Type { +func (P *Parser) tryType() AST.Expr { if P.trace { defer un(trace(P, "Type (try)")); } @@ -687,10 +756,11 @@ func (P *Parser) tryType() *AST.Type { case Scanner.STRUCT: return P.parseStructType(); case Scanner.MUL: return P.parsePointerType(); case Scanner.LPAREN: + pos := P.pos; P.next(); t := P.parseType(); P.expect(Scanner.RPAREN); - return t; + return &AST.Group(pos, t); } // no type found @@ -725,7 +795,7 @@ func (P *Parser) parseStatementList(list *vector.Vector) { } -func (P *Parser) parseBlock(ftyp *AST.Type, tok int) *AST.Block { +func (P *Parser) parseBlock(tok int) *AST.Block { if P.trace { defer un(trace(P, "Block")); } @@ -733,6 +803,7 @@ func (P *Parser) parseBlock(ftyp *AST.Type, tok int) *AST.Block { b := AST.NewBlock(P.pos, tok); P.expect(tok); + /* P.openScope(); // enter recv and parameters into function scope if ftyp != nil { @@ -747,9 +818,13 @@ func (P *Parser) parseBlock(ftyp *AST.Type, tok int) *AST.Block { } } } - + */ + P.parseStatementList(b.List); + + /* P.closeScope(); + */ if tok == Scanner.LBRACE { b.End = P.pos; @@ -795,7 +870,7 @@ func (P *Parser) parseFunctionLit() AST.Expr { P.expect(Scanner.FUNC); typ := P.parseSignature(); P.scope_lev++; - body := P.parseBlock(typ, Scanner.LBRACE); + body := P.parseBlock(Scanner.LBRACE); P.scope_lev--; return &AST.FunctionLit(pos, typ, body); @@ -812,10 +887,11 @@ func (P *Parser) parseOperand() AST.Expr { return P.parseIdent(P.top_scope); case Scanner.LPAREN: + pos := P.pos; P.next(); x := P.parseExpression(1); P.expect(Scanner.RPAREN); - return x; + return &AST.Group(pos, x); case Scanner.INT, Scanner.FLOAT, Scanner.STRING: x := &AST.BasicLit(P.pos, P.tok, P.val); @@ -835,7 +911,7 @@ func (P *Parser) parseOperand() AST.Expr { default: t := P.tryType(); if t != nil { - return &AST.TypeLit(t); + return t; } else { P.error(P.pos, "operand expected"); P.next(); // make progress @@ -978,6 +1054,8 @@ func (P *Parser) parseUnaryExpr() AST.Expr { pos, tok := P.pos, P.tok; P.next(); y := P.parseUnaryExpr(); + return &AST.UnaryExpr(pos, tok, y); + /* if lit, ok := y.(*AST.TypeLit); ok && tok == Scanner.MUL { // pointer type t := AST.NewType(pos, AST.POINTER); @@ -986,6 +1064,7 @@ func (P *Parser) parseUnaryExpr() AST.Expr { } else { return &AST.UnaryExpr(pos, tok, y); } + */ } return P.parsePrimaryExpr(); @@ -1180,7 +1259,7 @@ func (P *Parser) parseIfStat() *AST.IfStat { pos := P.pos; P.expect(Scanner.IF); init, cond, dummy := P.parseControlClause(false); - body := P.parseBlock(nil, Scanner.LBRACE); + body := P.parseBlock(Scanner.LBRACE); var else_ AST.Stat; if P.tok == Scanner.ELSE { P.next(); @@ -1211,7 +1290,7 @@ func (P *Parser) parseForStat() *AST.ForStat { pos := P.pos; P.expect(Scanner.FOR); init, cond, post := P.parseControlClause(true); - body := P.parseBlock(nil, Scanner.LBRACE); + body := P.parseBlock(Scanner.LBRACE); P.closeScope(); return &AST.ForStat(pos, init, cond, post, body); @@ -1233,7 +1312,7 @@ func (P *Parser) parseCaseClause() *AST.CaseClause { P.expect(Scanner.DEFAULT); } - return &AST.CaseClause(pos, expr, P.parseBlock(nil, Scanner.COLON)); + return &AST.CaseClause(pos, expr, P.parseBlock(Scanner.COLON)); } @@ -1286,7 +1365,7 @@ func (P *Parser) parseCommClause() *AST.CaseClause { P.expect(Scanner.DEFAULT); } - return &AST.CaseClause(pos, expr, P.parseBlock(nil, Scanner.COLON)); + return &AST.CaseClause(pos, expr, P.parseBlock(Scanner.COLON)); } @@ -1337,7 +1416,7 @@ func (P *Parser) parseStatement() AST.Stat { case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO, Scanner.FALLTHROUGH: return P.parseControlFlowStat(P.tok); case Scanner.LBRACE: - return &AST.CompositeStat(P.parseBlock(nil, Scanner.LBRACE)); + return &AST.CompositeStat(P.parseBlock(Scanner.LBRACE)); case Scanner.IF: return P.parseIfStat(); case Scanner.FOR: @@ -1360,90 +1439,105 @@ func (P *Parser) parseStatement() AST.Stat { // ---------------------------------------------------------------------------- // Declarations -func (P *Parser) parseImportSpec(d *AST.Decl) { +func (P *Parser) parseImportSpec(pos int) *AST.ImportDecl { if P.trace { defer un(trace(P, "ImportSpec")); } + var ident *AST.Ident; if P.tok == Scanner.PERIOD { P.error(P.pos, `"import ." not yet handled properly`); P.next(); } else if P.tok == Scanner.IDENT { - d.Ident = P.parseIdent(nil); + ident = P.parseIdent(nil); } + var path AST.Expr; if P.tok == Scanner.STRING { // TODO eventually the scanner should strip the quotes - d.Val = &AST.BasicLit(P.pos, Scanner.STRING, P.val); + path = &AST.BasicLit(P.pos, Scanner.STRING, P.val); P.next(); } else { P.expect(Scanner.STRING); // use expect() error handling } + + return &AST.ImportDecl(pos, ident, path); } -func (P *Parser) parseConstSpec(d *AST.Decl) { +func (P *Parser) parseConstSpec(pos int) *AST.ConstDecl { if P.trace { defer un(trace(P, "ConstSpec")); } - d.Ident = P.parseIdentList(nil); - d.Typ = P.tryType(); + idents := P.parseIdentList2(nil); + typ := P.tryType(); + var vals AST.Expr; if P.tok == Scanner.ASSIGN { P.next(); - d.Val = P.parseExpressionList(); + vals = P.parseExpressionList(); } + + return &AST.ConstDecl(pos, idents, typ, vals); } -func (P *Parser) parseTypeSpec(d *AST.Decl) { +func (P *Parser) parseTypeSpec(pos int) *AST.TypeDecl { if P.trace { defer un(trace(P, "TypeSpec")); } - d.Ident = P.parseIdent(nil); - d.Typ = P.parseType(); - P.opt_semi = true; + ident := P.parseIdent(nil); + typ := P.parseType(); + + return &AST.TypeDecl(pos, ident, typ); } -func (P *Parser) parseVarSpec(d *AST.Decl) { +func (P *Parser) parseVarSpec(pos int) *AST.VarDecl { if P.trace { defer un(trace(P, "VarSpec")); } - d.Ident = P.parseIdentList(nil); + idents := P.parseIdentList2(nil); + var typ AST.Expr; + var vals AST.Expr; if P.tok == Scanner.ASSIGN { P.next(); - d.Val = P.parseExpressionList(); + vals = P.parseExpressionList(); } else { - d.Typ = P.parseVarType(); + typ = P.parseVarType(); if P.tok == Scanner.ASSIGN { P.next(); - d.Val = P.parseExpressionList(); + vals = P.parseExpressionList(); } } + + return &AST.VarDecl(pos, idents, typ, vals); } -func (P *Parser) parseSpec(d *AST.Decl) { +func (P *Parser) parseSpec(pos, keyword int) AST.Decl { kind := SymbolTable.NONE; - switch d.Tok { - case Scanner.IMPORT: P.parseImportSpec(d); kind = SymbolTable.PACKAGE; - case Scanner.CONST: P.parseConstSpec(d); kind = SymbolTable.CONST; - case Scanner.TYPE: P.parseTypeSpec(d); kind = SymbolTable.TYPE; - case Scanner.VAR: P.parseVarSpec(d); kind = SymbolTable.VAR; - default: unreachable(); + switch keyword { + case Scanner.IMPORT: return P.parseImportSpec(pos); + case Scanner.CONST: return P.parseConstSpec(pos); + case Scanner.TYPE: return P.parseTypeSpec(pos); + case Scanner.VAR: return P.parseVarSpec(pos); } + + unreachable(); + return nil; + /* // semantic checks if d.Tok == Scanner.IMPORT { if d.Ident != nil { - P.declare(d.Ident, kind, nil); + //P.declare(d.Ident, kind, nil); } } else { - P.declare(d.Ident, kind, d.Typ); + //P.declare(d.Ident, kind, d.Typ); if d.Val != nil { // initialization/assignment llen := AST.ExprLen(d.Ident); @@ -1463,38 +1557,42 @@ func (P *Parser) parseSpec(d *AST.Decl) { // TODO } } + */ } -func (P *Parser) parseDecl(keyword int) *AST.Decl { +func (P *Parser) parseDecl(keyword int) AST.Decl { if P.trace { defer un(trace(P, "Decl")); } - d := AST.NewDecl(P.pos, keyword); + pos := P.pos; P.expect(keyword); if P.tok == Scanner.LPAREN { P.next(); - d.List = vector.New(0); + list := vector.New(0); for P.tok != Scanner.RPAREN && P.tok != Scanner.EOF { - d1 := AST.NewDecl(P.pos, keyword); - P.parseSpec(d1); - d.List.Push(d1); + list.Push(P.parseSpec(0, keyword)); if P.tok == Scanner.SEMICOLON { P.next(); } else { break; } } - d.End = P.pos; + end := P.pos; P.expect(Scanner.RPAREN); P.opt_semi = true; - - } else { - P.parseSpec(d); + + // convert vector + decls := make([]AST.Decl, list.Len()); + for i := 0; i < list.Len(); i++ { + decls[i] = list.At(i).(AST.Decl); + } + + return &AST.DeclList(pos, keyword, decls, end); } - return d; + return P.parseSpec(pos, keyword); } @@ -1507,54 +1605,53 @@ func (P *Parser) parseDecl(keyword int) *AST.Decl { // func (recv) ident (params) type // func (recv) ident (params) (results) -func (P *Parser) parseFunctionDecl() *AST.Decl { +func (P *Parser) parseFunctionDecl() *AST.FuncDecl { if P.trace { defer un(trace(P, "FunctionDecl")); } - d := AST.NewDecl(P.pos, Scanner.FUNC); + pos := P.pos; P.expect(Scanner.FUNC); - var recv *AST.Type; + var recv *AST.Field; if P.tok == Scanner.LPAREN { pos := P.pos; - recv = P.parseParameters(true); - if recv.Nfields() != 1 { + tmp := P.parseParameters(true); + if len(tmp) == 1 { + recv = tmp[0]; + } else { P.error(pos, "must have exactly one receiver"); } } ident := P.parseIdent(nil); - d.Ident = ident; - d.Typ = P.parseSignature(); - d.Typ.Key = recv; + sig := P.parseSignature(); + var body *AST.Block; if P.tok == Scanner.LBRACE { - d.Body = P.parseBlock(d.Typ, Scanner.LBRACE); + body = P.parseBlock(Scanner.LBRACE); } - return d; + return &AST.FuncDecl(pos, recv, ident, sig, body); } -func (P *Parser) parseDeclaration() *AST.Decl { +func (P *Parser) parseDeclaration() AST.Decl { if P.trace { defer un(trace(P, "Declaration")); } - d := AST.BadDecl; - switch P.tok { case Scanner.CONST, Scanner.TYPE, Scanner.VAR: - d = P.parseDecl(P.tok); + return P.parseDecl(P.tok); case Scanner.FUNC: - d = P.parseFunctionDecl(); - default: - P.error(P.pos, "declaration expected"); - P.next(); // make progress + return P.parseFunctionDecl(); } - - return d; + + pos := P.pos; + P.error(pos, "declaration expected"); + P.next(); // make progress + return &AST.BadDecl(pos); } @@ -1573,18 +1670,24 @@ func (P *Parser) ParseProgram() *AST.Program { // package body { P.openScope(); - p.Decls = vector.New(0); + list := vector.New(0); for P.tok == Scanner.IMPORT { - p.Decls.Push(P.parseDecl(Scanner.IMPORT)); + list.Push(P.parseDecl(Scanner.IMPORT)); P.OptSemicolon(); } if !P.deps { for P.tok != Scanner.EOF { - p.Decls.Push(P.parseDeclaration()); + list.Push(P.parseDeclaration()); P.OptSemicolon(); } } P.closeScope(); + + // convert list + p.Decls = make([]AST.Decl, list.Len()); + for i := 0; i < list.Len(); i++ { + p.Decls[i] = list.At(i).(AST.Decl); + } } p.Comments = P.comments; |