Expr ParseBinaryExpr(bool lhs, int prec1) { Expr x = ParseUnaryExpr(lhs); for (var prec = GetTokenPrecedence(); prec > prec1; prec--) { while (true) { var opprec = GetTokenPrecedence(); if (opprec != prec) { break; } var op = CurrTokenType; var oppos = CurrTokenPos; Next(); ScopeMgr.Resolve(x); var y = ParseBinaryExpr(false, prec + 1); ScopeMgr.Resolve(y); x = new BinaryExpr(x, y, op, oppos); } } return(x); }
List <Expr> ParseRHSList() { var list = ParseExprList(false); foreach (var x in list) { ScopeMgr.Resolve(x); } return(list); }
Stmt ParseClassDecl( ) { List <Ident> memberVar = new List <Ident>(); var defpos = CurrTokenPos; Expect(TokenType.Class); var className = ParseIdent(); var scope = ScopeMgr.OpenClassScope(className.Name, defpos); Ident parentName = null; var colonPos = CurrTokenPos; if (CurrTokenType == TokenType.Colon) { Next(); parentName = ParseIdent(); } Expect(TokenType.LBrace); var decl = new ClassDeclare(className, parentName, scope, memberVar, defpos); if (parentName != null) { decl.ColonPos = colonPos; } className.Symbol = ScopeManager.Declare(decl, ScopeMgr.PackageScope, className.Name, className.DefinePos, SymbolUsage.Class); while (CurrTokenType != TokenType.RBrace) { var param = ParseIdent(); memberVar.Add(param); ScopeManager.Declare(param, scope, param.Name, param.DefinePos, SymbolUsage.Member); } ScopeMgr.CloseScope(); Next(); return(decl); }
void ResolveSelectorElement(Expr x, Ident sel, TokenPos dotpos) { var xident = x as Ident; if (xident == null) { return; } if (xident.Symbol == null) { throw new CompileException(string.Format("{0} not defined", xident.Name), dotpos); } switch (xident.Symbol.Usage) { // 包.函数名 case SymbolUsage.Package: { var pkg = Exe.GetPackageByName(xident.Name); if (pkg == null) { throw new CompileException("package not found: " + xident.Name, dotpos); } // 包必须有一个顶级作用域 if (pkg.TopScope == null) { throw new CompileException("package should have a scope: " + xident.Name, dotpos); } ScopeMgr.Resolve(sel, pkg.TopScope); } break; // 实例.函数名 case SymbolUsage.Variable: case SymbolUsage.Parameter: case SymbolUsage.SelfParameter: { } break; default: throw new CompileException("unknown usage", dotpos); } }
BlockStmt ParseBlockStmt() { var defPos = CurrTokenPos; Expect(TokenType.LBrace); ScopeMgr.OpenScope(ScopeType.Block, defPos); var list = ParseStatmentList(); ScopeMgr.CloseScope(); var rpos = CurrTokenPos; Expect(TokenType.RBrace); return(new BlockStmt(list, defPos, rpos)); }
BlockStmt ParseBody(Scope s) { var lpos = CurrTokenPos; Expect(TokenType.LBrace); ScopeMgr.TopScope = s; var list = ParseStatmentList(); ScopeMgr.CloseScope(); var rpos = CurrTokenPos; Expect(TokenType.RBrace); return(new BlockStmt(list, lpos, rpos)); }
Stmt ParseForStmt() { var defPos = CurrTokenPos; Expect(TokenType.For); var forscope = ScopeMgr.OpenScope(ScopeType.For, defPos); Stmt s1 = null; Stmt s2 = null; Stmt s3 = null; // 可能是foreach if (CurrTokenType != TokenType.SemiColon) { var idents = ParseIdentList(); foreach (var i in idents) { ScopeManager.Declare(i, ScopeMgr.TopScope, i.Name, i.DefinePos, SymbolUsage.Variable); } var opPos = CurrTokenPos; switch (CurrTokenType) { // for numeral case TokenType.Assign: { Next(); var values = ParseRHSList(); var lhs = new List <Expr>(); foreach (var id in idents) { lhs.Add(id); } s1 = new AssignStmt(lhs, values, opPos, TokenType.Assign); } break; // for k, v in x {} case TokenType.In: { Next(); var x = ParseRHS(); var body = ParseBlockStmt(); ScopeMgr.CloseScope(); if (idents.Count != 2) { throw new CompileException("Expect key & value in for-range", CurrTokenPos); } return(new ForRangeStmt(idents[0], idents[1], x, opPos, defPos, forscope, body)); } default: throw new CompileException("Expect '=' or 'in' in for statement", CurrTokenPos); } } // s1和s2之间的分号 Expect(TokenType.SemiColon); if (CurrTokenType != TokenType.SemiColon) { s2 = ParseSimpleStmt(); } // s2和s3之间的分号 Expect(TokenType.SemiColon); if (CurrTokenType != TokenType.LBrace) { s3 = ParseSimpleStmt(); } var body2 = ParseBlockStmt(); ScopeMgr.CloseScope(); Expr condition = null; if (s2 != null) { condition = (s2 as ExprStmt).X[0]; } return(new ForStmt(s1, condition, s3, defPos, forscope, body2)); }
Expr ParseOperand(bool lhs) { var defPos = CurrTokenPos; switch (CurrTokenType) { case TokenType.Identifier: // a = b { var x = ParseIdent(); ScopeMgr.Resolve(x); return(x); } case TokenType.Base: // a= base.foo() { Next(); return(new BaseLit(defPos)); } case TokenType.Number: case TokenType.QuotedString: { var x = new BasicLit(_token.Value, CurrTokenType, CurrTokenPos); Next(); return(x); } case TokenType.LParen: // () 括号表达式 { Next(); var x = ParseExpr(false); var rparenPos = CurrTokenPos; Expect(TokenType.RParen); return(new ParenExpr(x, defPos, rparenPos)); } case TokenType.LBracket: // a = [] 数组初始化 { Next(); List <Expr> values = new List <Expr>(); while (CurrTokenType != TokenType.RBracket && CurrTokenType != TokenType.EOF) { values.Add(ParseOperand(false)); if (CurrTokenType == TokenType.RBracket || CurrTokenType == TokenType.EOF) { break; } Expect(TokenType.Comma); } var rPos = CurrTokenPos; Expect(TokenType.RBracket); return(new ArrayExpr(values, defPos, rPos)); } case TokenType.LBrace: // a = {} Map初始化 { Next(); Dictionary <BasicLit, Expr> mapValues = new Dictionary <BasicLit, Expr>(); while (CurrTokenType != TokenType.RBrace && CurrTokenType != TokenType.EOF) { var key = ParseBasicLit(); Expect(TokenType.Colon); var value = ParseRHS(); mapValues.Add(key, value); if (CurrTokenType == TokenType.RBrace || CurrTokenType == TokenType.EOF) { break; } Expect(TokenType.Comma); } var rPos = CurrTokenPos; Expect(TokenType.RBrace); return(new MapExpr(mapValues, defPos, rPos)); } case TokenType.Func: // a = func( ) {} { Next(); var scope = ScopeMgr.OpenScope(ScopeType.Closure, defPos); var paramlist = ParseParameters(scope, false); var body = ParseBody(scope); var funclit = new FuncLit(body, new FuncType(defPos, paramlist, scope)); return(funclit); } } throw new CompileException("Unknown operand", CurrTokenPos); }
Expr ParsePrimaryExpr(bool lhs) { var x = ParseOperand(lhs); bool parsing = true; int callTimes = 0; while (parsing) { switch (CurrTokenType) { // a.b case TokenType.Dot: { var dotpos = CurrTokenPos; Next(); ScopeMgr.Resolve(x); switch (CurrTokenType) { case TokenType.Identifier: { var sel = ParseIdent(); ResolveSelectorElement(x, sel, dotpos); x = new SelectorExpr(x, sel, dotpos); } break; default: throw new CompileException("expect selector", CurrTokenPos); } } break; // a[index] case TokenType.LBracket: { var lpos = CurrTokenPos; ScopeMgr.Resolve(x); Next(); var index = ParseRHSList(); var rpos = CurrTokenPos; Expect(TokenType.RBracket); x = new IndexExpr(x, index[0], lpos, rpos); } break; case TokenType.LParen: { callTimes++; // 函数调用不能连续, foo()()是不可以的 if (callTimes > 1) { throw new CompileException("invalid call statement", CurrTokenPos); } ScopeMgr.Resolve(x); x = ParseCallExpr(x); } break; default: parsing = false; break; } } return(x); }
Stmt ParseFuncDecl() { var funcPos = CurrTokenPos; Expect(TokenType.Func); var scope = ScopeMgr.OpenScope(ScopeType.Function, funcPos); Ident funcName; Ident className = null; var NameA = ParseIdent(); Scope funcAtScope; if (CurrTokenType == TokenType.Dot) { Next(); funcName = ParseIdent(); className = NameA; funcAtScope = ScopeMgr.GetClassScope(className.Name); // 主定义文件还未出现, 所以暂时创建空的scope if (funcAtScope == null) { funcAtScope = ScopeMgr.OpenClassScope(className.Name, funcPos); ScopeMgr.CloseScope(); } } else { funcAtScope = ScopeMgr.PackageScope; funcName = NameA; } var paramlist = ParseParameters(scope, className != null); if (CurrTokenType == TokenType.LBrace) { var decl = new FuncDeclare(funcName, new FuncType(funcPos, paramlist, scope)); decl.ClassName = className; funcName.Symbol = ScopeManager.Declare(decl, funcAtScope, funcName.Name, funcName.DefinePos, SymbolUsage.Func); decl.Body = ParseBody(scope); decl.BuildRelation(); return(decl); } else { // 声明已经结束 ScopeMgr.CloseScope(); // 函数前置声明 var decl = new DelegateDeclare(funcName, new FuncType(funcPos, paramlist, scope)); funcName.Symbol = ScopeManager.Declare(decl, ScopeMgr.PackageScope, funcName.Name, funcName.DefinePos, SymbolUsage.Delegate); return(decl); } }