Exemplo n.º 1
0
        private void Generate(ITree node, Context context)
        {
            int tempLabIndex;

            switch (node.Type)
            {
            case AstNodeType.VARS:
            case AstNodeType.VAR:
                int tmp = (node.GetChild(1) as AstNode).ODataType.ArrayCount;
                if (tmp > 0)
                {
                    for (int i = 0; i < tmp; i++)
                    {
                        msil.Append(string.Format("    ldc.i4.s {0}\n", (node.GetChild(1) as AstNode).ODataType.ALength));
                    }
                    if (tmp == 1)
                    {
                        msil.Append(string.Format("    newarr [mscorlib]System.{0}\n", ReturnConvertType(context.Idents[node.GetChild(0).Text].DataType.SimpleDataType)));
                    }
                    else
                    {
                        msil.Append(string.Format("    newobj instance void {0}", ReturnType(context.Idents[node.GetChild(0).Text].DataType.SimpleDataType)));
                        MsilArray(tmp);
                        msil.Append(string.Format("\n"));
                    }
                    msil.Append(string.Format("    stloc.s {0}\n", context.Idents[node.GetChild(0).Text].Index));
                }
                break;

            case AstNodeType.ARRAYPART:
                Generate((AstNode)node.GetChild(0), context);
                for (int i = 1; i < node.ChildCount; i++)
                {
                    Generate((AstNode)node.GetChild(i), context);
                }
                if (node.ChildCount == 2)
                {
                    msil.Append(string.Format("    ldelem.i4\n"));
                }
                else
                {
                    string type = ReturnType(context.Idents[node.GetChild(0).Text].DataType.SimpleDataType);
                    msil.Append(string.Format("    call instance {0} {0} ", type));
                    MsilArray(node.ChildCount - 1);
                    msil.Append(string.Format("::Get({0} ", type));
                    for (int i = 0; i < node.ChildCount - 2; i++)
                    {
                        msil.Append(string.Format(",{0}", type));
                    }
                    msil.Append(string.Format(")\n", type));
                }
                break;

            case AstNodeType.ASSIGN:

                if (node.GetChild(0).Type != AstNodeType.ARRAYPART)
                {
                    Generate(node.GetChild(1), context);
                    msil.Append(string.Format("    stloc.s {0}\n", context.Idents[node.GetChild(0).Text].Index));
                }
                else
                {
                    Generate(node.GetChild(0).GetChild(0), context);
                    for (int i = 1; i < node.ChildCount; i++)
                    {
                        Generate((AstNode)node.GetChild(0).GetChild(i), context);
                    }
                    if (node.ChildCount == 2)
                    {
                        Generate(node.GetChild(1), context);
                        msil.Append(string.Format("    stelem.i4\n"));
                    }
                    else
                    {
                        string type = ReturnType(context.Idents[node.GetChild(0).Text].DataType.SimpleDataType);
                        msil.Append(string.Format("    call instance void {0} ", type));
                        MsilArray(node.ChildCount - 1);
                        msil.Append(string.Format("::Set({0} ", type));
                        for (int i = 0; i < node.ChildCount - 2; i++)
                        {
                            msil.Append(string.Format(",{0}", type));
                        }
                        msil.Append(string.Format(")\n", type));
                    }
                }
                break;

            case AstNodeType.IDENT:
                Ident ident = context.InThisContext(node.Text);    //context.Idents[node.Text];
                if (ident == null)
                {
                    ident = context.ParentContext.InThisContext(node.Text);
                    if (ident != null && context.ParentContext.Function != null)
                    {
                        msil.Append(string.Format("    ldarg.s {0}\n", ident.Index));
                    }
                    break;
                }
                msil.Append(string.Format("    ldloc.s {0}\n", ident.Index));
                break;

            case AstNodeType.NUMBER:
                msil.Append(string.Format("    ldc.i4.s {0}\n", node.Text));
                break;

            case AstNodeType.TRUE:
                msil.Append(string.Format("    ldc.i4.s {0}\n", 1));
                break;

            case AstNodeType.FALSE:
                msil.Append(string.Format("    ldc.i4.s {0}\n", 0));
                break;

            case AstNodeType.STRINGVAL:
                msil.Append(string.Format("    ldstr {0}\n", node.Text));
                break;



            case AstNodeType.FUNC_CALL:
                for (int i = 0; i < node.GetChild(1).ChildCount; i++)
                {
                    Generate(node.GetChild(1).GetChild(i), context);
                }

                msil.Append(string.Format("    call {0} Program::{1}(", ReturnType((node as AstNode).ODataType.SimpleDataType), node.GetChild(0).Text));
                for (int i = 0; i < node.GetChild(1).ChildCount; i++)
                {
                    msil.Append(string.Format("{0}, ", ReturnType((node.GetChild(1).GetChild(i) as AstNode).ODataType.SimpleDataType)));
                }
                msil.Remove(msil.Length - 2, 2);
                msil.Append(string.Format(")\n"));
                break;

            case AstNodeType.FUNC:
                break;

            case AstNodeType.CONVERT:
                Generate((AstNode)node.GetChild(0), context);
                msil.Append(string.Format("    call string [mscorlib]System.Convert::To{0}({1})\n", ReturnConvertType((node as AstNode).ODataType.SimpleDataType),
                                          ReturnType((node.GetChild(0) as AstNode).ODataType.SimpleDataType)));

                break;

            case AstNodeType.ADD:
            case AstNodeType.SUB:
            case AstNodeType.MUL:
            case AstNodeType.DIV:
                string oper = node.Type == AstNodeType.ADD ? "add" :
                              node.Type == AstNodeType.SUB ? "sub" :
                              node.Type == AstNodeType.MUL ? "mul" :
                              node.Type == AstNodeType.DIV ? "div" :
                              "unknown";

                Generate(node.GetChild(0), context);
                Generate(node.GetChild(1), context);
                msil.Append(string.Format("    {0}\n", oper));
                break;

            case AstNodeType.GT:
            case AstNodeType.EQ:
            case AstNodeType.LT:
                oper = node.Type == AstNodeType.GT ? "cgt" :
                       node.Type == AstNodeType.LT ? "clt" :
                       node.Type == AstNodeType.EQ ? "ceq" :
                       "unknown";
                Generate(node.GetChild(0), context);
                Generate(node.GetChild(1), context);
                msil.Append(string.Format("    {0}\n", oper));

                break;

            case AstNodeType.GE:
            case AstNodeType.LE:
            case AstNodeType.NE:
                oper = node.Type == AstNodeType.GE ? "clt" :
                       node.Type == AstNodeType.LE ? "cgt" :
                       node.Type == AstNodeType.NE ? "seq" :
                       "unknown";

                Generate(node.GetChild(0), context);
                Generate(node.GetChild(1), context);
                msil.Append(string.Format("    {0}\n", oper));
                msil.Append(string.Format("    ldc.i4.0 \n"));
                msil.Append(string.Format("    seq\n"));
                break;

            case MathExprLexer.SINCR:
            case MathExprLexer.EINCR:
            case MathExprLexer.SDECR:
            case MathExprLexer.EDECR:
                oper = (node.Type == AstNodeType.SINCR || node.Type == AstNodeType.EINCR) ? "add" :
                       (node.Type == AstNodeType.SDECR || node.Type == AstNodeType.EDECR) ? "sub" :
                       "unknown";
                msil.Append(string.Format("    ldloc.s {0}\n", context.Idents[node.GetChild(0).Text].Index));
                msil.Append(string.Format("    ldc.i4.1 \n"));
                msil.Append(string.Format("    {0}\n", oper));
                msil.Append(string.Format("    stloc.s {0}\n", context.Idents[node.GetChild(0).Text].Index));
                break;

            case AstNodeType.IF:
                tempLabIndex = labIndex;
                labIndex    += 2;
                Generate(node.GetChild(0), context);
                msil.Append(string.Format("    brfalse.s L_{0:X4}\n", tempLabIndex + 1));
                Generate(node.GetChild(1), context);
                msil.Append(string.Format("    br.s L_{0:X4}\n", tempLabIndex + 2));
                msil.Append(string.Format("  L_{0:X4}:\n", tempLabIndex + 1));
                if (node.ChildCount > 2)
                {
                    Generate(node.GetChild(2), context);
                }
                msil.Append(string.Format("  L_{0:X4}:\n", tempLabIndex + 2));
                break;

            case AstNodeType.WHILE:
                tempLabIndex = labIndex;
                labIndex    += 2;
                msil.Append(string.Format("  L_{0:X4}:\n", tempLabIndex + 1));
                Generate(node.GetChild(0), context);
                msil.Append(string.Format("    brfalse.s L_{0:X4}\n", tempLabIndex + 2));
                Generate(node.GetChild(1), context);
                msil.Append(string.Format("    br.s L_{0:X4}\n", tempLabIndex + 1));
                msil.Append(string.Format("  L_{0:X4}:\n", tempLabIndex + 2));
                break;

            case AstNodeType.REPEATE:
                tempLabIndex = labIndex;
                labIndex    += 1;
                msil.Append(string.Format("  L_{0:X4}:\n", tempLabIndex + 1));
                Generate(node.GetChild(0), context);
                Generate(node.GetChild(1), context);
                msil.Append(string.Format("    brtrue.s L_{0:X4}\n", tempLabIndex + 1));
                break;

            case AstNodeType.FOR:
                tempLabIndex = labIndex;
                labIndex    += 2;
                Generate(node.GetChild(1), context);
                msil.Append(string.Format("    stloc.s {0}\n", context.Idents[node.GetChild(0).GetChild(0).Text].Index));
                msil.Append(string.Format("  L_{0:X4}:\n", tempLabIndex + 1));
                msil.Append(string.Format("    ldloc.s {0}\n", context.Idents[node.GetChild(0).GetChild(0).Text].Index));
                Generate(node.GetChild(2), context);
                msil.Append(string.Format("    sub\n"));
                msil.Append(string.Format("    ldc.i4.s {0}\n", 1));
                msil.Append(string.Format("    sub\n"));
                msil.Append(string.Format("    brfalse.s L_{0:X4}\n", tempLabIndex + 2));
                Generate(node.GetChild(3), context);
                msil.Append(string.Format("    ldloc.s {0}\n", context.Idents[node.GetChild(0).GetChild(0).Text].Index));
                msil.Append(string.Format("    ldc.i4.s {0}\n", 1));
                msil.Append(string.Format("    add\n"));
                msil.Append(string.Format("    stloc.s {0}\n", context.Idents[node.GetChild(0).GetChild(0).Text].Index));
                msil.Append(string.Format("    br.s L_{0:X4}\n", tempLabIndex + 1));
                msil.Append(string.Format("  L_{0:X4}:\n", tempLabIndex + 2));
                break;

            case AstNodeType.PRINT:
                Generate(node.GetChild(0), context);
                msil.Append(string.Format("    call void [mscorlib]System.Console::WriteLine(string)\n"));
                msil.Append(string.Format("    nop\n"));
                break;

            case AstNodeType.RETURN:
                Generate((AstNode)node.GetChild(0), context);
                msil.Append(string.Format("    ret\n"));
                break;

            case AstNodeType.BLOCK:
            case AstNodeType.PROGRAM:
                for (int i = 0; i < node.ChildCount; i++)
                {
                    Generate(node.GetChild(i), context);
                }
                break;

            default:
                throw new MSILGeneratorException("Not implemented!");
            }
        }
