コード例 #1
0
        public override void Generate(AsmCode asmCode, SymTable symTable)
        {
            int stackSize = 4;

            if (Childs[0] is ExpressionListNode el)
            {
                foreach (var node in el.Childs.AsEnumerable().Reverse())
                {
                    var child = (ExpressionNode)node;
                    child.Generate(asmCode, symTable);
                    stackSize += ((TypeSymbol)child.Type).Size;
                }
                string fmt = string.Join(
                    " ",
                    el.Childs.Cast <ExpressionNode>().
                    Select(i => _fmtDictionary[(TypeSymbol)i.Type]));
                string val = $"__@string{asmCode.CurrentID++}";
                if (!asmCode.ConstDictionary.ContainsKey(fmt))
                {
                    asmCode.ConstDictionary[fmt] = val;
                }
                asmCode.Add(AsmCmd.Cmd.Push, $"offset {asmCode.ConstDictionary[fmt]}");
            }
            else if (Childs[0] is StringNode sn)
            {
                sn.GenerateLValue(asmCode, symTable);
            }
//            asmCode.Add(AsmCmd.Cmd.And, AsmReg.Reg.Esp, -4);
            asmCode.Add(AsmCmd.Cmd.Call, "crt_printf");
            asmCode.Add(AsmCmd.Cmd.Add, AsmReg.Reg.Esp, stackSize);
        }
コード例 #2
0
        public override void GenerateLValue(AsmCode asmCode, SymTable symTable)
        {
            var       t     = symTable.LookUpLevel(Value.ToString());
            VarSymbol v     = (VarSymbol)t?.Item1;
            int       level = t.Value.Item2;

            asmCode.Add(AsmCmd.Cmd.Mov, AsmReg.Reg.Eax, AsmReg.Reg.Ebp);
            while (level-- > 0)
            {
                asmCode.Add(
                    AsmCmd.Cmd.Mov,
                    AsmReg.Reg.Eax,
                    new AsmOffset(-8, 4, AsmReg.Reg.Eax));
            }
            asmCode.Add(
                AsmCmd.Cmd.Lea,
                AsmReg.Reg.Eax,
                new AsmOffset(v.Offset, 0, AsmReg.Reg.Eax));
            if (v is ParameterSymbol ps &&
                ps.ParameterModifier != ParameterModifier.Value)
            {
                asmCode.Add(
                    AsmCmd.Cmd.Mov,
                    AsmReg.Reg.Eax,
                    new AsmOffset(0, 4, AsmReg.Reg.Eax));
            }
            asmCode.Add(AsmCmd.Cmd.Push, AsmReg.Reg.Eax);
        }
コード例 #3
0
 private static List <Statement> OptimizeStatements(
     List <Statement> statements, SymTable symTable)
 {
     return(OptimizeStatements(statements.Cast <Node>().ToList(), symTable).
            Cast <Statement>().
            ToList());
 }
コード例 #4
0
        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);
        }
コード例 #5
0
        private DesignatorNode ParseMemberAccess(SymTable symTable, DesignatorNode record)
        {
            while (true)
            {
                if (Current.SubType != Dot)
                {
                    return(record);
                }
                Next();
                var rt = (RecordTypeSymbol)record.Type;
                var c  = Current;
                Require(Identifier);
                if (!rt.Fields.Contains(c.Value.ToString()))
                {
                    throw new ParserException("Illegal identifier", c.Line, c.Position);
                }
                var f = new MemberAccessOperator(new List <Node> {
                    record, new IdentNode(null, c)
                }, "Member access",
                                                 c.Line, c.Position)
                {
                    Type = ((VarSymbol)rt.Fields[c.Value.ToString()]).Type
                };
                switch (f.Type)
                {
                case RecordTypeSymbol _:
                    record = f;
                    continue;

                case ArrayTypeSymbol _:
                    return(ParseIndex(symTable, f));
                }
                return(f);
            }
        }
