summaryrefslogtreecommitdiff
path: root/usr/gri/src/parser.go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2008-07-10 18:05:00 -0700
committerRobert Griesemer <gri@golang.org>2008-07-10 18:05:00 -0700
commitfffe52d91f5697404854814b8b5ef9be92617c24 (patch)
tree7cc85a4c5f9655cf6d49c9e8220e232a27fb5437 /usr/gri/src/parser.go
parentd1284ef9f08ad1b342a27b2f5de064b07bb45d03 (diff)
downloadgolang-fffe52d91f5697404854814b8b5ef9be92617c24.tar.gz
- created new dir (gosrc) for go-based front-end
- adjusted makefiles SVN=126763
Diffstat (limited to 'usr/gri/src/parser.go')
-rw-r--r--usr/gri/src/parser.go1058
1 files changed, 0 insertions, 1058 deletions
diff --git a/usr/gri/src/parser.go b/usr/gri/src/parser.go
deleted file mode 100644
index 49b0f6ab2..000000000
--- a/usr/gri/src/parser.go
+++ /dev/null
@@ -1,1058 +0,0 @@
-// Copyright 2009 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package Parser
-
-import Scanner "scanner"
-
-
-export Parser
-type Parser struct {
- verbose, indent int;
- S *Scanner.Scanner;
- tok int; // one token look-ahead
- beg, end int; // token position
- ident string; // last ident seen
-}
-
-
-func (P *Parser) PrintIndent() {
- for i := P.indent; i > 0; i-- {
- print ". ";
- }
-}
-
-
-func (P *Parser) Trace(msg string) {
- if P.verbose > 0 {
- P.PrintIndent();
- print msg, " {\n";
- P.indent++;
- }
-}
-
-
-func (P *Parser) Ecart() {
- if P.verbose > 0 {
- P.indent--;
- P.PrintIndent();
- print "}\n";
- }
-}
-
-
-func (P *Parser) Next() {
- P.tok, P.beg, P.end = P.S.Scan();
- if P.tok == Scanner.IDENT {
- P.ident = P.S.src[P.beg : P.end];
- }
- if P.verbose > 1 {
- P.PrintIndent();
- print Scanner.TokenName(P.tok), "\n";
- }
-}
-
-
-func (P *Parser) Open(S *Scanner.Scanner, verbose int) {
- P.verbose = verbose;
- P.indent = 0;
- P.S = S;
- P.Next();
-}
-
-
-func (P *Parser) Error(pos int, msg string) {
- P.S.Error(pos, msg);
- P.Next(); // make progress
-}
-
-
-func (P *Parser) Expect(tok int) {
- if P.tok == tok {
- P.Next()
- } else {
- P.Error(P.beg, "expected '" + Scanner.TokenName(tok) + "', found '" + Scanner.TokenName(P.tok) + "'");
- }
-}
-
-
-func (P *Parser) Optional(tok int) {
- if P.tok == tok {
- P.Next();
- }
-}
-
-
-func (P *Parser) TryType() bool;
-func (P *Parser) ParseExpression();
-
-
-func (P *Parser) ParseIdent() {
- if P.verbose > 0 {
- P.PrintIndent();
- print "Ident = \"", P.ident, "\"\n";
- }
- P.Expect(Scanner.IDENT);
-}
-
-
-func (P *Parser) ParseIdentList() {
- P.Trace("IdentList");
- P.ParseIdent();
- for P.tok == Scanner.COMMA {
- P.Next();
- P.ParseIdent();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseQualifiedIdent() {
- P.Trace("QualifiedIdent");
- P.ParseIdent();
- if P.tok == Scanner.PERIOD {
- P.Next();
- P.ParseIdent();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseTypeName() {
- P.Trace("TypeName");
- P.ParseQualifiedIdent();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseType() {
- P.Trace("Type");
- if !P.TryType() {
- P.Error(P.beg, "type expected");
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseArrayType() {
- P.Trace("ArrayType");
- P.Expect(Scanner.LBRACK);
- if P.tok != Scanner.RBRACK {
- P.ParseExpression();
- }
- P.Expect(Scanner.RBRACK);
- P.ParseType();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseChannelType() {
- P.Trace("ChannelType");
- P.Expect(Scanner.CHAN);
- switch P.tok {
- case Scanner.LSS: fallthrough
- case Scanner.GTR:
- P.Next();
- }
- P.ParseType();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseParameters();
-func (P *Parser) TryResult() bool;
-
-
-func (P *Parser) ParseMethodDecl() {
- P.Trace("MethodDecl");
- P.ParseIdent();
- P.ParseParameters();
- P.TryResult();
- P.Optional(Scanner.SEMICOLON);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseInterfaceType() {
- P.Trace("InterfaceType");
- P.Expect(Scanner.INTERFACE);
- P.Expect(Scanner.LBRACE);
- for P.tok != Scanner.RBRACE {
- P.ParseMethodDecl();
- }
- P.Next();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseAnonymousSignature();
-
-
-func (P *Parser) ParseFunctionType() {
- P.Trace("FunctionType");
- P.Expect(Scanner.FUNC);
- P.ParseAnonymousSignature();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseMapType() {
- P.Trace("MapType");
- P.Expect(Scanner.MAP);
- P.Expect(Scanner.LBRACK);
- P.ParseType();
- P.Expect(Scanner.RBRACK);
- P.ParseType();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseFieldDecl() {
- P.Trace("FieldDecl");
- P.ParseIdentList();
- P.ParseType();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseStructType() {
- P.Trace("StructType");
- P.Expect(Scanner.STRUCT);
- P.Expect(Scanner.LBRACE);
- for P.tok != Scanner.RBRACE {
- P.ParseFieldDecl();
- if P.tok != Scanner.RBRACE {
- P.Expect(Scanner.SEMICOLON);
- }
- }
- P.Optional(Scanner.SEMICOLON);
- P.Expect(Scanner.RBRACE);
- P.Ecart();
-}
-
-
-func (P *Parser) ParsePointerType() {
- P.Trace("PointerType");
- P.Expect(Scanner.MUL);
- P.ParseType();
- P.Ecart();
-}
-
-
-func (P *Parser) TryType() bool {
- P.Trace("Type (try)");
- switch P.tok {
- case Scanner.IDENT:
- P.ParseTypeName();
- case Scanner.LBRACK:
- P.ParseArrayType();
- case Scanner.CHAN:
- P.ParseChannelType();
- case Scanner.INTERFACE:
- P.ParseInterfaceType();
- case Scanner.FUNC:
- P.ParseFunctionType();
- case Scanner.MAP:
- P.ParseMapType();
- case Scanner.STRUCT:
- P.ParseStructType();
- case Scanner.MUL:
- P.ParsePointerType();
- default:
- P.Ecart();
- return false;
- }
- P.Ecart();
- return true;
-}
-
-
-func (P *Parser) ParseImportSpec() {
- P.Trace("ImportSpec");
- if P.tok == Scanner.PERIOD {
- P.Next();
- } else if P.tok == Scanner.IDENT {
- P.Next();
- }
- P.Expect(Scanner.STRING);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseImportDecl() {
- P.Trace("ImportDecl");
- P.Expect(Scanner.IMPORT);
- if P.tok == Scanner.LPAREN {
- P.Next();
- for P.tok != Scanner.RPAREN {
- P.ParseImportSpec();
- P.Optional(Scanner.SEMICOLON); // TODO this seems wrong
- }
- P.Next();
- } else {
- P.ParseImportSpec();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseExpressionList() {
- P.Trace("ExpressionList");
- P.ParseExpression();
- for P.tok == Scanner.COMMA {
- P.Next();
- P.ParseExpression();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseConstSpec() {
- P.Trace("ConstSpec");
- P.ParseIdent();
- P.TryType();
- if P.tok == Scanner.ASSIGN {
- P.Next();
- P.ParseExpression();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseConstDecl() {
- P.Trace("ConstDecl");
- P.Expect(Scanner.CONST);
- if P.tok == Scanner.LPAREN {
- P.Next();
- for P.tok != Scanner.RPAREN {
- P.ParseConstSpec();
- if P.tok != Scanner.RPAREN {
- P.Expect(Scanner.SEMICOLON);
- }
- }
- P.Next();
- } else {
- P.ParseConstSpec();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseTypeSpec() {
- P.Trace("TypeSpec");
- P.ParseIdent();
- P.TryType();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseTypeDecl() {
- P.Trace("TypeDecl");
- P.Expect(Scanner.TYPE);
- if P.tok == Scanner.LPAREN {
- P.Next();
- for P.tok != Scanner.RPAREN {
- P.ParseTypeSpec();
- if P.tok != Scanner.RPAREN {
- P.Expect(Scanner.SEMICOLON);
- }
- }
- P.Next();
- } else {
- P.ParseTypeSpec();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseVarSpec() {
- P.Trace("VarSpec");
- P.ParseIdentList();
- if P.tok == Scanner.ASSIGN {
- P.Next();
- P.ParseExpressionList();
- } else {
- P.ParseType();
- if P.tok == Scanner.ASSIGN {
- P.Next();
- P.ParseExpressionList();
- }
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseVarDecl() {
- P.Trace("VarDecl");
- P.Expect(Scanner.VAR);
- if P.tok == Scanner.LPAREN {
- P.Next();
- for P.tok != Scanner.RPAREN {
- P.ParseVarSpec();
- if P.tok != Scanner.RPAREN {
- P.Expect(Scanner.SEMICOLON);
- }
- }
- P.Next();
- } else {
- P.ParseVarSpec();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseParameterSection() {
- P.Trace("ParameterSection");
- P.ParseIdentList();
- P.ParseType();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseParameterList() {
- P.Trace("ParameterList");
- P.ParseParameterSection();
- for P.tok == Scanner.COMMA {
- P.Next();
- P.ParseParameterSection();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseParameters() {
- P.Trace("Parameters");
- P.Expect(Scanner.LPAREN);
- if P.tok != Scanner.RPAREN {
- P.ParseParameterList();
- }
- P.Expect(Scanner.RPAREN);
- P.Ecart();
-}
-
-
-func (P *Parser) TryResult() bool {
- P.Trace("Result (try)");
- res := false;
- if P.tok == Scanner.LPAREN {
- // TODO: here we allow empty returns - should proably fix this
- P.ParseParameters();
- res = true;
- } else {
- res = P.TryType();
- }
- P.Ecart();
- return res;
-}
-
-
-// Anonymous signatures
-//
-// (params)
-// (params) type
-// (params) (results)
-// (recv) . (params)
-// (recv) . (params) type
-// (recv) . (params) (results)
-
-func (P *Parser) ParseAnonymousSignature() {
- P.Trace("AnonymousSignature");
- P.ParseParameters();
- if P.tok == Scanner.PERIOD {
- P.Next();
- P.ParseParameters();
- }
- P.TryResult();
- P.Ecart();
-}
-
-
-// Named signatures
-//
-// name (params)
-// name (params) type
-// name (params) (results)
-// (recv) name (params)
-// (recv) name (params) type
-// (recv) name (params) (results)
-
-func (P *Parser) ParseNamedSignature() {
- P.Trace("NamedSignature");
- if P.tok == Scanner.LPAREN {
- P.ParseParameters();
- }
- P.ParseIdent(); // function name
- P.ParseParameters();
- P.TryResult();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseDeclaration();
-func (P *Parser) TryStatement() bool;
-func (P *Parser) ParseStatementList();
-func (P *Parser) ParseBlock();
-func (P *Parser) ParsePrimaryExpr();
-
-
-func (P *Parser) ParsePrimaryExprList() {
- P.Trace("PrimaryExprList");
- P.ParsePrimaryExpr();
- for P.tok == Scanner.COMMA {
- P.Next();
- P.ParsePrimaryExpr();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseBuiltinStat() {
- P.Trace("BuiltinStat");
- P.Expect(Scanner.IDENT);
- P.ParseExpressionList(); // TODO should be optional
- P.Ecart();
-}
-
-
-func (P *Parser) ParseSimpleStat() {
- P.Trace("SimpleStat");
- P.ParseExpression();
- if P.tok == Scanner.COLON {
- P.Next();
- P.Ecart();
- return;
- }
- if P.tok == Scanner.COMMA {
- P.Next();
- P.ParsePrimaryExprList();
- }
- switch P.tok {
- case Scanner.ASSIGN: fallthrough;
- case Scanner.DEFINE: fallthrough;
- case Scanner.ADD_ASSIGN: fallthrough;
- case Scanner.SUB_ASSIGN: fallthrough;
- case Scanner.MUL_ASSIGN: fallthrough;
- case Scanner.QUO_ASSIGN: fallthrough;
- case Scanner.REM_ASSIGN: fallthrough;
- case Scanner.AND_ASSIGN: fallthrough;
- case Scanner.OR_ASSIGN: fallthrough;
- case Scanner.XOR_ASSIGN: fallthrough;
- case Scanner.SHL_ASSIGN: fallthrough;
- case Scanner.SHR_ASSIGN:
- P.Next();
- P.ParseExpressionList();
- case Scanner.INC:
- P.Next();
- case Scanner.DEC:
- P.Next();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseGoStat() {
- P.Trace("GoStat");
- P.Expect(Scanner.GO);
- P.ParseExpression();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseReturnStat() {
- P.Trace("ReturnStat");
- P.Expect(Scanner.RETURN);
- if P.tok != Scanner.SEMICOLON && P.tok != Scanner.RBRACE {
- P.ParseExpressionList();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseControlFlowStat(tok int) {
- P.Trace("ControlFlowStat");
- P.Expect(tok);
- if P.tok == Scanner.IDENT {
- P.ParseIdent();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseStatement() {
- P.Trace("Statement");
- if !P.TryStatement() {
- P.Error(P.beg, "statement expected");
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseIfStat() {
- P.Trace("IfStat");
- P.Expect(Scanner.IF);
- if P.tok != Scanner.LBRACE {
- P.ParseSimpleStat();
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- P.ParseExpression();
- }
- }
- P.ParseBlock();
- if P.tok == Scanner.ELSE {
- P.Next();
- if P.tok == Scanner.IF {
- P.ParseIfStat();
- } else {
- // TODO should be P.ParseBlock()
- P.ParseStatement();
- }
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseForStat() {
- P.Trace("ForStat");
- P.Expect(Scanner.FOR);
- if P.tok != Scanner.LBRACE {
- if P.tok != Scanner.SEMICOLON {
- P.ParseSimpleStat();
- }
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- if P.tok != Scanner.SEMICOLON {
- P.ParseExpression();
- }
- P.Expect(Scanner.SEMICOLON);
- if P.tok != Scanner.LBRACE {
- P.ParseSimpleStat();
- }
- }
- }
- P.ParseBlock();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseCase() {
- P.Trace("Case");
- if P.tok == Scanner.CASE {
- P.Next();
- P.ParseExpressionList();
- } else {
- P.Expect(Scanner.DEFAULT);
- }
- P.Expect(Scanner.COLON);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseCaseList() {
- P.Trace("CaseList");
- P.ParseCase();
- for P.tok == Scanner.CASE || P.tok == Scanner.DEFAULT {
- P.ParseCase();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseCaseClause() {
- P.Trace("CaseClause");
- P.ParseCaseList();
- if P.tok != Scanner.FALLTHROUGH && P.tok != Scanner.RBRACE {
- P.ParseStatementList();
- P.Optional(Scanner.SEMICOLON);
- }
- if P.tok == Scanner.FALLTHROUGH {
- P.Next();
- P.Optional(Scanner.SEMICOLON);
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseSwitchStat() {
- P.Trace("SwitchStat");
- P.Expect(Scanner.SWITCH);
- if P.tok != Scanner.LBRACE {
- P.ParseSimpleStat();
- if P.tok == Scanner.SEMICOLON {
- P.Next();
- P.ParseExpression();
- }
- }
- P.Expect(Scanner.LBRACE);
- for P.tok != Scanner.RBRACE {
- P.ParseCaseClause();
- }
- P.Expect(Scanner.RBRACE);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseCommCase() {
- P.Trace("CommCase");
- if P.tok == Scanner.CASE {
- P.Next();
- if P.tok == Scanner.GTR {
- // send
- P.Next();
- P.ParseExpression();
- P.Expect(Scanner.EQL);
- P.ParseExpression();
- } else {
- // receive
- if P.tok != Scanner.LSS {
- P.ParseIdent();
- P.Expect(Scanner.ASSIGN);
- }
- P.Expect(Scanner.LSS);
- P.ParseExpression();
- }
- } else {
- P.Expect(Scanner.DEFAULT);
- }
- P.Expect(Scanner.COLON);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseCommClause() {
- P.Trace("CommClause");
- P.ParseCommCase();
- if P.tok != Scanner.CASE && P.tok != Scanner.DEFAULT && P.tok != Scanner.RBRACE {
- P.ParseStatementList();
- P.Optional(Scanner.SEMICOLON);
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseRangeStat() bool {
- P.Trace("RangeStat");
- P.Expect(Scanner.RANGE);
- P.ParseIdentList();
- P.Expect(Scanner.DEFINE);
- P.ParseExpression();
- P.ParseBlock();
- P.Ecart();
-}
-
-
-func (P *Parser) ParseSelectStat() bool {
- P.Trace("SelectStat");
- P.Expect(Scanner.SELECT);
- P.Expect(Scanner.LBRACE);
- for P.tok != Scanner.RBRACE {
- P.ParseCommClause();
- }
- P.Next();
- P.Ecart();
-}
-
-
-func (P *Parser) TryStatement() bool {
- P.Trace("Statement (try)");
- indent := P.indent;
- res := true;
- switch P.tok {
- case Scanner.CONST: fallthrough;
- case Scanner.TYPE: fallthrough;
- case Scanner.VAR: fallthrough;
- case Scanner.FUNC:
- P.ParseDeclaration();
- case Scanner.GTR:
- P.ParseSimpleStat(); // send
- case Scanner.IDENT:
- switch P.ident {
- case "print", "panic":
- P.ParseBuiltinStat();
- default:
- P.ParseSimpleStat();
- }
- case Scanner.GO:
- P.ParseGoStat();
- case Scanner.RETURN:
- P.ParseReturnStat();
- case Scanner.BREAK, Scanner.CONTINUE, Scanner.GOTO:
- P.ParseControlFlowStat(P.tok);
- case Scanner.LBRACE:
- P.ParseBlock();
- case Scanner.IF:
- P.ParseIfStat();
- case Scanner.FOR:
- P.ParseForStat();
- case Scanner.SWITCH:
- P.ParseSwitchStat();
- case Scanner.RANGE:
- P.ParseRangeStat();
- case Scanner.SELECT:
- P.ParseSelectStat();
- default:
- // no statement found
- res = false;
- }
- if indent != P.indent {
- panic "imbalanced tracing code"
- }
- P.Ecart();
- return res;
-}
-
-
-func (P *Parser) ParseStatementList() {
- P.Trace("StatementList");
- for P.TryStatement() {
- P.Optional(Scanner.SEMICOLON);
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseBlock() {
- P.Trace("Block");
- P.Expect(Scanner.LBRACE);
- if P.tok != Scanner.RBRACE && P.tok != Scanner.SEMICOLON {
- P.ParseStatementList();
- }
- P.Optional(Scanner.SEMICOLON);
- P.Expect(Scanner.RBRACE);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseFuncDecl() {
- P.Trace("FuncDecl");
- P.Expect(Scanner.FUNC);
- P.ParseNamedSignature();
- if P.tok == Scanner.SEMICOLON {
- // forward declaration
- P.Next();
- } else {
- P.ParseBlock();
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseExportDecl() {
- P.Trace("ExportDecl");
- P.Expect(Scanner.EXPORT);
- if P.tok == Scanner.LPAREN {
- P.Next();
- for P.tok != Scanner.RPAREN {
- P.ParseIdent();
- P.Optional(Scanner.COMMA); // TODO this seems wrong
- }
- P.Next();
- } else {
- P.ParseIdent();
- for P.tok == Scanner.COMMA {
- P.Next();
- P.ParseIdent();
- }
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseDeclaration() {
- P.Trace("Declaration");
- indent := P.indent;
- switch P.tok {
- case Scanner.CONST:
- P.ParseConstDecl();
- case Scanner.TYPE:
- P.ParseTypeDecl();
- case Scanner.VAR:
- P.ParseVarDecl();
- case Scanner.FUNC:
- P.ParseFuncDecl();
- case Scanner.EXPORT:
- P.ParseExportDecl();
- default:
- P.Error(P.beg, "declaration expected");
- }
- if indent != P.indent {
- panic "imbalanced tracing code"
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseNew() {
- P.Trace("New");
- P.Expect(Scanner.NEW);
- P.Expect(Scanner.LPAREN);
- P.ParseType();
- if P.tok == Scanner.COMMA {
- P.Next();
- P.ParseExpressionList()
- }
- P.Expect(Scanner.RPAREN);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseOperand() {
- P.Trace("Operand");
- switch P.tok {
- case Scanner.IDENT:
- P.ParseQualifiedIdent();
- case Scanner.LPAREN:
- P.Next();
- P.ParseExpression();
- P.Expect(Scanner.RPAREN);
- case Scanner.STRING: fallthrough;
- case Scanner.NUMBER: fallthrough;
- case Scanner.NIL: fallthrough;
- case Scanner.IOTA: fallthrough;
- case Scanner.TRUE: fallthrough;
- case Scanner.FALSE:
- P.Next();
- case Scanner.NEW:
- P.ParseNew();
- default:
- P.Error(P.beg, "operand expected");
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseSelectorOrTypeAssertion() {
- P.Trace("SelectorOrTypeAssertion");
- P.Expect(Scanner.PERIOD);
- if P.tok == Scanner.IDENT {
- P.ParseIdent();
- } else {
- P.Expect(Scanner.LPAREN);
- P.ParseType();
- P.Expect(Scanner.RPAREN);
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseIndexOrSlice() {
- P.Trace("IndexOrSlice");
- P.Expect(Scanner.LBRACK);
- P.ParseExpression();
- if P.tok == Scanner.COLON {
- P.Next();
- P.ParseExpression();
- }
- P.Expect(Scanner.RBRACK);
- P.Ecart();
-}
-
-
-func (P *Parser) ParseInvocation() {
- P.Trace("Invocation");
- P.Expect(Scanner.LPAREN);
- if P.tok != Scanner.RPAREN {
- P.ParseExpressionList();
- }
- P.Expect(Scanner.RPAREN);
- P.Ecart();
-}
-
-
-func (P *Parser) ParsePrimaryExpr() {
- P.Trace("PrimaryExpr");
- P.ParseOperand();
- for {
- switch P.tok {
- case Scanner.PERIOD:
- P.ParseSelectorOrTypeAssertion();
- case Scanner.LBRACK:
- P.ParseIndexOrSlice();
- case Scanner.LPAREN:
- P.ParseInvocation();
- default:
- P.Ecart();
- return;
- }
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseUnaryExpr() {
- P.Trace("UnaryExpr");
- switch P.tok {
- case Scanner.ADD: fallthrough;
- case Scanner.SUB: fallthrough;
- case Scanner.NOT: fallthrough;
- case Scanner.XOR: fallthrough;
- case Scanner.LSS: fallthrough;
- case Scanner.GTR: fallthrough;
- case Scanner.MUL: fallthrough;
- case Scanner.AND:
- P.Next();
- P.ParseUnaryExpr();
- P.Ecart();
- return;
- }
- P.ParsePrimaryExpr();
- P.Ecart();
-}
-
-
-func Precedence(tok int) int {
- // TODO should use a map or array here for lookup
- switch tok {
- case Scanner.LOR:
- return 1;
- case Scanner.LAND:
- return 2;
- case Scanner.EQL, Scanner.NEQ, Scanner.LSS, Scanner.LEQ, Scanner.GTR, Scanner.GEQ:
- return 3;
- case Scanner.ADD, Scanner.SUB, Scanner.OR, Scanner.XOR:
- return 4;
- case Scanner.MUL, Scanner.QUO, Scanner.REM, Scanner.SHL, Scanner.SHR, Scanner.AND:
- return 5;
- }
- return 0;
-}
-
-
-func (P *Parser) ParseBinaryExpr(prec1 int) {
- P.Trace("BinaryExpr");
- P.ParseUnaryExpr();
- for prec := Precedence(P.tok); prec >= prec1; prec-- {
- for Precedence(P.tok) == prec {
- P.Next();
- P.ParseBinaryExpr(prec + 1);
- }
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseExpression() {
- P.Trace("Expression");
- indent := P.indent;
- P.ParseBinaryExpr(1);
- if indent != P.indent {
- panic "imbalanced tracing code";
- }
- P.Ecart();
-}
-
-
-func (P *Parser) ParseProgram() {
- P.Trace("Program");
- P.Expect(Scanner.PACKAGE);
- P.ParseIdent();
- for P.tok == Scanner.IMPORT {
- P.ParseImportDecl();
- P.Optional(Scanner.SEMICOLON);
- }
- for P.tok != Scanner.EOF {
- P.ParseDeclaration();
- P.Optional(Scanner.SEMICOLON);
- }
- P.Ecart();
-}