/// <summary> /// expression ::= /// operand '=' expression /// operand '+' expression /// operand '-' expression /// operand '*' expression /// operand /// </summary> /// <exception cref="DynException"></exception> public DynAstNodeExpression MatchExpression() { var r = new DynAstNodeExpression(); r.Left = MatchOperand(); var lexeme = PeekLexeme(); switch (lexeme.Token) { case DynToken.SymbolPlus: case DynToken.SymbolMinus: case DynToken.SymbolStar: case DynToken.SymbolEqual: NextLexeme(); r.Operation = lexeme; r.Right = MatchExpression(); break; } return(r); }
/// <summary> /// /// </summary> /// <param name="e"></param> /// <param name="ilg"></param> /// <param name="scope"></param> /// <param name="args"></param> /// <exception cref="DynException"></exception> public void EmitExpression(DynAstNodeExpression e, ILGenerator ilg, Dictionary <string, LocalBuilder> scope, Dictionary <string, int> args) { if (e.Operation is null) { EmitOperand(e.Left, ilg, scope, args); return; } switch (e.Operation.Token) { case DynToken.SymbolEqual: { if (e.Left.Lexeme.Token != DynToken.Identifier) { throw new DynException($"语法错误,赋值操作只可作用于左值。"); } // Right EmitExpression(e.Right, ilg, scope, args); if (GlobalVariables.Contains(e.Left.Lexeme.Identifier)) { ilg.Emit(OpCodes.Stfld, e.Left.Lexeme.Identifier); break; } if (!scope.ContainsKey(e.Left.Lexeme.Identifier)) { LocalBuilder lbt = ilg.DeclareLocal(anyType); scope.Add(e.Left.Lexeme.Identifier, lbt); } LocalBuilder lb = scope[e.Left.Lexeme.Identifier]; ilg.Emit(OpCodes.Stloc, lb.LocalIndex); break; } case DynToken.SymbolPlus: { // Left EmitOperand(e.Left, ilg, scope, args); // Right EmitExpression(e.Right, ilg, scope, args); //ilg.Emit(OpCodes.Add); ilg.Emit(OpCodes.Call, anyType.GetMethod("add_operator")); break; } case DynToken.SymbolMinus: { // Left EmitOperand(e.Left, ilg, scope, args); // Right EmitExpression(e.Right, ilg, scope, args); ilg.Emit(OpCodes.Sub); break; } case DynToken.SymbolStar: { // Left EmitOperand(e.Left, ilg, scope, args); // Right EmitExpression(e.Right, ilg, scope, args); ilg.Emit(OpCodes.Mul); break; } default: throw new DynException($"语法错误,未知的表达式 {e.Operation}"); } }