コード例 #6
0
        private ArrayConstant ParseArrayConstant(SymTable symTable, ArrayTypeSymbol arrayType)
        {
            Require(LParenthesis);
            List <Constant> arrayElem =
                new List <Constant> {
                ParseTypedConstant(symTable, arrayType.ElementType)
            };

            while (Current.SubType != RParenthesis)
            {
                Require(Comma);
                arrayElem.Add(ParseTypedConstant(symTable, arrayType.ElementType));
            }
            foreach (var el in arrayElem)
            {
                CheckImplicitTypeCompatibility(el.Type, arrayType.ElementType);
            }
            if (arrayType.Length != arrayElem.Count)
            {
                throw new ParserException("Invalid array length", Current.Line, Current.Position);
            }
            Require(RParenthesis);
            return(new ArrayConstant {
                Elements = arrayElem, Type = arrayType
            });
        }
コード例 #7
0
        private SimpleConstant ParseConstExpr(SymTable symTable)
        {
            var e = ParseExpression(symTable);

            try
            {
                var        t = EvaluateConstExpr(e, symTable);
                TypeSymbol type;
                switch (t)
                {
                case int _:
                    type = TypeSymbol.IntTypeSymbol;
                    break;

                case double _:
                    type = TypeSymbol.RealTypeSymbol;
                    break;

                case char _:
                    type = TypeSymbol.CharTypeSymbol;
                    break;

                default:
                    throw new InvalidOperationException("Const type is invalid");
                }
                return(new SimpleConstant {
                    Value = t, Type = type
                });
            }
            catch (EvaluatorException ex)
            {
                throw new ParserException(ex.Message, Current.Line, Current.Position);
            }
        }
コード例 #8
0
        private RecordConstant ParseRecordConstant(SymTable symTable, RecordTypeSymbol recordType)
        {
            Require(LParenthesis);
            Dictionary <VarSymbol, Constant> recordElem = new Dictionary <VarSymbol, Constant>();

            for (var index = 0;
                 Current.SubType == Identifier && index < recordType.Fields.Count;
                 ++index)
            {
                var i = Current;
                if (((VarSymbol)recordType.Fields[index]).Name != i.Value.ToString())
                {
                    throw new ParserException("Invalid identifier", Current.Line, Current.Position);
                }
                Next();
                Require(Colon);
                var v = ParseTypedConstant(symTable, ((VarSymbol)recordType.Fields[index]).Type);
                CheckImplicitTypeCompatibility(v.Type, ((VarSymbol)recordType.Fields[index]).Type);
                recordElem.Add((VarSymbol)recordType.Fields[index], v);
                if (Current.SubType == RParenthesis)
                {
                    break;
                }
                Require(Semicolon);
            }
            Require(RParenthesis);
            return(new RecordConstant {
                Type = recordType, Values = recordElem
            });
        }
コード例 #9
0
        public override void Generate(AsmCode asmCode, SymTable symTable)
        {
            if (asmCode.SubprogramStack.Count == 0)
            {
                asmCode.Add(AsmCmd.Cmd.Exit);
                return;
            }
            var sp = asmCode.SubprogramStack.Peek();

            switch (sp)
            {
            case FunctionSymbol fs:
                Childs[0].Generate(asmCode, symTable);
                if (fs.ReturnType == TypeSymbol.IntTypeSymbol ||
                    fs.ReturnType == TypeSymbol.CharTypeSymbol)
                {
                    asmCode.Add(AsmCmd.Cmd.Pop, AsmReg.Reg.Eax);
                }
                else if (fs.ReturnType == TypeSymbol.RealTypeSymbol)
                {
                    asmCode.Add(
                        AsmCmd.Cmd.Movsd,
                        AsmReg.Reg.Xmm0,
                        new AsmOffset(0, 8, AsmReg.Reg.Esp));
                    asmCode.Add(AsmCmd.Cmd.Sub, AsmReg.Reg.Esp, 8);
                }
                else
                {
                    throw new NotImplementedException();
                }
                break;
            }
            asmCode.Add(AsmCmd.Cmd.Leave);
            asmCode.Add(AsmCmd.Cmd.Ret, $"{-sp.ParameterOffset - 4}");
        }
