public static dynamic EvaluateConstExpr(Node expr, SymTable symTable) { try { switch (expr) { case ConstNode _: return(expr.Value); case CastOperator _: return(EvaluateConstExpr(expr.Childs[0], symTable)); case DesignatorNode _: var temp = symTable.LookUp(expr.Value.ToString()); if (temp is ConstSymbol) { return(((SimpleConstant)(temp as ConstSymbol).Value).Value); } throw new EvaluatorException("Illegal operation"); case BinOpNode _: return(BinaryOps[(Tokenizer.TokenSubType)expr.Value](EvaluateConstExpr(expr.Childs[0], symTable), EvaluateConstExpr(expr.Childs[1], symTable))); case UnOpNode _: return(UnaryOps[(Tokenizer.TokenSubType)expr.Value](EvaluateConstExpr(expr.Childs[0], symTable))); } } catch (RuntimeBinderException) { throw new ParserException("Invalid operation in constant expression", expr.Line, expr.Position); } throw new InvalidOperationException($"Node of type {expr.GetType()} met in expression"); }
private Parameters ParseValueParameter(SymTable symTable) { List <string> idents = new List <string>(); while (Current.SubType == Identifier) { idents.Add(Current.Value.ToString()); Next(); if (Current.SubType != Comma) { break; } Next(); } Require(Colon); var t = Current; Require(Identifier); var tp = symTable.LookUp(t.Value.ToString()); if (!(tp is TypeSymbol)) { throw new ParserException("Illegal type declaration", t.Line, t.Position); } if (Current.SubType == Equal) { if (idents.Count != 1) { throw new ParserException("Only one parameter can have default value", Current.Line, Current.Position); } Require(Equal); var v = ParseConstExpr(symTable); var s = new ParameterSymbol { Name = idents[0], ParameterModifier = ParameterModifier.Value, Type = (TypeSymbol)tp, Value = v }; symTable.Add(idents[0], s); return(new Parameters { s }); } var p = new Parameters(); foreach (var i in idents) { var s = new ParameterSymbol { Name = i, ParameterModifier = ParameterModifier.Value, Type = (TypeSymbol)tp, }; p.Add(s); symTable.Add(i, s); } return(p); }
public override void Generate(AsmCode asmCode, SymTable symTable) { long id = asmCode.CurrentID++; StartLabel = new AsmLabel($"Cycle{id}Start"); EndLabel = new AsmLabel($"Cycle{id}End"); AsmLabel bodyLabel = new AsmLabel($"Cycle{id}Body"); var v = (VarSymbol)symTable.LookUp(Childs[0].Value.ToString()); Childs[1].Generate(asmCode, symTable); // Initial value ((IdentNode)Childs[0]).GenerateLValue(asmCode, symTable); // Cycle counter asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax); asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Ebx); asmCode.Add(AsmCmd.Cmd.Sub, AsmReg.Reg.Ebx, 1); asmCode.Add( AsmCmd.Cmd.Mov, new AsmOffset(0, v.Type.Size, AsmReg.Reg.Eax), AsmReg.Reg.Ebx); // Value initialized asmCode.Add(AsmCmd.Cmd.Jmp, StartLabel); asmCode.Add(bodyLabel); asmCode.LoopStack.Push(this); Childs[3].Generate(asmCode, symTable); // Cycle body asmCode.LoopStack.Pop(); asmCode.Add(StartLabel); ((IdentNode)Childs[0]).GenerateLValue(asmCode, symTable); asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax); asmCode.Add(AsmCmd.Cmd.Inc, new AsmOffset(0, v.Type.Size, AsmReg.Reg.Eax)); Childs[2].Generate(asmCode, symTable); // Cycle counter target ((IdentNode)Childs[0]).GenerateLValue(asmCode, symTable); asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax); asmCode.Add( AsmCmd.Cmd.Mov, AsmReg.Reg.Eax, new AsmOffset(0, v.Type.Size, AsmReg.Reg.Eax)); asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Ebx); asmCode.Add(AsmCmd.Cmd.Cmp, AsmReg.Reg.Eax, AsmReg.Reg.Ebx); asmCode.Add(AsmCmd.Cmd.Jle, bodyLabel); asmCode.Add(EndLabel); }
private DesignatorNode ParseDesignator(SymTable symTable) { var c = Current; Require(Identifier); var t = symTable.LookUp(c.Value.ToString()); switch (t) { case TypeSymbol ts: return(ParseCast(symTable, new IdentNode(null, c) { Type = ts })); case ProcedureSymbol ps: return(ParseProcedureCall(symTable, new IdentNode(null, c) { Type = ps })); case FunctionSymbol fs: return(ParseFunctionCall(symTable, new IdentNode(null, c) { Type = fs })); case ValueSymbol vs: DesignatorNode v = new IdentNode(null, c) { Type = vs.Type }; switch (vs.Type) { case RecordTypeSymbol _: return(ParseMemberAccess(symTable, v)); case ArrayTypeSymbol _: return(ParseIndex(symTable, v)); } return(v); default: throw new ParserException("Illegal identifier", c.Line, c.Position); } }
private PascalProgram ParseProgram() { var c = Current; string name = ""; if (c.SubType == Tokenizer.TokenSubType.Program) { Next(); var n = Current; Require(Identifier); name = n.Value.ToString(); Require(Semicolon); } SymTable st = new SymTable { { TypeSymbol.IntTypeSymbol.Name, TypeSymbol.IntTypeSymbol }, { TypeSymbol.RealTypeSymbol.Name, TypeSymbol.RealTypeSymbol }, { TypeSymbol.CharTypeSymbol.Name, TypeSymbol.CharTypeSymbol } }; if (st.LookUp(name) != null) { throw new ParserException("Illegal program name", c.Line, c.Position); } ProgramSymbol pn; if (name != "") { pn = new ProgramSymbol { Name = name }; st.Add(name, pn); } else { pn = new ProgramSymbol { Name = "" }; } var b = ParseBlock(st); Require(Dot); return(new PascalProgram { Block = b, Name = pn }); }
private Parameters ParseVarParameter(SymTable symTable) { Require(Var); List <string> idents = new List <string>(); while (Current.SubType == Identifier) { idents.Add(Current.Value.ToString()); Next(); if (Current.SubType != Comma) { break; } Next(); } if (idents.Count == 0) { throw new ParserException("Empty parameter list", Current.Line, Current.Position); } Require(Colon); var t = Current; Require(Identifier); var tp = symTable.LookUp(t.Value.ToString()); if (!(tp is TypeSymbol)) { throw new ParserException("Illegal type declaration", t.Line, t.Position); } var p = new Parameters(); foreach (var i in idents) { var s = new ParameterSymbol { Name = i, ParameterModifier = ParameterModifier.Var, Type = (TypeSymbol)tp }; p.Add(s); symTable.Add(i, s); } return(p); }
private TypeSymbol ParseType(SymTable symTable) { var c = Current; switch (c.SubType) { case Identifier: Next(); var t = symTable.LookUp(c.Value.ToString()); if (!(t is TypeSymbol)) { throw new ParserException("Error in type definition", c.Line, c.Position); } return((TypeSymbol)t); case Tokenizer.TokenSubType.Array: return(ParseArrayType(symTable)); case Record: return(ParseRecordType(symTable)); } throw new ParserException($"Expected type, found '{c.SubType}'", c.Line, c.Position); }
private ExpressionNode ParseFactor(SymTable symTable) { var c = Current; switch (c.SubType) { case Identifier: Next(); var t = symTable.LookUp(c.Value.ToString()); switch (t) { case TypeSymbol ts: return(ParseCast(symTable, new IdentNode(null, c) { Type = ts })); case FunctionSymbol fs: return(ParseFunctionCall(symTable, new IdentNode(null, c) { Type = fs })); case ValueSymbol vs: DesignatorNode v = new IdentNode(null, c) { Type = vs.Type }; switch (vs.Type) { case RecordTypeSymbol _: return(ParseMemberAccess(symTable, v)); case ArrayTypeSymbol _: return(ParseIndex(symTable, v)); } return(v); default: throw new ParserException("Illegal identifier", c.Line, c.Position); } case IntegerConstant: Next(); return(new ConstNode(null, c.Value, c.Line, c.Position) { Type = TypeSymbol.IntTypeSymbol }); case FloatConstant: Next(); return(new ConstNode(null, c.Value, c.Line, c.Position) { Type = TypeSymbol.RealTypeSymbol }); case LParenthesis: Next(); var e = ParseExpression(symTable); Require(RParenthesis); return(e); case Plus: case Minus: { Next(); var tmp = ParseFactor(symTable); return(new UnOpNode(new List <Node> { tmp }, c.SubType, c.Line, c.Position) { Type = tmp.Type }); } case Not: { Next(); var tmp = ParseFactor(symTable); if (tmp.Type == TypeSymbol.IntTypeSymbol) { return(new UnOpNode(new List <Node> { tmp }, c.SubType, c.Line, c.Position) { Type = tmp.Type }); } throw new ParserException("Illegal operation", c.Line, c.Position); } } throw new ParserException($"Unexpected token {c.SubType}", c.Line, c.Position); }