summaryrefslogtreecommitdiff
path: root/usr/gri/pretty/parser.go
diff options
context:
space:
mode:
Diffstat (limited to 'usr/gri/pretty/parser.go')
-rw-r--r--usr/gri/pretty/parser.go268
1 files changed, 168 insertions, 100 deletions
diff --git a/usr/gri/pretty/parser.go b/usr/gri/pretty/parser.go
index 5bfa8bfe5..ffe9615c9 100644
--- a/usr/gri/pretty/parser.go
+++ b/usr/gri/pretty/parser.go
@@ -21,6 +21,10 @@ import (
)
+// TODO rename Position to scanner.Position, possibly factor out
+type Position scanner.Location
+
+
// A Parser holds the parser's internal state while processing
// a given text. It can be allocated as part of another data
// structure but must be initialized via Init before use.
@@ -37,7 +41,7 @@ type Parser struct {
last_comment ast.CommentGroup;
// The next token
- loc scanner.Location; // token location
+ loc Position; // token location
tok int; // one token look-ahead
val []byte; // token value
@@ -49,7 +53,7 @@ type Parser struct {
// When we don't have a location use noloc.
// TODO make sure we always have a location.
-var noloc scanner.Location;
+var noloc Position;
// ----------------------------------------------------------------------------
@@ -182,12 +186,12 @@ func (P *Parser) Init(scanner *scanner.Scanner, err scanner.ErrorHandler, trace
}
-func (P *Parser) error(loc scanner.Location, msg string) {
+func (P *Parser) error(loc Position, msg string) {
P.err.Error(loc, msg);
}
-func (P *Parser) expect(tok int) {
+func (P *Parser) expect(tok int) Position {
if P.tok != tok {
msg := "expected '" + token.TokenString(tok) + "', found '" + token.TokenString(P.tok) + "'";
if token.IsLiteral(P.tok) {
@@ -195,7 +199,9 @@ func (P *Parser) expect(tok int) {
}
P.error(P.loc, msg);
}
+ loc := P.loc;
P.next(); // make progress in any case
+ return loc;
}
@@ -214,13 +220,13 @@ func (P *Parser) parseIdent() *ast.Ident {
}
if P.tok == token.IDENT {
- x := &ast.Ident{P.loc, string(P.val)};
+ x := &ast.Ident{string(P.val), P.loc};
P.next();
return x;
}
P.expect(token.IDENT); // use expect() error handling
- return &ast.Ident{P.loc, ""};
+ return &ast.Ident{"", P.loc};
}
@@ -254,13 +260,13 @@ func (P *Parser) parseExpressionList() []ast.Expr {
}
list := vector.New(0);
- list.Push(P.parseExpression(1)); // TODO should use a const instead of 1
+ list.Push(P.parseExpression(1));
for P.tok == token.COMMA {
P.next();
- list.Push(P.parseExpression(1)); // TODO should use a const instead of 1
+ list.Push(P.parseExpression(1));
}
- // convert vector
+ // convert list
exprs := make([]ast.Expr, list.Len());
for i := 0; i < list.Len(); i++ {
exprs[i] = list.At(i).(ast.Expr);
@@ -303,10 +309,10 @@ func (P *Parser) parseQualifiedIdent() ast.Expr {
var x ast.Expr = P.parseIdent();
for P.tok == token.PERIOD {
- loc := P.loc;
+ pos := P.loc;
P.next();
- y := P.parseIdent();
- x = &ast.Selector{loc, x, y};
+ sel := P.parseIdent();
+ x = &ast.Selector{x, sel, pos};
}
return x;
@@ -548,7 +554,7 @@ func (P *Parser) parseInterfaceType() *ast.InterfaceType {
}
loc := P.loc;
- var end scanner.Location;
+ var end Position;
var methods []*ast.Field;
P.expect(token.INTERFACE);
@@ -633,7 +639,7 @@ func (P *Parser) parseFieldDecl() *ast.Field {
if ident, is_ident := list.At(i).(*ast.Ident); is_ident {
idents[i] = ident;
} else {
- P.error(list.At(i).(ast.Expr).Loc(), "identifier expected");
+ P.error(list.At(i).(ast.Expr).Pos(), "identifier expected");
}
}
} else {
@@ -656,7 +662,7 @@ func (P *Parser) parseStructType() ast.Expr {
}
loc := P.loc;
- var end scanner.Location;
+ var end Position;
var fields []*ast.Field;
P.expect(token.STRUCT);
@@ -719,11 +725,11 @@ func (P *Parser) tryType() ast.Expr {
case token.STRUCT: return P.parseStructType();
case token.MUL: return P.parsePointerType();
case token.LPAREN:
- loc := P.loc;
+ lparen := P.loc;
P.next();
- t := P.parseType();
- P.expect(token.RPAREN);
- return &ast.Group{loc, t};
+ x := P.parseType();
+ rparen := P.expect(token.RPAREN);
+ return &ast.Group{x, lparen, rparen};
}
// no type found
@@ -786,14 +792,14 @@ func (P *Parser) parseFunctionLit() ast.Expr {
defer un(trace(P, "FunctionLit"));
}
- loc := P.loc;
+ pos := P.loc;
P.expect(token.FUNC);
typ := P.parseSignature();
P.expr_lev++;
body := P.parseBlock(token.LBRACE);
P.expr_lev--;
- return &ast.FunctionLit{loc, typ, body};
+ return &ast.FunctionLit{typ, body, pos};
}
@@ -802,16 +808,23 @@ func (P *Parser) parseStringLit() ast.Expr {
defer un(trace(P, "StringLit"));
}
- var x ast.Expr = &ast.BasicLit{P.loc, P.tok, P.val};
- P.expect(token.STRING); // always satisfied
+ if P.tok != token.STRING {
+ panic();
+ }
+ list := vector.New(0);
for P.tok == token.STRING {
- y := &ast.BasicLit{P.loc, P.tok, P.val};
+ list.Push(&ast.BasicLit{token.STRING, P.val, P.loc});
P.next();
- x = &ast.ConcatExpr{x, y};
}
- return x;
+ // convert list
+ strings := make([]*ast.BasicLit, list.Len());
+ for i := 0; i < list.Len(); i++ {
+ strings[i] = list.At(i).(*ast.BasicLit);
+ }
+
+ return &ast.StringLit{strings};
}
@@ -825,7 +838,7 @@ func (P *Parser) parseOperand() ast.Expr {
return P.parseIdent();
case token.INT, token.FLOAT, token.CHAR:
- x := &ast.BasicLit{P.loc, P.tok, P.val};
+ x := &ast.BasicLit{P.tok, P.val, P.loc};
P.next();
return x;
@@ -833,13 +846,13 @@ func (P *Parser) parseOperand() ast.Expr {
return P.parseStringLit();
case token.LPAREN:
- loc := P.loc;
+ lparen := P.loc;
P.next();
P.expr_lev++;
x := P.parseExpression(1);
P.expr_lev--;
- P.expect(token.RPAREN);
- return &ast.Group{loc, x};
+ rparen := P.expect(token.RPAREN);
+ return &ast.Group{x, lparen, rparen};
case token.FUNC:
return P.parseFunctionLit();
@@ -858,51 +871,74 @@ func (P *Parser) parseOperand() ast.Expr {
}
-func (P *Parser) parseSelectorOrTypeGuard(x ast.Expr) ast.Expr {
+func (P *Parser) parseSelectorOrTypeAssertion(x ast.Expr) ast.Expr {
if P.trace {
- defer un(trace(P, "SelectorOrTypeGuard"));
+ defer un(trace(P, "SelectorOrTypeAssertion"));
}
- loc := P.loc;
- P.expect(token.PERIOD);
+ period := P.expect(token.PERIOD);
if P.tok == token.IDENT {
- x = &ast.Selector{loc, x, P.parseIdent()};
-
+ // selector
+ sel := P.parseIdent();
+ return &ast.Selector{x, sel, period};
+ }
+
+ // type assertion
+ lparen := P.expect(token.LPAREN);
+ var typ ast.Expr;
+ if P.tok == token.TYPE {
+ typ = &ast.TypeType{P.loc};
+ P.next();
} else {
- P.expect(token.LPAREN);
- var typ ast.Expr;
- if P.tok == token.TYPE {
- typ = &ast.TypeType{P.loc};
- P.next();
- } else {
- typ = P.parseType();
- }
- x = &ast.TypeGuard{loc, x, typ};
- P.expect(token.RPAREN);
+ typ = P.parseType();
}
-
- return x;
+ rparen := P.expect(token.RPAREN);
+ return &ast.TypeAssertion{x, typ, period, lparen, rparen};
}
-func (P *Parser) parseIndex(x ast.Expr) ast.Expr {
+func (P *Parser) parseIndexOrSlice(x ast.Expr) ast.Expr {
if P.trace {
defer un(trace(P, "IndexOrSlice"));
}
- loc := P.loc;
- P.expect(token.LBRACK);
+ lbrack := P.expect(token.LBRACK);
P.expr_lev++;
- i := P.parseExpression(0);
+ index := P.parseExpression(1);
P.expr_lev--;
- P.expect(token.RBRACK);
- return &ast.Index{loc, x, i};
+ if P.tok == token.RBRACK {
+ // index
+ rbrack := P.loc;
+ P.next();
+ return &ast.Index{x, index, lbrack, rbrack};
+ }
+
+ // slice
+ colon := P.expect(token.COLON);
+ P.expr_lev++;
+ end := P.parseExpression(1);
+ P.expr_lev--;
+ rbrack := P.expect(token.RBRACK);
+ return &ast.Slice{x, index, end, lbrack, colon, rbrack};
}
-func (P *Parser) parseBinaryExpr(prec1 int) ast.Expr
+func (P *Parser) parseCall(fun ast.Expr) *ast.Call {
+ if P.trace {
+ defer un(trace(P, "Call"));
+ }
+
+ lparen := P.expect(token.LPAREN);
+ var args []ast.Expr;
+ if P.tok != token.RPAREN {
+ args = P.parseExpressionList();
+ }
+ rparen := P.expect(token.RPAREN);
+ return &ast.Call{fun, args, lparen, rparen};
+}
+
func (P *Parser) parseCompositeElements(close int) ast.Expr {
x := P.parseExpression(0);
@@ -912,7 +948,7 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
// first element determines mode
singles := true;
- if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON {
+ if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
singles = false;
}
@@ -921,20 +957,20 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
y := P.parseExpression(0);
if singles {
- if t, is_binary := y.(*ast.BinaryExpr); is_binary && t.Tok == token.COLON {
- P.error(t.X.Loc(), "single value expected; found pair");
+ if t, is_binary := y.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
+ P.error(t.X.Pos(), "single value expected; found pair");
}
} else {
- if t, is_binary := y.(*ast.BinaryExpr); !is_binary || t.Tok != token.COLON {
- P.error(y.Loc(), "key:value pair expected; found single value");
+ if t, is_binary := y.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
+ P.error(y.Pos(), "key:value pair expected; found single value");
}
}
if last == nil {
- last = &ast.BinaryExpr{loc, token.COMMA, x, y};
+ last = &ast.BinaryExpr{token.COMMA, x, y, loc};
x = last;
} else {
- last.Y = &ast.BinaryExpr{loc, token.COMMA, last.Y, y};
+ last.Y = &ast.BinaryExpr{token.COMMA, last.Y, y, loc};
last = last.Y.(*ast.BinaryExpr);
}
@@ -951,20 +987,64 @@ func (P *Parser) parseCompositeElements(close int) ast.Expr {
}
-func (P *Parser) parseCallOrCompositeLit(f ast.Expr, open, close int) ast.Expr {
+func (P *Parser) parseElementList() []ast.Expr {
if P.trace {
- defer un(trace(P, "CallOrCompositeLit"));
+ defer un(trace(P, "ElementList"));
}
- loc := P.loc;
- P.expect(open);
- var args ast.Expr;
- if P.tok != close {
- args = P.parseCompositeElements(close);
+ list := vector.New(0);
+ singles := true;
+ for P.tok != token.RBRACE {
+ x := P.parseExpression(0);
+ if list.Len() == 0 {
+ // first element determines syntax for remaining elements
+ if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
+ singles = false;
+ }
+ } else {
+ // not the first element - check syntax
+ if singles {
+ if t, is_binary := x.(*ast.BinaryExpr); is_binary && t.Op == token.COLON {
+ P.error(t.X.Pos(), "single value expected; found pair");
+ }
+ } else {
+ if t, is_binary := x.(*ast.BinaryExpr); !is_binary || t.Op != token.COLON {
+ P.error(x.Pos(), "key:value pair expected; found single value");
+ }
+ }
+ }
+
+ list.Push(x);
+
+ if P.tok == token.COMMA {
+ P.next();
+ } else {
+ break;
+ }
+ }
+
+ // convert list
+ elts := make([]ast.Expr, list.Len());
+ for i := 0; i < list.Len(); i++ {
+ elts[i] = list.At(i).(ast.Expr);
+ }
+
+ return elts;
+}
+
+
+func (P *Parser) parseCompositeLit(typ ast.Expr) ast.Expr {
+ if P.trace {
+ defer un(trace(P, "CompositeLit"));
}
- P.expect(close);
- return &ast.Call{loc, open, f, args};
+ lbrace := P.expect(token.LBRACE);
+ var elts []ast.Expr;
+ if P.tok != token.RBRACE {
+ elts = P.parseElementList();
+ }
+ rbrace := P.expect(token.RBRACE);
+ return &ast.CompositeLit{typ, elts, lbrace, rbrace};
}
@@ -976,13 +1056,12 @@ func (P *Parser) parsePrimaryExpr() ast.Expr {
x := P.parseOperand();
for {
switch P.tok {
- case token.PERIOD: x = P.parseSelectorOrTypeGuard(x);
- case token.LBRACK: x = P.parseIndex(x);
- // TODO fix once we have decided on literal/conversion syntax
- case token.LPAREN: x = P.parseCallOrCompositeLit(x, token.LPAREN, token.RPAREN);
+ case token.PERIOD: x = P.parseSelectorOrTypeAssertion(x);
+ case token.LBRACK: x = P.parseIndexOrSlice(x);
+ case token.LPAREN: x = P.parseCall(x);
case token.LBRACE:
if P.expr_lev >= 0 {
- x = P.parseCallOrCompositeLit(x, token.LBRACE, token.RBRACE);
+ x = P.parseCompositeLit(x);
} else {
return x;
}
@@ -1006,17 +1085,7 @@ func (P *Parser) parseUnaryExpr() ast.Expr {
loc, tok := P.loc, P.tok;
P.next();
y := P.parseUnaryExpr();
- return &ast.UnaryExpr{loc, tok, y};
- /*
- if lit, ok := y.(*ast.TypeLit); ok && tok == token.MUL {
- // pointer type
- t := ast.NewType(pos, ast.POINTER);
- t.Elt = lit.Typ;
- return &ast.TypeLit{t};
- } else {
- return &ast.UnaryExpr{loc, tok, y};
- }
- */
+ return &ast.UnaryExpr{tok, y, loc};
}
return P.parsePrimaryExpr();
@@ -1034,7 +1103,7 @@ func (P *Parser) parseBinaryExpr(prec1 int) ast.Expr {
loc, tok := P.loc, P.tok;
P.next();
y := P.parseBinaryExpr(prec + 1);
- x = &ast.BinaryExpr{loc, tok, x, y};
+ x = &ast.BinaryExpr{tok, x, y, loc};
}
}
@@ -1070,7 +1139,6 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
defer un(trace(P, "SimpleStat"));
}
- loc := P.loc;
x := P.parseExpressionList();
switch P.tok {
@@ -1123,8 +1191,8 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
}
default:
- if len(x) != 1 {
- P.error(loc, "only one expression allowed");
+ if len(x) > 1 {
+ P.error(x[0].Pos(), "only one expression allowed");
}
if P.tok == token.INC || P.tok == token.DEC {
@@ -1134,7 +1202,7 @@ func (P *Parser) parseSimpleStat(mode int) ast.Stat {
}
// TODO change ILLEGAL -> NONE
- return &ast.ExpressionStat{loc, token.ILLEGAL, x[0]};
+ return &ast.ExpressionStat{x[0].Pos(), token.ILLEGAL, x[0]};
}
unreachable();
@@ -1267,14 +1335,14 @@ func (P *Parser) asIdent(x ast.Expr) *ast.Ident {
if name, ok := x.(*ast.Ident); ok {
return name;
}
- P.error(x.Loc(), "identifier expected");
- return &ast.Ident{noloc, "BAD"};
+ P.error(x.Pos(), "identifier expected");
+ return &ast.Ident{"BAD", noloc};
}
func (P *Parser) isTypeSwitch(init ast.Stat) (lhs *ast.Ident, rhs ast.Expr) {
if assign, ok := init.(*ast.AssignmentStat); ok {
- if guard, ok := assign.Rhs.(*ast.TypeGuard); ok {
+ if guard, ok := assign.Rhs.(*ast.TypeAssertion); ok {
if tmp, ok := guard.Typ.(*ast.TypeType); ok {
// we appear to have a type switch
// TODO various error checks
@@ -1436,7 +1504,7 @@ func (P *Parser) parseStatement() ast.Stat {
// ----------------------------------------------------------------------------
// Declarations
-func (P *Parser) parseImportSpec(loc scanner.Location) *ast.ImportDecl {
+func (P *Parser) parseImportSpec(loc Position) *ast.ImportDecl {
if P.trace {
defer un(trace(P, "ImportSpec"));
}
@@ -1460,7 +1528,7 @@ func (P *Parser) parseImportSpec(loc scanner.Location) *ast.ImportDecl {
}
-func (P *Parser) parseConstSpec(loc scanner.Location, comment ast.CommentGroup) *ast.ConstDecl {
+func (P *Parser) parseConstSpec(loc Position, comment ast.CommentGroup) *ast.ConstDecl {
if P.trace {
defer un(trace(P, "ConstSpec"));
}
@@ -1477,7 +1545,7 @@ func (P *Parser) parseConstSpec(loc scanner.Location, comment ast.CommentGroup)
}
-func (P *Parser) parseTypeSpec(loc scanner.Location, comment ast.CommentGroup) *ast.TypeDecl {
+func (P *Parser) parseTypeSpec(loc Position, comment ast.CommentGroup) *ast.TypeDecl {
if P.trace {
defer un(trace(P, "TypeSpec"));
}
@@ -1489,7 +1557,7 @@ func (P *Parser) parseTypeSpec(loc scanner.Location, comment ast.CommentGroup) *
}
-func (P *Parser) parseVarSpec(loc scanner.Location, comment ast.CommentGroup) *ast.VarDecl {
+func (P *Parser) parseVarSpec(loc Position, comment ast.CommentGroup) *ast.VarDecl {
if P.trace {
defer un(trace(P, "VarSpec"));
}
@@ -1506,7 +1574,7 @@ func (P *Parser) parseVarSpec(loc scanner.Location, comment ast.CommentGroup) *a
}
-func (P *Parser) parseSpec(loc scanner.Location, comment ast.CommentGroup, keyword int) ast.Decl {
+func (P *Parser) parseSpec(loc Position, comment ast.CommentGroup, keyword int) ast.Decl {
switch keyword {
case token.IMPORT: return P.parseImportSpec(loc);
case token.CONST: return P.parseConstSpec(loc, comment);