コード例 #10
0
        private static List <Node> OptimizeStatements(List <Node> list, SymTable symTable)
        {
            for (var i = 0; i < list.Count; i++)
            {
                FindAndOptimizeExpressions(list[i], symTable);
                switch (list[i])
                {
                case IfStatementNode ifs:
                    OptimizeStatements(ifs.Childs, symTable);
                    list[i] = OptimizeIf(ifs, symTable);
                    break;

                case RepeatStatementNode rs:
                    OptimizeStatements(rs.Childs, symTable);
                    list[i] = OptimizeRepeat(rs, symTable);
                    break;

                case WhileStatementNode ws:
                    OptimizeStatements(ws.Childs, symTable);
                    list[i] = OptimizeWhile(ws, symTable);
                    break;

                case ForStatementNode fs:
                    OptimizeStatements(fs.Childs, symTable);
                    list[i] = OptimizeFor(fs, symTable);
                    break;

                case CompoundStatementNode csn:
                    csn.Statements = OptimizeStatements(csn.Statements, symTable);
                    break;
                }
            }
            return(list);
        }
コード例 #11
0
        private ExpressionNode ParseTerm(SymTable symTable)
        {
            var f = ParseFactor(symTable);
            var c = Current;

            while (MulOps.Contains(c.SubType))
            {
                Next();
                var t = ParseFactor(symTable);
                if (
                    t.Type is ArrayTypeSymbol || t.Type is RecordTypeSymbol ||
                    f.Type is ArrayTypeSymbol || f.Type is RecordTypeSymbol
                    )
                {
                    throw new ParserException("Incompatible types", c.Line, c.Position);
                }
                if (c.SubType == Slash)
                {
                    f = ToType(f, TypeSymbol.RealTypeSymbol);
                }
                (f, t) = SelectType(f, t);
                f      = new BinOpNode(new List <Node> {
                    f, t
                }, c.SubType, c.Line, c.Position)
                {
                    Type = f.Type
                };
                c = Current;
            }
            return(f);
        }
コード例 #12
0
        private ExpressionNode ParseExpression(SymTable symTable)
        {
            var e = ParseSimpleExpression(symTable);
            var c = Current;

            while (RelOps.Contains(c.SubType))
            {
                Next();
                var t = ParseSimpleExpression(symTable);
                if (
                    t.Type is ArrayTypeSymbol || t.Type is RecordTypeSymbol ||
                    e.Type is ArrayTypeSymbol || e.Type is RecordTypeSymbol
                    )
                {
                    throw new ParserException("Incompatible types", c.Line, c.Position);
                }
                (e, t) = SelectType(e, t);
                e      = new BinOpNode(new List <Node> {
                    e, t
                }, c.SubType, c.Line, c.Position)
                {
                    Type = TypeSymbol.IntTypeSymbol
                };
                c = Current;
            }
            return(e);
        }
コード例 #13
0
        private static void FindAndOptimizeExpressions(Node start, SymTable symTable)
        {
            switch (start)
            {
            case RepeatStatementNode rn:
                rn.Condition = OptimizeExpression(
                    (ExpressionNode)rn.Condition, symTable);
                break;

            case WhileStatementNode wn:
                wn.Condition = OptimizeExpression(
                    (ExpressionNode)wn.Condition, symTable);
                break;

            case CompoundStatementNode csn:
                foreach (var statement in csn.Statements)
                {
                    FindAndOptimizeExpressions(statement, symTable);
                }
                break;
            }
            for (var i = 0; i < start.Childs?.Count; i++)
            {
                if (start.Childs[i] is ExpressionNode en)
                {
                    start.Childs[i] = OptimizeExpression(en, symTable);
                }
                else
                {
                    FindAndOptimizeExpressions(start.Childs[i], symTable);
                }
            }
        }
コード例 #14
0
        private DesignatorNode ParseIndex(SymTable symTable, DesignatorNode array)
        {
            while (true)
            {
                if (Current.SubType != LBracket)
                {
                    return(array);
                }
                var ars = (ArrayTypeSymbol)array.Type;
                var p   = ParseIndexParam(symTable);
                CheckImplicitTypeCompatibility((TypeSymbol)p.Type, TypeSymbol.IntTypeSymbol);
                var i = new IndexOperator(new List <Node> {
                    array, p
                }, "Index", p.Line, p.Position)
                {
                    Type = ars.ElementType
                };
                switch (ars.ElementType)
                {
                case RecordTypeSymbol _:
                    return(ParseMemberAccess(symTable, i));

                case ArrayTypeSymbol _:
                    array = i;
                    continue;
                }
                return(i);
            }
        }