Exemplo n.º 2
0
        public static OrigDataType Check(AstNode node, Context context)
        {
            switch (node.Type)
            {
            case MathExprLexer.PROGRAM:
            {
                if (context == null)
                {
                    context = new Context(context);
                }
                CheckBlock(node, context);
                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.BLOCK:
            {
                context = new Context(context);
                contexts.Add(context);
                CheckBlock(node, context);
                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.LET:
            case MathExprLexer.VAR:
            {
                List <AstNode> nodes = new List <AstNode>();
                //String str = node.GetChild(1).GetChild(0).Text;
                OrigDataType dataType;
                //OrigDataType dataType = strToDataType(node.GetChild(1).GetChild(0).Text);

                for (int i = 0; i < node.ChildCount; i++)
                {
                    dataType = new OrigDataType(DataType.Void);
                    AstNode tempi = (AstNode)node.GetChild(i);
                    Ident   ident = context.InThisContext(node.GetChild(i).Text);
                    if (ident != null)
                    {
                        throw new ApplicationException(string.Format("Identifier {0} already exists", tempi.Text));
                    }
                    String  typeText = node.Type == MathExprLexer.VAR ? "VARS" : "LETS";
                    AstNode var      = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.VARS, typeText));
                    var.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.IDENT, tempi.Text)));
                    nodes.Add(var);

                    for (int j = 0; j < node.GetChild(i).ChildCount; j++)
                    {
                        AstNode tempj = (AstNode)node.GetChild(i).GetChild(j);
                        if (tempj.Token.Type == MathExprLexer.TYPE && tempj.ChildCount > 0)
                        {
                            dataType.ReturnFromType(tempj);

                            AstNode tempType = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.TYPE, dataTypeToStr(dataType.SimpleDataType)));
                            tempType.ODataType = dataType;

                            var.AddChild(tempType);
                        }
                        if (tempj.Token.Type == MathExprLexer.ASSIGN)
                        {
                            AstNode tempAssign = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.ASSIGN, "="));
                            tempAssign.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.IDENT, tempi.Text)));
                            tempAssign.AddChild(tempj.GetChild(0));
                            nodes.Add(tempAssign);
                            if (dataType.SimpleDataType == DataType.Void)
                            {
                                dataType = Check((AstNode)tempAssign.GetChild(1), context);

                                AstNode tempType = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.TYPE, dataTypeToStr(dataType.SimpleDataType)));
                                tempType.ODataType = dataType;
                                AstNode tempCheckArrayPart = (AstNode)tempj.GetChild(0);
                                //часть массива
                                if (tempCheckArrayPart.Token.Type == MathExprLexer.ARRAY)
                                {
                                    dataType.Check((AstNode)tempAssign.GetChild(1));
                                    AstNode tempTypeArr = (AstNode)tempj.GetChild(0);
                                    tempType.ODataType.ArrayCount = tempTypeArr.ODataType.ArrayCount;
                                }
                                //вызов функции
                                if (tempCheckArrayPart.Token.Type == MathExprLexer.FUNC_CALL)
                                {
                                    Check((AstNode)tempAssign.GetChild(1), context);
                                    tempType.ODataType = (tempAssign.GetChild(1) as AstNode).ODataType;
                                }


                                var.AddChild(tempType);
                                crutch++;
                            }
                        }
                    }

                    string name = nodes[i + i].GetChild(0).Text;
                    context[name] = new Ident(name, context.ParentContext == null ? IdentType.GlobalVar : IdentType.LocalVar, dataType, nodes[i + i], identIndex++);
                }

                Antlr.Runtime.Tree.CommonTree tree = new Antlr.Runtime.Tree.CommonTree();
                foreach (AstNode n in nodes)
                {
                    tree.AddChild(n);
                }
                node.Parent.ReplaceChildren(node.ChildIndex, node.ChildIndex, tree);

                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.VARS:
            case MathExprLexer.PARAMS: return(new OrigDataType(DataType.Void));

            case MathExprLexer.FUNC:
            {
                OrigDataType dataType = new OrigDataType(strToDataType(node.GetChild(2).GetChild(0).Text));
                string       name     = node.GetChild(0).Text;
                Ident        ident    = context[name];
                if (ident != null)
                {
                    throw new ApplicationException(string.Format("Identifier {0} already exists", name));
                }
                Ident func = new Ident(name, IdentType.Function, dataType, node, identIndex++);
                context[name] = func;
                context       = new Context(context);
                contexts.Add(context);
                AstNode _params = (AstNode)node.GetChild(1);
                for (int i = 0; i < _params.ChildCount; i++)
                {
                    OrigDataType paramDataType = new OrigDataType(strToDataType(_params.GetChild(i).GetChild(0).Text));
                    string       paramName     = _params.GetChild(i).Text;
                    if (paramDataType.SimpleDataType == DataType.Void)
                    {
                        throw new ApplicationException(string.Format("In function {0} void param {1}", name, paramName));
                    }
                    context[paramName] = new Ident(paramName, IdentType.Param, paramDataType, (AstNode)_params.GetChild(i), identIndex++);
                }
                context.Function = func;
                if (dataType.SimpleDataType == DataType.Array)
                {
                    dataType.ReturnFromType((AstNode)node.GetChild(2).GetChild(0));
                    dataType.ArrayCount++;
                    AstNode tempType = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.TYPE, dataTypeToStr(dataType.SimpleDataType)));
                    tempType.ODataType = dataType;
                    node.GetChild(2).ReplaceChildren(0, 0, tempType);
                }
                Check((AstNode)node.GetChild(3), context);
                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.CONVERT:
            {
                OrigDataType dataType = new OrigDataType(strToDataType(node.GetChild(1).Text));
                return(dataType);
            }

            case MathExprLexer.FUNC_CALL:
            {
                Ident ident = context[node.GetChild(0).Text];
                node.ODataType = ident.DataType;
                if (ident == null)
                {
                    throw new ApplicationException(string.Format("Unknown identifier {0}", node.GetChild(0).Text));
                }
                if (ident.IdentType != IdentType.Function)
                {
                    throw new ApplicationException(string.Format("Identifier {0} is not function", node.GetChild(0).Text));
                }
                if (node.ChildCount == 2 && node.GetChild(1).ChildCount != ident.Node.GetChild(1).ChildCount)
                {
                    throw new ApplicationException(string.Format("Not equals params count in function {0}", node.GetChild(0).Text));
                }
                for (int i = 0; i < ident.Node.GetChild(1).ChildCount; i++)
                {
                    OrigDataType formalDataType = new OrigDataType(strToDataType(ident.Node.GetChild(1).GetChild(i).GetChild(0).Text));
                    OrigDataType factDataType   = Check((AstNode)node.GetChild(1).GetChild(i), context);
                    if (formalDataType.SimpleDataType != factDataType.SimpleDataType)
                    {
                        if (formalDataType.SimpleDataType == DataType.Double && factDataType.SimpleDataType == DataType.Int)
                        {
                            convert((AstNode)node.GetChild(1).GetChild(i), new OrigDataType(DataType.Double));
                        }
                        else
                        {
                            throw new ApplicationException(string.Format("In function {0} param {1} incopotible types {2} {3}", node.GetChild(0).Text, i, dataTypeToStr(formalDataType.SimpleDataType), dataTypeToStr(factDataType.SimpleDataType)));
                        }
                    }
                }
                return(new OrigDataType(strToDataType(ident.Node.GetChild(2).GetChild(0).Text)));
            }

            case MathExprLexer.IDENT:
            {
                Ident ident = context[node.Text];
                if (ident == null)
                {
                    throw new ApplicationException(string.Format("Unknown identifier {0}", node.Text));
                }
                if (ident.IdentType == IdentType.Function)
                {
                    if (ident.DataType.SimpleDataType == DataType.Void)
                    {
                        throw new ApplicationException(string.Format("Function {0} returns void", ident.Name));
                    }
                    if (ident.Node.GetChild(1).ChildCount > 0)
                    {
                        throw new ApplicationException(string.Format("No params for function {0} call", ident.Name));
                    }
                    AstNode call = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.FUNC_CALL));
                    call.AddChild(node);
                    call.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.PARAMS)));
                    node.Parent.SetChild(node.ChildIndex, call);

                    node.ODataType = ident.DataType;
                    return(node.ODataType);
                }
                else
                {
                    node.ODataType = ident.DataType;
                    return(node.ODataType);
                }
            }

            case MathExprLexer.NUMBER:
            {
                node.ODataType = node.Text.Contains(".") ? new OrigDataType(DataType.Double) : new OrigDataType(DataType.Int);
                return(node.ODataType);
            }

            case MathExprLexer.STRINGVAL:
            {
                node.ODataType.SimpleDataType = DataType.String;
                return(node.ODataType);
            }

            case MathExprLexer.TRUE:
            case MathExprLexer.FALSE:
            {
                node.ODataType.SimpleDataType = DataType.Bool;
                return(node.ODataType);
            }

            case MathExprLexer.ARRAY:
            {
                OrigDataType dataType = new OrigDataType(DataType.Void);

                dataType.ReturnFromValue(node);
                node.ODataType = dataType;
                int tmpArr = dataType.ArrayCount;
                //int type = node.GetChild(0).Type;
                for (int i = 0; i < node.ChildCount; i++)
                {
                    dataType = Check((AstNode)node.GetChild(i), context);
                }

                return(dataType);
            }

            case MathExprLexer.ARRAYPART:
            {
                Ident ident = context[node.GetChild(0).Text];

                OrigDataType dataType = new OrigDataType(ident.DataType.SimpleDataType);
                dataType.ArrayCount = ident.DataType.ArrayCount - node.ChildCount + 1;
                for (int i = 1; i < node.ChildCount; i++)
                {
                    Check((AstNode)node.GetChild(i), context);
                }
                node.ODataType = dataType;
                return(dataType);
            }

            case MathExprLexer.ASSIGN:
            {
                Ident ident = context[node.GetChild(0).Text];
                if (node.GetChild(0).Type == MathExprLexer.ARRAYPART)
                {
                    ident = context[node.GetChild(0).GetChild(0).Text];
                }
                if (ident == null)
                {
                    throw new ApplicationException(string.Format("Unknown identifier {0}", node.GetChild(0).Text));
                }
                if (ident.IdentType == IdentType.Function)
                {
                    throw new ApplicationException(string.Format("Assign to function {0}", node.GetChild(0).Text));
                }


                OrigDataType rightDataType = Check((AstNode)node.GetChild(1), context);
                if (ident.DataType.SimpleDataType == DataType.Void)
                {
                    return(rightDataType);
                }
                //if(ident.OrigDataType == OrigDataType.Void)

                if (ident.DataType.SimpleDataType != rightDataType.SimpleDataType)
                {
                    if (ident.DataType.SimpleDataType == DataType.Double && rightDataType.SimpleDataType == DataType.Int)
                    {
                        convert((AstNode)node.GetChild(1), new OrigDataType(DataType.Double));
                    }
                    else
                    {
                        throw new ApplicationException(string.Format("Assign incopotible types {0} {1}", dataTypeToStr(ident.DataType.SimpleDataType), dataTypeToStr(rightDataType.SimpleDataType)));
                    }
                }


                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.RETURN:
            {
                if (context.Function == null)
                {
                    throw new ApplicationException(string.Format("Return not in function in line {0}", node.Line));
                }

                OrigDataType returnDataType = Check((AstNode)node.GetChild(0), context);
                if (context.Function.DataType.SimpleDataType != returnDataType.SimpleDataType && context.Function.DataType.ArrayCount != returnDataType.ArrayCount)
                {
                    if (context.Function.DataType.SimpleDataType == DataType.Double && returnDataType.SimpleDataType == DataType.Int)
                    {
                        convert((AstNode)node.GetChild(0), new OrigDataType(DataType.Double));
                    }
                    else
                    {
                        throw new ApplicationException(string.Format("Return incopotible types {0} {1}", dataTypeToStr(context.Function.DataType.SimpleDataType), dataTypeToStr(returnDataType.SimpleDataType)));
                    }
                }
                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.SINCR:
            case MathExprLexer.EINCR:
            case MathExprLexer.SDECR:
            case MathExprLexer.EDECR:
            {
                OrigDataType idenDataType = Check((AstNode)node.GetChild(0), context);
                if (idenDataType.SimpleDataType != DataType.Int && idenDataType.SimpleDataType != DataType.Double)
                {
                    throw new ApplicationException(string.Format("In crement condition type is {0}", dataTypeToStr(idenDataType.SimpleDataType)));
                }
                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.ADD:
            case MathExprLexer.SUB:
            case MathExprLexer.MUL:
            case MathExprLexer.DIV:
            case MathExprLexer.GE:
            case MathExprLexer.LE:
            case MathExprLexer.NE:
            case MathExprLexer.EQ:
            case MathExprLexer.GT:
            case MathExprLexer.LT:
            {
                bool compareOperation = true;
                switch (node.Type)
                {
                case MathExprLexer.ADD:
                case MathExprLexer.SUB:
                case MathExprLexer.MUL:
                case MathExprLexer.DIV:
                    compareOperation = false;
                    break;
                }

                OrigDataType leftDataType  = Check((AstNode)node.GetChild(0), context);
                OrigDataType rightDataType = Check((AstNode)node.GetChild(1), context);
                if (leftDataType.SimpleDataType != DataType.Double && leftDataType.SimpleDataType != DataType.Int && leftDataType.SimpleDataType != DataType.Bool)
                {
                    throw new ApplicationException(string.Format("Left operand invalid type for operation {0}, line = {1}, pos = {2}", node.Text, node.Line, node.TokenStartIndex));
                }
                if (rightDataType.SimpleDataType != DataType.Double && rightDataType.SimpleDataType != DataType.Int && leftDataType.SimpleDataType != DataType.Bool)
                {
                    throw new ApplicationException(string.Format("Right operand invalid type for operation {0}, line = {1}, pos = {2}", node.Text, node.Line, node.TokenStartIndex));
                }
                if (leftDataType.SimpleDataType == DataType.Double)
                {
                    if (rightDataType.SimpleDataType == DataType.Int)
                    {
                        convert((AstNode)node.GetChild(1), new OrigDataType(DataType.Double));
                    }
                    node.ODataType = compareOperation ? new OrigDataType(DataType.Bool) : new OrigDataType(DataType.Double);
                    return(node.ODataType);
                }
                if (rightDataType.SimpleDataType == DataType.Double)
                {
                    if (leftDataType.SimpleDataType == DataType.Int)
                    {
                        convert((AstNode)node.GetChild(0), new OrigDataType(DataType.Double));
                    }
                    node.ODataType = compareOperation ? new OrigDataType(DataType.Bool) : new OrigDataType(DataType.Double);
                    return(node.ODataType);
                }
                node.ODataType = compareOperation ? new OrigDataType(DataType.Bool) : new OrigDataType(DataType.Int);
                return(node.ODataType);
            }

            case MathExprLexer.NOT:
            {
                OrigDataType dataType = Check((AstNode)node.GetChild(0), context);
                if (dataType.SimpleDataType != DataType.Bool)
                {
                    throw new ApplicationException(string.Format("Not operator with type {0}", dataTypeToStr(dataType.SimpleDataType)));
                }
                node.ODataType.SimpleDataType = DataType.Bool;
                return(node.ODataType);
            }

            case MathExprLexer.AND:
            case MathExprLexer.OR:
            {
                OrigDataType leftDataType  = Check((AstNode)node.GetChild(0), context);
                OrigDataType rightDataType = Check((AstNode)node.GetChild(1), context);
                if (leftDataType.SimpleDataType != DataType.Bool && rightDataType.SimpleDataType != DataType.Bool)
                {
                    throw new ApplicationException(string.Format("{0} operator with type {1}, {2}", node.Text, dataTypeToStr(leftDataType.SimpleDataType), dataTypeToStr(rightDataType.SimpleDataType)));
                }
                node.ODataType = new OrigDataType(DataType.Bool);
                return(node.ODataType);
            }

            case MathExprLexer.REPEATE:
            case MathExprLexer.WHILE:
            {
                OrigDataType condDataType = Check((AstNode)node.GetChild(0), context);
                if (condDataType.SimpleDataType != DataType.Bool)
                {
                    throw new ApplicationException(string.Format("In while condition type is {0}", dataTypeToStr(condDataType.SimpleDataType)));
                }
                // context = new Context(context);
                Check((AstNode)node.GetChild(1), context);
                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.IF:
            {
                OrigDataType condDataType = Check((AstNode)node.GetChild(0), context);
                if (condDataType.SimpleDataType != DataType.Bool)
                {
                    throw new ApplicationException(string.Format("In if condition type is {0}", dataTypeToStr(condDataType.SimpleDataType)));
                }
                //context = new Context(context);
                Check((AstNode)node.GetChild(1), context);
                if (node.ChildCount == 3)
                {
                    Check((AstNode)node.GetChild(2), context);
                }
                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.FOR:
            {
                for (int i = 0; i < node.ChildCount - 1; i++)
                {
                    Check((AstNode)node.GetChild(i), context);
                }
                context = new Context(context);
                CheckBlock((AstNode)node.GetChild(node.ChildCount - 1), context);

                OrigDataType condDataType = Check((AstNode)node.GetChild(node.ChildCount - 3), context);
                if (condDataType.SimpleDataType != DataType.Bool)
                {
                    throw new ApplicationException(string.Format("In while condition type is {0}", dataTypeToStr(condDataType.SimpleDataType)));
                }

                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.SWITCH:
            {
                OrigDataType identDataType = Check((AstNode)node.GetChild(0), context);
                for (int i = 1; i < node.ChildCount; i++)
                {
                    AstNode tempi = (AstNode)node.GetChild(i);
                    for (int j = 0; j < tempi.GetChild(0).ChildCount; j++)
                    {
                        if (identDataType.SimpleDataType != Check((AstNode)tempi.GetChild(0).GetChild(j), context).SimpleDataType)
                        {
                            throw new ApplicationException(string.Format("In switch identDataType type is {0}", dataTypeToStr(identDataType.SimpleDataType)));
                        }
                    }
                    context = new Context(context);
                    CheckBlock((AstNode)tempi.GetChild(1), context);
                    //Check((AstNode)node.GetChild(i), context);
                }
                //context = new Context(context);

                return(new OrigDataType(DataType.Void));
            }

            case MathExprLexer.PRINT:
            {
                if (node.ChildCount > 0)
                {
                    Check((AstNode)node.GetChild(0), context);
                    if ((node.GetChild(0) as AstNode).ODataType.SimpleDataType != DataType.String)
                    {
                        convert((AstNode)node.GetChild(0), new OrigDataType(DataType.String));
                    }
                }
                return(new OrigDataType(DataType.String));
            }

            default:
            {
                throw new ApplicationException("Unknown token type");
            }
            }
        }
Exemplo n.º 3
0
        public static DataType Check(AstNode node, Context context)
        {
            switch (node.Type)
            {
                case MathExprLexer.PROGRAM:
                {
                    if (context == null)
                        context = new Context(context);
                    CheckBlock(node, context);
                    return DataType.Void;
                }
                case MathExprLexer.BLOCK:
                {
                    context = new Context(context);
                    CheckBlock(node, context);
                    return DataType.Void;
                }

                case MathExprLexer.VAR: {
                    List<AstNode> nodes = new List<AstNode>();
                    DataType dataType = strToDataType(node.GetChild(0).Text);
                    for (int i = 0; i < node.GetChild(0).ChildCount; i++)
                    {
                        AstNode temp = (AstNode) node.GetChild(0).GetChild(i);
                        if (temp.Token.Type == MathExprLexer.ASSIGN)
                        {
                            Ident ident = context.InThisContext(temp.GetChild(0).Text);
                            if (ident != null)
                                throw new ApplicationException(string.Format("Identifier {0} already exists", temp.GetChild(0).Text));
                            AstNode var = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.VAR, "VAR"));
                            var.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.IDENT, dataTypeToStr(dataType))));
                            var.GetChild(0).AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.IDENT, temp.GetChild(0).Text)));
                            nodes.Add(var);
                            nodes.Add(temp);
                        }
                        else
                        {
                            Ident ident = context.InThisContext(temp.Text);
                            if (ident != null)
                                throw new ApplicationException(string.Format("Identifier {0} already exists", temp.Text));
                            AstNode var = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.VAR, "VAR"));
                            var.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.IDENT, dataTypeToStr(dataType))));
                            var.GetChild(0).AddChild(temp);
                            nodes.Add(var);
                        }
                        string name = nodes[0].GetChild(0).GetChild(0).Text;
                        context[name] = new Ident(name, context.ParentContext == null ? IdentType.GlobalVar : IdentType.LocalVar, dataType, nodes[0]);

                        Antlr.Runtime.Tree.CommonTree tree = new Antlr.Runtime.Tree.CommonTree();
                        foreach (AstNode n in nodes)
                            tree.AddChild(n);
                        node.Parent.ReplaceChildren(node.ChildIndex, node.ChildIndex, tree);
                    }

                    return DataType.Void;