コード例 #15
0
        private WriteStatementNode ParseWriteStatement(SymTable symTable)
        {
            var c = Current;

            Require(Write);
            if (Current.SubType != LParenthesis)
            {
                return(new WriteStatementNode(null, "Write", c.Line, c.Position));
            }
            Next();
            if (Current.SubType == StringConstant)
            {
                var s = Current;
                Next();
                Require(RParenthesis);
                return(new WriteStatementNode(new List <Node> {
                    new StringNode(null, s)
                }, "Write", c.Line,
                                              c.Position));
            }
            var e = ParseExpressionList(symTable);

            Require(RParenthesis);
            return(new WriteStatementNode(new List <Node> {
                e
            }, "Write", c.Line, c.Position));
        }
コード例 #16
0
        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");
        }
コード例 #17
0
        private Statement ParseExitStatement(SymTable symTable)
        {
            var c = Current;

            Require(Exit);
            if (Current.SubType != LParenthesis)
            {
                return(new ExitNode(null, c.Value, c.Line, c.Position));
            }
            Next();
            if (Current.SubType == RParenthesis)
            {
                Next();
                return(new ExitNode(null, c.Value, c.Line, c.Position));
            }
            if (CurrentReturnType == null)
            {
                throw new ParserException("Procedures cannot return a value", Current.Line, Current.Position);
            }
            var e = ParseExpression(symTable);

            Require(RParenthesis);
            CheckImplicitTypeCompatibility((TypeSymbol)e.Type, CurrentReturnType);
            return(new ExitNode(new List <Node> {
                e
            }, c.Value, c.Line, c.Position));
        }
コード例 #18
0
        private void ParseFunctionDecl(SymTable symTable)
        {
            var      c            = Current;
            SymTable procSymTable = new SymTable {
                Parent = symTable
            };
            var h = ParseFunctionHeading(procSymTable);

            Require(Semicolon);
            if (symTable.Contains(h.Name))
            {
                throw new ParserException("Duplicate identifier {h.Name}", c.Line, c.Position);
            }
            var f = new FunctionSymbol
            {
                Name       = h.Name,
                Parameters = h.Parameters,
                ReturnType = h.ReturnType
            };

            symTable.Add(h.Name, f);
            var backup = CurrentReturnType;

            CurrentReturnType = f.ReturnType;
            var b = ParseBlock(procSymTable);

            CurrentReturnType = backup;
            Require(Semicolon);
            f.Block = b;
        }
コード例 #19
0
        private void ParseDeclSection(SymTable symTable)
        {
            while (true)
            {
                switch (Current.SubType)
                {
                case Const:
                    ParseConstSection(symTable);
                    break;

                case Var:
                    ParseVarSection(symTable);
                    break;

                case Tokenizer.TokenSubType.Type:
                    ParseTypeSection(symTable);
                    break;

                case Procedure:
                    ParseProcedureDecl(symTable);
                    break;

                case Function:
                    ParseFunctionDecl(symTable);
                    break;

                default:
                    return;
                }
            }
        }
コード例 #20
0
        private void ParseProcedureDecl(SymTable symTable)
        {
            var      c            = Current;
            SymTable procSymTable = new SymTable {
                Parent = symTable
            };
            var h = ParseProcedureHeading(procSymTable);

            Require(Semicolon);
            if (symTable.Contains(h.Name))
            {
                throw new ParserException($"Duplicate identifier {h.Name}", c.Line, c.Position);
            }
            var p = new ProcedureSymbol {
                Name = h.Name, Parameters = h.Parameters
            };

            symTable.Add(h.Name, p);
            var backup = CurrentReturnType;

            CurrentReturnType = null;
            var b = ParseBlock(procSymTable);

            CurrentReturnType = backup;
            p.Block           = b;
            Require(Semicolon);
        }