; 
                }

                case MathExprLexer.FUNCTION:
                {
                    DataType dataType = strToDataType(node.GetChild(0).Text);
                    string name = node.GetChild(1).Text;
                    Ident ident = context[name];
                    if (ident != null)
                        throw new ApplicationException(string.Format("Identifier {0} already exists", name));
                    Ident func = new Ident(name, IdentType.Function, dataType, node);
                    context[name] = func;
                    context = new Context(context);
                    AstNode _params = (AstNode) node.GetChild(2);
                    for (int i = 0; i < _params.ChildCount; i++)
                    {
                        DataType paramDataType = strToDataType(_params.GetChild(i).Text);
                        string paramName = _params.GetChild(i).GetChild(0).Text;
                        if (paramDataType == DataType.Void)
                            throw new ApplicationException(string.Format("In function {0} void param {1}", name, paramName));
                        context[paramName] = new Ident(paramName, IdentType.Param, paramDataType, (AstNode) _params.GetChild(i));
                    }
                    context.Function = func;
                    Check((AstNode) node.GetChild(3), context);
                    return DataType.Void;
                }

                case MathExprLexer.CALL:
                {
                    Ident ident = context[node.GetChild(0).Text];
                    if (ident == null)
                        throw new ApplicationException(string.Format("Unknown identifier {0}", node.GetChild(0).Text));
                    if (ident.IdentType != IdentType.Function)
                        throw new ApplicationException(string.Format("Identifier {0} is not function", node.GetChild(0).Text));
                    if (node.GetChild(1).ChildCount != ident.Node.GetChild(2).ChildCount)
                        throw new ApplicationException(string.Format("Not equals params count in function {0}", node.GetChild(0).Text));
                    for (int i = 0; i < ident.Node.GetChild(2).ChildCount; i++) {
                        DataType formalDataType = strToDataType(ident.Node.GetChild(2).GetChild(i).Text);
                        DataType factDataType = Check((AstNode)node.GetChild(1).GetChild(i), context);
                        if (formalDataType != factDataType)
                        {
                            if (formalDataType == DataType.Double && factDataType == DataType.Int)
                                convert((AstNode)node.GetChild(1).GetChild(i), DataType.Double);
                            else
                                throw new ApplicationException(string.Format("In function {0} param {1} incopotible types {2} {3}", node.GetChild(0).Text, i, dataTypeToStr(formalDataType), dataTypeToStr(factDataType)));
                        }
                    }
                    return strToDataType(ident.Node.GetChild(0).Text);
                }

                case MathExprLexer.IDENT:
                {
                    Ident ident = context[node.Text];
                    if (ident == null)
                        throw new ApplicationException(string.Format("Unknown identifier {0}", node.Text));
                    if (ident.IdentType == IdentType.Function)
                    {
                        if (ident.DataType == DataType.Void)
                            throw new ApplicationException(string.Format("Function {0} returns void", ident.Name));
                        if (ident.Node.GetChild(1).ChildCount > 0)
                            throw new ApplicationException(string.Format("No params for function {0} call", ident.Name));
                        AstNode call = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.CALL));
                        call.AddChild(node);
                        call.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.PARAMS)));
                        node.Parent.SetChild(node.ChildIndex, call);

                        node.DataType = ident.DataType;
                        return node.DataType;
                    }
                    else
                    {
                        node.DataType = ident.DataType;
                        return node.DataType;
                    }
                }

                case MathExprLexer.NUMBER:
                {
                    node.DataType = node.Text.Contains(".") ? DataType.Double : DataType.Int;
                    return node.DataType;
                }

                case MathExprLexer.TRUE:
                case MathExprLexer.FALSE:
                {
                    node.DataType = DataType.Bool;
                    return node.DataType;
                }

                case MathExprLexer.ASSIGN:
                {
                    Ident ident = context[node.GetChild(0).Text];
                    if (ident == null)
                        throw new ApplicationException(string.Format("Unknown identifier {0}", node.GetChild(0).Text));
                    if (ident.IdentType == IdentType.Function)
                        throw new ApplicationException(string.Format("Assign to function {0}", node.GetChild(0).Text));
                    DataType rightDataType = Check((AstNode) node.GetChild(1), context);
                    if (ident.DataType != rightDataType)
                    {
                        if (ident.DataType == DataType.Double && rightDataType == DataType.Int)
                            convert((AstNode) node.GetChild(1), DataType.Double);
                        else
                            throw new ApplicationException(string.Format("Assign incopotible types {0} {1}", dataTypeToStr(ident.DataType), dataTypeToStr(rightDataType)));
                    }
                    return DataType.Void;
                }

                case MathExprLexer.RETURN:
                {
                    if (context.Function == null)
                        throw new ApplicationException(string.Format("Return not in function in line {0}", node.Line));

                    DataType returnDataType = Check((AstNode) node.GetChild(0), context);
                    if (context.Function.DataType != returnDataType)
                    {
                        if (context.Function.DataType == DataType.Double && returnDataType == DataType.Int)
                            convert((AstNode) node.GetChild(0), DataType.Double);
                        else
                            throw new ApplicationException(string.Format("Return incopotible types {0} {1}", dataTypeToStr(context.Function.DataType), dataTypeToStr(returnDataType)));
                    }
                    return DataType.Void;
                }

                case MathExprLexer.ADD:
                case MathExprLexer.SUB:
                case MathExprLexer.MUL:
                case MathExprLexer.DIV:
                case MathExprLexer.GE:
                case MathExprLexer.LE:
                case MathExprLexer.NEQUALS:
                case MathExprLexer.EQUALS:
                case MathExprLexer.GT:
                case MathExprLexer.LT:
                {
                    bool compareOperation = true;
                    switch (node.Type) {
                        case MathExprLexer.ADD:
                        case MathExprLexer.SUB:
                        case MathExprLexer.MUL:
                        case MathExprLexer.DIV:
                            compareOperation = false;
                            break;
                    }

                    DataType leftDataType = Check((AstNode) node.GetChild(0), context);
                    DataType rightDataType = Check((AstNode) node.GetChild(1), context);
                    if (leftDataType != DataType.Double && leftDataType != DataType.Int)
                        throw new ApplicationException(string.Format("Left operand invalid type for operation {0}, line = {1}, pos = {2}", node.Text, node.Line, node.TokenStartIndex));
                    if (rightDataType != DataType.Double && rightDataType != DataType.Int)
                        throw new ApplicationException(string.Format("Right operand invalid type for operation {0}, line = {1}, pos = {2}", node.Text, node.Line, node.TokenStartIndex));
                    if (leftDataType == DataType.Double)
                    {
                        if (rightDataType == DataType.Int)
                            convert((AstNode)node.GetChild(1), DataType.Double);
                        node.DataType = compareOperation ? DataType.Bool : DataType.Double;
                        return node.DataType;
                    }
                    if (rightDataType == DataType.Double)
                    {
                        if (leftDataType == DataType.Int)
                            convert((AstNode)node.GetChild(0), DataType.Double);
                        node.DataType = compareOperation ? DataType.Bool : DataType.Double;
                        return node.DataType;
                    }
                    node.DataType = compareOperation ? DataType.Bool : DataType.Int;
                    return node.DataType;
                }

                case MathExprLexer.NOT:
                {
                    DataType dataType = Check((AstNode) node.GetChild(0), context);
                    if (dataType != DataType.Bool)
                        throw new ApplicationException(string.Format("Not operator with type {0}", dataTypeToStr(dataType)));
                    node.DataType = DataType.Bool;
                    return node.DataType;
                }

                case MathExprLexer.AND:
                case MathExprLexer.OR:
                case MathExprLexer.XOR:
                {
                    DataType leftDataType = Check((AstNode) node.GetChild(0), context);
                    DataType rightDataType = Check((AstNode) node.GetChild(1), context);
                    if (leftDataType != DataType.Bool && rightDataType != DataType.Bool)
                        throw new ApplicationException(string.Format("{0} operator with type {1}, {2}", node.Text, dataTypeToStr(leftDataType), dataTypeToStr(rightDataType)));
                    node.DataType = DataType.Bool;
                    return node.DataType;
                }

                case MathExprLexer.WHILE:
                {
                    DataType condDataType = Check((AstNode)node.GetChild(0), context);
                    if (condDataType != DataType.Bool)
                        throw new ApplicationException(string.Format("In while condition type is {0}", dataTypeToStr(condDataType)));
                    // context = new Context(context);
                    Check((AstNode)node.GetChild(1), context);
                    return DataType.Void;
                }

                case MathExprLexer.IF:
                {
                    DataType condDataType = Check((AstNode)node.GetChild(0), context);
                    if (condDataType != DataType.Bool)
                        throw new ApplicationException(string.Format("In if condition type is {0}", dataTypeToStr(condDataType)));
                    // context = new Context(context);
                    Check((AstNode)node.GetChild(1), context);
                    if (node.ChildCount == 3)
                        Check((AstNode)node.GetChild(2), context);
                    return DataType.Void;
                }
                
                case MathExprLexer.FOR:
                {
                    context = new Context(context);
                    CheckBlock((AstNode) node.GetChild(0), context);
                    DataType condDataType = Check((AstNode)node.GetChild(1), context);
                    if (condDataType != DataType.Bool)
                        throw new ApplicationException(string.Format("In while condition type is {0}", dataTypeToStr(condDataType)));
                    CheckBlock((AstNode)node.GetChild(2), context);
                    Check((AstNode)node.GetChild(3), context);
                    return DataType.Void;
                }

                default:
                {
                    throw new ApplicationException("Unknown token type");
                }
                break;
            }
        }