コード例 #21
0
 public override void Generate(AsmCode asmCode, SymTable symTable)
 {
     if (Type == TypeSymbol.IntTypeSymbol)
     {
         asmCode.Add(AsmCmd.Cmd.Push, Value.ToString());
     }
     else if (Type == TypeSymbol.CharTypeSymbol)
     {
         asmCode.Add(AsmCmd.Cmd.Push, Convert.ToInt32(Value).ToString());
     }
     else if (Type == TypeSymbol.RealTypeSymbol)
     {
         string val = $"__@real{HexConverter.DoubleToHexString((double) Value)}";
         if (!asmCode.ConstDictionary.ContainsKey(Value))
         {
             asmCode.ConstDictionary[Value] = val;
         }
         asmCode.Add(AsmCmd.Cmd.Sub, AsmReg.Reg.Esp, 8);
         asmCode.Add(
             AsmCmd.Cmd.Movsd,
             AsmReg.Reg.Xmm0,
             asmCode.ConstDictionary[Value]);
         asmCode.Add(
             AsmCmd.Cmd.Movsd,
             new AsmOffset(0, 8, AsmReg.Reg.Esp),
             AsmReg.Reg.Xmm0);
     }
 }
コード例 #22
0
        private void ParseFieldDecl(SymTable parentSymTable, SymTable recSymTable)
        {
            var c = Current;

            Require(Identifier);
            List <string> idents = new List <string> {
                c.Value.ToString()
            };
            var t = Current;

            while (t.SubType == Comma)
            {
                Next();
                t = Current;
                Require(Identifier);
                idents.Add(t.Value.ToString());
            }
            Require(Colon);
            var tp = ParseType(parentSymTable);

            foreach (var i in idents)
            {
                if (recSymTable.Contains(i))
                {
                    throw new ParserException($"Field {i} already declared", c.Line, c.Position);
                }
                recSymTable.Add(i, new VarSymbol {
                    Name = i, Type = tp, Value = null
                });
            }
        }
コード例 #23
0
        private void ParseTypeDecl(SymTable symTable)
        {
            var c = Current;

            Require(Identifier);
            Require(Equal);
            var t = ParseType(symTable);

            switch (t)
            {
            case ArrayTypeSymbol at:
                at.Name = c.Value.ToString();
                symTable.Add(at.Name, at);
                break;

            case RecordTypeSymbol rt:
                rt.Name = c.Value.ToString();
                symTable.Add(rt.Name, rt);
                break;

            default:
                symTable.Add(c.Value.ToString(), t);
                break;
            }
        }
コード例 #24
0
        private ExpressionNode ParseCastParam(SymTable symTable)
        {
            Require(LParenthesis);
            var t = ParseExpression(symTable);

            Require(RParenthesis);
            return(t);
        }
コード例 #25
0
        private ExpressionNode ParseIndexParam(SymTable symTable)
        {
            Require(LBracket);
            var t = ParseExpression(symTable);

            Require(RBracket);
            return(t);
        }
コード例 #26
0
 private Block ParseBlock(SymTable symTable)
 {
     if (Current.SubType != Begin)
     {
         ParseDeclSection(symTable);
     }
     return(new Block {
         StatementList = ParseCompoundStatement(symTable).Statements, SymTable = symTable
     });
 }
コード例 #27
0
        public void GenerateLValue(AsmCode asmCode, SymTable symTable)
        {
            string val = $"__@string{asmCode.CurrentID++}";

            if (!asmCode.ConstDictionary.ContainsKey(Value))
            {
                asmCode.ConstDictionary[Value] = val;
            }
            asmCode.Add(AsmCmd.Cmd.Push, $"offset {asmCode.ConstDictionary[Value]}");
        }
コード例 #28
0
 private void ParseTypeSection(SymTable symTable)
 {
     Require(Tokenizer.TokenSubType.Type);
     ParseTypeDecl(symTable);
     Require(Semicolon);
     while (Current.SubType == Identifier)
     {
         ParseTypeDecl(symTable);
         Require(Semicolon);
     }
 }
コード例 #29
0
        private Parameters ParseConstParameter(SymTable symTable)
        {
            Require(Const);
            var p = ParseValueParameter(symTable);

            foreach (ParameterSymbol ps in p)
            {
                ps.ParameterModifier = ParameterModifier.Const;
            }
            return(p);
        }
コード例 #30
0
        private DesignatorNode ParseProcedureCall(SymTable symTable, DesignatorNode procedure)
        {
            var ps = (ProcedureSymbol)procedure.Type;
            var p  = ParseActualParameters(symTable);

            CheckParameters(ps.Parameters, p);
            return(new CallOperator(p.Childs, "Call", p.Line, p.Position)
            {
                Subprogram = ps
            });
        }