Exemplo n.º 4
0
        public static OrigDataType Check(AstNode node, Context context)
        {
            switch (node.Type)
            {
                case MathExprLexer.PROGRAM:
                    {
                        if (context == null)
                            context = new Context(context);
                        CheckBlock(node, context);
                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.BLOCK:
                    {
                        context = new Context(context);
                        contexts.Add(context);
                        CheckBlock(node, context);
                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.LET:
                case MathExprLexer.VAR:
                    {
                        List<AstNode> nodes = new List<AstNode>();
                        //String str = node.GetChild(1).GetChild(0).Text;
                        OrigDataType dataType;
                        //OrigDataType dataType = strToDataType(node.GetChild(1).GetChild(0).Text);

                        for (int i = 0; i < node.ChildCount; i++)
                        {
                            dataType = new OrigDataType(DataType.Void);
                            AstNode tempi = (AstNode)node.GetChild(i);
                            Ident ident = context.InThisContext(node.GetChild(i).Text);
                            if (ident != null)
                                throw new ApplicationException(string.Format("Identifier {0} already exists", tempi.Text));
                            String typeText = node.Type == MathExprLexer.VAR ? "VARS" : "LETS";
                            AstNode var = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.VARS, typeText));
                            var.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.IDENT, tempi.Text)));
                            nodes.Add(var);

                            for (int j = 0; j < node.GetChild(i).ChildCount; j++)
                            {
                                AstNode tempj = (AstNode)node.GetChild(i).GetChild(j);
                                if (tempj.Token.Type == MathExprLexer.TYPE && tempj.ChildCount > 0)
                                {
                                    dataType.ReturnFromType(tempj);

                                    AstNode tempType = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.TYPE, dataTypeToStr(dataType.SimpleDataType)));
                                    tempType.ODataType = dataType;

                                    var.AddChild(tempType);
                                }
                                if (tempj.Token.Type == MathExprLexer.ASSIGN)
                                {
                                    AstNode tempAssign = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.ASSIGN, "="));
                                    tempAssign.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.IDENT, tempi.Text)));
                                    tempAssign.AddChild(tempj.GetChild(0));
                                    nodes.Add(tempAssign);
                                    if (dataType.SimpleDataType == DataType.Void)
                                    {
                                        dataType = Check((AstNode)tempAssign.GetChild(1), context);

                                        AstNode tempType = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.TYPE, dataTypeToStr(dataType.SimpleDataType)));
                                        tempType.ODataType = dataType;
                                        AstNode tempCheckArrayPart = (AstNode)tempj.GetChild(0);
                                        //часть массива
                                        if (tempCheckArrayPart.Token.Type == MathExprLexer.ARRAY)
                                        {
                                            dataType.Check((AstNode)tempAssign.GetChild(1));
                                            AstNode tempTypeArr = (AstNode)tempj.GetChild(0);
                                            tempType.ODataType.ArrayCount = tempTypeArr.ODataType.ArrayCount;
                                        }
                                        //вызов функции
                                        if (tempCheckArrayPart.Token.Type == MathExprLexer.FUNC_CALL)
                                        {
                                            Check((AstNode)tempAssign.GetChild(1), context);
                                            tempType.ODataType = (tempAssign.GetChild(1) as AstNode).ODataType;
                                        }

                                        var.AddChild(tempType);
                                        crutch++;
                                    }
                                }
                            }

                            string name = nodes[i + i].GetChild(0).Text;
                            context[name] = new Ident(name, context.ParentContext == null ? IdentType.GlobalVar : IdentType.LocalVar, dataType, nodes[i + i], identIndex++);

                        }

                        Antlr.Runtime.Tree.CommonTree tree = new Antlr.Runtime.Tree.CommonTree();
                        foreach (AstNode n in nodes)
                            tree.AddChild(n);
                        node.Parent.ReplaceChildren(node.ChildIndex, node.ChildIndex, tree);

                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.VARS:
                case MathExprLexer.PARAMS: return new OrigDataType(DataType.Void);
                case MathExprLexer.FUNC:
                    {
                        OrigDataType dataType = new OrigDataType(strToDataType(node.GetChild(2).GetChild(0).Text));
                        string name = node.GetChild(0).Text;
                        Ident ident = context[name];
                        if (ident != null)
                            throw new ApplicationException(string.Format("Identifier {0} already exists", name));
                        Ident func = new Ident(name, IdentType.Function, dataType, node, identIndex++);
                        context[name] = func;
                        context = new Context(context);
                        contexts.Add(context);
                        AstNode _params = (AstNode)node.GetChild(1);
                        for (int i = 0; i < _params.ChildCount; i++)
                        {
                            OrigDataType paramDataType = new OrigDataType(strToDataType(_params.GetChild(i).GetChild(0).Text));
                            string paramName = _params.GetChild(i).Text;
                            if (paramDataType.SimpleDataType == DataType.Void)
                                throw new ApplicationException(string.Format("In function {0} void param {1}", name, paramName));
                            context[paramName] = new Ident(paramName, IdentType.Param, paramDataType, (AstNode)_params.GetChild(i), identIndex++);
                        }
                        context.Function = func;
                        if (dataType.SimpleDataType == DataType.Array)
                        {
                            dataType.ReturnFromType((AstNode)node.GetChild(2).GetChild(0));
                            dataType.ArrayCount++;
                            AstNode tempType = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.TYPE, dataTypeToStr(dataType.SimpleDataType)));
                            tempType.ODataType = dataType;
                            node.GetChild(2).ReplaceChildren(0, 0, tempType);
                        }
                        Check((AstNode)node.GetChild(3), context);
                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.CONVERT:
                    {
                        OrigDataType dataType = new OrigDataType(strToDataType(node.GetChild(1).Text));
                        return dataType;
                    }
                case MathExprLexer.FUNC_CALL:
                    {

                        Ident ident = context[node.GetChild(0).Text];
                        node.ODataType = ident.DataType;
                        if (ident == null)
                            throw new ApplicationException(string.Format("Unknown identifier {0}", node.GetChild(0).Text));
                        if (ident.IdentType != IdentType.Function)
                            throw new ApplicationException(string.Format("Identifier {0} is not function", node.GetChild(0).Text));
                        if (node.ChildCount == 2 && node.GetChild(1).ChildCount != ident.Node.GetChild(1).ChildCount)
                            throw new ApplicationException(string.Format("Not equals params count in function {0}", node.GetChild(0).Text));
                        for (int i = 0; i < ident.Node.GetChild(1).ChildCount; i++)
                        {
                            OrigDataType formalDataType = new OrigDataType(strToDataType(ident.Node.GetChild(1).GetChild(i).GetChild(0).Text));
                            OrigDataType factDataType = Check((AstNode)node.GetChild(1).GetChild(i), context);
                            if (formalDataType.SimpleDataType != factDataType.SimpleDataType)
                            {
                                if (formalDataType.SimpleDataType == DataType.Double && factDataType.SimpleDataType == DataType.Int)
                                    convert((AstNode)node.GetChild(1).GetChild(i), new OrigDataType(DataType.Double));
                                else
                                    throw new ApplicationException(string.Format("In function {0} param {1} incopotible types {2} {3}", node.GetChild(0).Text, i, dataTypeToStr(formalDataType.SimpleDataType), dataTypeToStr(factDataType.SimpleDataType)));
                            }
                        }
                        return new OrigDataType(strToDataType(ident.Node.GetChild(2).GetChild(0).Text));
                    }

                case MathExprLexer.IDENT:
                    {
                        Ident ident = context[node.Text];
                        if (ident == null)
                            throw new ApplicationException(string.Format("Unknown identifier {0}", node.Text));
                        if (ident.IdentType == IdentType.Function)
                        {
                            if (ident.DataType.SimpleDataType == DataType.Void)
                                throw new ApplicationException(string.Format("Function {0} returns void", ident.Name));
                            if (ident.Node.GetChild(1).ChildCount > 0)
                                throw new ApplicationException(string.Format("No params for function {0} call", ident.Name));
                            AstNode call = new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.FUNC_CALL));
                            call.AddChild(node);
                            call.AddChild(new AstNode(new Antlr.Runtime.CommonToken(MathExprLexer.PARAMS)));
                            node.Parent.SetChild(node.ChildIndex, call);

                            node.ODataType = ident.DataType;
                            return node.ODataType;
                        }
                        else
                        {
                            node.ODataType = ident.DataType;
                            return node.ODataType;
                        }
                    }

                case MathExprLexer.NUMBER:
                    {
                        node.ODataType = node.Text.Contains(".") ? new OrigDataType(DataType.Double) : new OrigDataType(DataType.Int);
                        return node.ODataType;
                    }

                case MathExprLexer.STRINGVAL:
                    {
                        node.ODataType.SimpleDataType = DataType.String;
                        return node.ODataType;
                    }
                case MathExprLexer.TRUE:
                case MathExprLexer.FALSE:
                    {
                        node.ODataType.SimpleDataType = DataType.Bool;
                        return node.ODataType;
                    }
                case MathExprLexer.ARRAY:
                    {

                        OrigDataType dataType = new OrigDataType(DataType.Void);

                        dataType.ReturnFromValue(node);
                        node.ODataType = dataType;
                        int tmpArr = dataType.ArrayCount;
                        //int type = node.GetChild(0).Type;
                        for (int i = 0; i < node.ChildCount; i++)
                        {
                            dataType = Check((AstNode)node.GetChild(i), context);

                        }

                        return dataType;
                    }
                case MathExprLexer.ARRAYPART:
                    {
                        Ident ident = context[node.GetChild(0).Text];

                        OrigDataType dataType = new OrigDataType(ident.DataType.SimpleDataType);
                        dataType.ArrayCount = ident.DataType.ArrayCount - node.ChildCount + 1;
                        for (int i = 1; i < node.ChildCount; i++)
                        {
                            Check((AstNode)node.GetChild(i), context);
                        }
                        node.ODataType = dataType;
                        return dataType;
                    }
                case MathExprLexer.ASSIGN:
                    {

                        Ident ident = context[node.GetChild(0).Text];
                        if (node.GetChild(0).Type == MathExprLexer.ARRAYPART)
                        {
                            ident = context[node.GetChild(0).GetChild(0).Text];
                        }
                        if (ident == null)
                            throw new ApplicationException(string.Format("Unknown identifier {0}", node.GetChild(0).Text));
                        if (ident.IdentType == IdentType.Function)
                            throw new ApplicationException(string.Format("Assign to function {0}", node.GetChild(0).Text));

                        OrigDataType rightDataType = Check((AstNode)node.GetChild(1), context);
                        if (ident.DataType.SimpleDataType == DataType.Void)
                            return rightDataType;
                        //if(ident.OrigDataType == OrigDataType.Void)

                        if (ident.DataType.SimpleDataType != rightDataType.SimpleDataType)
                        {
                            if (ident.DataType.SimpleDataType == DataType.Double && rightDataType.SimpleDataType == DataType.Int)
                                convert((AstNode)node.GetChild(1), new OrigDataType(DataType.Double));
                            else
                                throw new ApplicationException(string.Format("Assign incopotible types {0} {1}", dataTypeToStr(ident.DataType.SimpleDataType), dataTypeToStr(rightDataType.SimpleDataType)));
                        }

                        return new OrigDataType(DataType.Void);
                    }

                case MathExprLexer.RETURN:
                    {
                        if (context.Function == null)
                            throw new ApplicationException(string.Format("Return not in function in line {0}", node.Line));

                        OrigDataType returnDataType = Check((AstNode)node.GetChild(0), context);
                        if (context.Function.DataType.SimpleDataType != returnDataType.SimpleDataType && context.Function.DataType.ArrayCount != returnDataType.ArrayCount)
                        {
                            if (context.Function.DataType.SimpleDataType == DataType.Double && returnDataType.SimpleDataType == DataType.Int)
                                convert((AstNode)node.GetChild(0), new OrigDataType(DataType.Double));
                            else
                                throw new ApplicationException(string.Format("Return incopotible types {0} {1}", dataTypeToStr(context.Function.DataType.SimpleDataType), dataTypeToStr(returnDataType.SimpleDataType)));
                        }
                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.SINCR:
                case MathExprLexer.EINCR:
                case MathExprLexer.SDECR:
                case MathExprLexer.EDECR:
                    {
                        OrigDataType idenDataType = Check((AstNode)node.GetChild(0), context);
                        if (idenDataType.SimpleDataType != DataType.Int && idenDataType.SimpleDataType != DataType.Double)
                            throw new ApplicationException(string.Format("In crement condition type is {0}", dataTypeToStr(idenDataType.SimpleDataType)));
                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.ADD:
                case MathExprLexer.SUB:
                case MathExprLexer.MUL:
                case MathExprLexer.DIV:
                case MathExprLexer.GE:
                case MathExprLexer.LE:
                case MathExprLexer.NE:
                case MathExprLexer.EQ:
                case MathExprLexer.GT:
                case MathExprLexer.LT:
                    {
                        bool compareOperation = true;
                        switch (node.Type)
                        {
                            case MathExprLexer.ADD:
                            case MathExprLexer.SUB:
                            case MathExprLexer.MUL:
                            case MathExprLexer.DIV:
                                compareOperation = false;
                                break;
                        }

                        OrigDataType leftDataType = Check((AstNode)node.GetChild(0), context);
                        OrigDataType rightDataType = Check((AstNode)node.GetChild(1), context);
                        if (leftDataType.SimpleDataType != DataType.Double && leftDataType.SimpleDataType != DataType.Int && leftDataType.SimpleDataType != DataType.Bool)
                            throw new ApplicationException(string.Format("Left operand invalid type for operation {0}, line = {1}, pos = {2}", node.Text, node.Line, node.TokenStartIndex));
                        if (rightDataType.SimpleDataType != DataType.Double && rightDataType.SimpleDataType != DataType.Int && leftDataType.SimpleDataType != DataType.Bool)
                            throw new ApplicationException(string.Format("Right operand invalid type for operation {0}, line = {1}, pos = {2}", node.Text, node.Line, node.TokenStartIndex));
                        if (leftDataType.SimpleDataType == DataType.Double)
                        {
                            if (rightDataType.SimpleDataType == DataType.Int)
                                convert((AstNode)node.GetChild(1), new OrigDataType(DataType.Double));
                            node.ODataType = compareOperation ? new OrigDataType(DataType.Bool) : new OrigDataType(DataType.Double);
                            return node.ODataType;
                        }
                        if (rightDataType.SimpleDataType == DataType.Double)
                        {
                            if (leftDataType.SimpleDataType == DataType.Int)
                                convert((AstNode)node.GetChild(0), new OrigDataType(DataType.Double));
                            node.ODataType = compareOperation ? new OrigDataType(DataType.Bool) : new OrigDataType(DataType.Double);
                            return node.ODataType;
                        }
                        node.ODataType = compareOperation ? new OrigDataType(DataType.Bool) : new OrigDataType(DataType.Int);
                        return node.ODataType;
                    }

                case MathExprLexer.NOT:
                    {
                        OrigDataType dataType = Check((AstNode)node.GetChild(0), context);
                        if (dataType.SimpleDataType != DataType.Bool)
                            throw new ApplicationException(string.Format("Not operator with type {0}", dataTypeToStr(dataType.SimpleDataType)));
                        node.ODataType.SimpleDataType = DataType.Bool;
                        return node.ODataType;
                    }

                case MathExprLexer.AND:
                case MathExprLexer.OR:
                    {
                        OrigDataType leftDataType = Check((AstNode)node.GetChild(0), context);
                        OrigDataType rightDataType = Check((AstNode)node.GetChild(1), context);
                        if (leftDataType.SimpleDataType != DataType.Bool && rightDataType.SimpleDataType != DataType.Bool)
                            throw new ApplicationException(string.Format("{0} operator with type {1}, {2}", node.Text, dataTypeToStr(leftDataType.SimpleDataType), dataTypeToStr(rightDataType.SimpleDataType)));
                        node.ODataType = new OrigDataType(DataType.Bool);
                        return node.ODataType;
                    }
                case MathExprLexer.REPEATE:
                case MathExprLexer.WHILE:
                    {
                        OrigDataType condDataType = Check((AstNode)node.GetChild(0), context);
                        if (condDataType.SimpleDataType != DataType.Bool)
                            throw new ApplicationException(string.Format("In while condition type is {0}", dataTypeToStr(condDataType.SimpleDataType)));
                        // context = new Context(context);
                        Check((AstNode)node.GetChild(1), context);
                        return new OrigDataType(DataType.Void);
                    }

                case MathExprLexer.IF:
                    {
                        OrigDataType condDataType = Check((AstNode)node.GetChild(0), context);
                        if (condDataType.SimpleDataType != DataType.Bool)
                            throw new ApplicationException(string.Format("In if condition type is {0}", dataTypeToStr(condDataType.SimpleDataType)));
                        //context = new Context(context);
                        Check((AstNode)node.GetChild(1), context);
                        if (node.ChildCount == 3)
                            Check((AstNode)node.GetChild(2), context);
                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.FOR:
                    {

                        for (int i = 0; i < node.ChildCount - 1; i++)
                        {
                            Check((AstNode)node.GetChild(i), context);
                        }
                        context = new Context(context);
                        CheckBlock((AstNode)node.GetChild(node.ChildCount - 1), context);

                        OrigDataType condDataType = Check((AstNode)node.GetChild(node.ChildCount - 3), context);
                        if (condDataType.SimpleDataType != DataType.Bool)
                            throw new ApplicationException(string.Format("In while condition type is {0}", dataTypeToStr(condDataType.SimpleDataType)));

                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.SWITCH:
                    {
                        OrigDataType identDataType = Check((AstNode)node.GetChild(0), context);
                        for (int i = 1; i < node.ChildCount; i++)
                        {
                            AstNode tempi = (AstNode)node.GetChild(i);
                            for (int j = 0; j < tempi.GetChild(0).ChildCount; j++)
                            {
                                if (identDataType.SimpleDataType != Check((AstNode)tempi.GetChild(0).GetChild(j), context).SimpleDataType)
                                    throw new ApplicationException(string.Format("In switch identDataType type is {0}", dataTypeToStr(identDataType.SimpleDataType)));
                            }
                            context = new Context(context);
                            CheckBlock((AstNode)tempi.GetChild(1), context);
                            //Check((AstNode)node.GetChild(i), context);
                        }
                        //context = new Context(context);

                        return new OrigDataType(DataType.Void);
                    }
                case MathExprLexer.PRINT:
                    {
                        if (node.ChildCount > 0)
                        {
                            Check((AstNode)node.GetChild(0), context);
                            if ((node.GetChild(0) as AstNode).ODataType.SimpleDataType != DataType.String)
                            {
                                convert((AstNode)node.GetChild(0), new OrigDataType(DataType.String));
                            }
                        }
                        return new OrigDataType(DataType.String);
                    }
                default:
                    {
                        throw new ApplicationException("Unknown token type");
                    }

            }
        }