コード例 #1
0
ファイル: Message.cs プロジェクト: fronx/ioke
        public static IokeObject FromTree(Runtime runtime, ITree tree)
        {
            //             Console.Error.WriteLine(" fromTree(" + tree.ToStringTree() + ")");
            Message m = null;
            int argStart = 0;

            if(!tree.IsNil) {
                switch(tree.Type) {
                case iokeParser.RegexpLiteral: {
                    string s = tree.Text;
                    char first = s[0];
                    char second = s[1];
                    char last = s[s.Length-1];
                    if(first == '#' && last != '{') {
                        if(second == 'r') {
                            int lastIndex = s.LastIndexOf(']');
                            m = new Message(runtime, "internal:createRegexp", s.Substring(3, lastIndex-3));
                            m.arguments.Add(s.Substring(lastIndex+1));
                        } else {
                            int lastIndex = s.LastIndexOf('/');
                            m = new Message(runtime, "internal:createRegexp", s.Substring(2, lastIndex-2));
                            m.arguments.Add(s.Substring(lastIndex+1));
                        }
                        m.Line = tree.Line;
                        m.Position = tree.CharPositionInLine;
                        return runtime.CreateMessage(m);
                    } else if(first == '}' && last == '{') {
                        m = new Message(runtime, "internal:createText", s.Substring(1, s.Length-3), Type.MIDDLE_RE_INTERPOLATION);
                        m.Line = tree.Line;
                        m.Position = tree.CharPositionInLine;
                        return runtime.CreateMessage(m);
                    } else if(first == '}') {
                        int lastIndex = s.LastIndexOf('/');
                        if(lastIndex == -1) {
                            lastIndex = s.LastIndexOf(']');
                        }
                        m = new Message(runtime, "internal:createText", s.Substring(1, lastIndex-1), Type.END_RE_INTERPOLATION);
                        m.arguments.Add(s.Substring(lastIndex+1));
                        m.Line = tree.Line;
                        m.Position = tree.CharPositionInLine;
                        return runtime.CreateMessage(m);
                    } else {
                        m = new Message(runtime, "internal:createText", s.Substring(2, s.Length-4), Type.START_RE_INTERPOLATION);
                        m.Line = tree.Line;
                        m.Position = tree.CharPositionInLine;
                        return runtime.CreateMessage(m);
                    }
                }
                case iokeParser.StringLiteral: {
                    string s = tree.Text;
                    char first = s[0];
                    char last = s[s.Length-1];
                    if(first == '"' && last == '"') {
                        m = new Message(runtime, "internal:createText", s.Substring(1, s.Length-2));
                        m.Line = tree.Line;
                        m.Position = tree.CharPositionInLine;
                        return runtime.CreateMessage(m);
                    } else if(first == '#' && last == ']') {
                        m = new Message(runtime, "internal:createText", s.Substring(2, s.Length-3));
                        m.Line = tree.Line;
                        m.Position = tree.CharPositionInLine;
                        return runtime.CreateMessage(m);
                    } else {
                        if(first == '}' && (last == '"' || last == ']')) { // This is an ending
                            m = new Message(runtime, "internal:createText", s.Substring(1, s.Length-2), Type.END_INTERPOLATION);
                            m.Line = tree.Line;
                            m.Position = tree.CharPositionInLine;
                            return runtime.CreateMessage(m);
                        } else if(first == '"') { // This is a beginning
                            m = new Message(runtime, "internal:createText", s.Substring(1, s.Length-3), Type.START_INTERPOLATION);
                            m.Line = tree.Line;
                            m.Position = tree.CharPositionInLine;
                            return runtime.CreateMessage(m);
                        } else if(first == '#') { // This is a beginning
                            m = new Message(runtime, "internal:createText", s.Substring(2, s.Length-4), Type.START_INTERPOLATION);
                            m.Line = tree.Line;
                            m.Position = tree.CharPositionInLine;
                            return runtime.CreateMessage(m);
                        } else { // This is in the middle
                            m = new Message(runtime, "internal:createText", s.Substring(1, s.Length-3), Type.MIDDLE_INTERPOLATION);
                            m.Line = tree.Line;
                            m.Position = tree.CharPositionInLine;
                            return runtime.CreateMessage(m);
                        }
                    }
                }
                case iokeParser.NumberLiteral:
                    m = new Message(runtime, "internal:createNumber", tree.Text);
                    m.Line = tree.Line;
                    m.Position = tree.CharPositionInLine;
                    return runtime.CreateMessage(m);
                case iokeParser.DecimalLiteral:
                    m = new Message(runtime, "internal:createDecimal", tree.Text);
                    m.Line = tree.Line;
                    m.Position = tree.CharPositionInLine;
                    return runtime.CreateMessage(m);
                case iokeParser.UnitLiteral: {
                    string text = tree.Text;
                    int ending = text.Length-1;
                    while(!Char.IsDigit(text[ending])) {
                        ending--;
                    }
                    Message mex = new Message(runtime, "internal:createNumber", text.Substring(0, ending+1));
                    mex.Line = tree.Line;
                    mex.Position = tree.CharPositionInLine;
                    m = new Message(runtime, "internal:createUnit", runtime.CreateMessage(mex));
                    m.Line = tree.Line;
                    m.Position = tree.CharPositionInLine;
                    return runtime.CreateMessage(m);
                }
                case iokeParser.UnitDecimalLiteral: {
                    string text = tree.Text;
                    int ending = text.Length-1;
                    while(!Char.IsDigit(text[ending])) {
                        ending--;
                    }
                    Message mex = new Message(runtime, "internal:createDecimal", text.Substring(0, ending+1));
                    mex.Line = tree.Line;
                    mex.Position = tree.CharPositionInLine;
                    m = new Message(runtime, "internal:createUnit", mex);
                    m.Line = tree.Line;
                    m.Position = tree.CharPositionInLine;
                    return runtime.CreateMessage(m);
                }
                case iokeParser.Identifier:
                    m = new Message(runtime, tree.Text);
                    m.Line = tree.Line;
                    m.Position = tree.CharPositionInLine;
                    return runtime.CreateMessage(m);
                case iokeParser.Terminator:
                    m = new Message(runtime, ".", null, Type.TERMINATOR);
                    m.Line = tree.Line;
                    m.Position = tree.CharPositionInLine;
                    return runtime.CreateMessage(m);
                case iokeParser.Comma:
                    m = new Message(runtime, ",", null, Type.SEPARATOR);
                    m.Line = tree.Line;
                    m.Position = tree.CharPositionInLine;
                    return runtime.CreateMessage(m);
                case iokeParser.MESSAGE: {
                    string text = tree.GetChild(0).Text;
                    m = new Message(runtime, text);
                    int count = tree.ChildCount;
                    argStart = 1;
                    if(count > 1) {
                        int diff = tree.GetChild(1).CharPositionInLine - (tree.CharPositionInLine+text.Length);
                        if(diff != 0) {
                            m.type = Type.DETACH;
                        }
                        argStart = 2;
                    }

                    break;
                }
                default:
                    Console.Error.WriteLine("ERROR: Can't handle " + tree + " : " + tree.Type);
                    return null;
                }

                m.Line = tree.Line;
                m.Position = tree.CharPositionInLine;
            }

            IokeObject mx = m == null ? (IokeObject)null : runtime.CreateMessage(m);

            object head = null;
            IList<IokeObject> currents = new SaneList<IokeObject>();

            IList<IList<IokeObject>> oldCurrents = new SaneList<IList<IokeObject>>();
            IList<object> oldHeads = new SaneList<object>();
            IList<IokeObject> oldMx = new SaneList<IokeObject>();

            for(int i=argStart,j=tree.ChildCount; i<j; i++) {
                IokeObject created = FromTree(runtime, tree.GetChild(i));

                switch(Message.typeOf(created)) {
                case Type.START_INTERPOLATION:{
                    Message mvv = new Message(runtime, "internal:concatenateText");
                    mvv.Line = tree.Line;
                    mvv.Position = tree.CharPositionInLine;
                    oldCurrents.Insert(0, currents);
                    oldHeads.Insert(0, head);
                    oldMx.Insert(0, mx);

                    currents = new SaneList<IokeObject>();
                    head = created;
                    mx = runtime.CreateMessage(mvv);

                    created = runtime.CreateMessage(new Message(runtime, ",", null, Type.SEPARATOR));
                    break;
                }
                case Type.START_RE_INTERPOLATION:{
                    Message mvv = new Message(runtime, "internal:compositeRegexp");
                    mvv.Line = tree.Line;
                    mvv.Position = tree.CharPositionInLine;
                    oldCurrents.Insert(0, currents);
                    oldHeads.Insert(0, head);
                    oldMx.Insert(0, mx);

                    currents = new SaneList<IokeObject>();
                    head = created.Arguments[0];
                    mx = runtime.CreateMessage(mvv);

                    created = runtime.CreateMessage(new Message(runtime, ",", null, Type.SEPARATOR));
                    break;
                }
                case Type.MIDDLE_INTERPOLATION:
                    mx.Arguments.Add(head);

                    currents.Clear();
                    head = created;

                    created = runtime.CreateMessage(new Message(runtime, ",", null, Type.SEPARATOR));
                    break;
                case Type.MIDDLE_RE_INTERPOLATION:
                    mx.Arguments.Add(head);

                    currents.Clear();
                    head = created.Arguments[0];

                    created = runtime.CreateMessage(new Message(runtime, ",", null, Type.SEPARATOR));
                    break;
                case Type.END_INTERPOLATION:
                    mx.Arguments.Add(head);
                    mx.Arguments.Add(created);

                    currents = oldCurrents[0];
                    oldCurrents.RemoveAt(0);

                    head = oldHeads[0];
                    oldHeads.RemoveAt(0);

                    created = mx;

                    mx = oldMx[0];
                    oldMx.RemoveAt(0);

                    break;
                case Type.END_RE_INTERPOLATION:
                    mx.Arguments.Add(head);
                    mx.Arguments.Add(created.Arguments[0]);
                    mx.Arguments.Add(created.Arguments[1]);

                    currents = oldCurrents[0];
                    oldCurrents.RemoveAt(0);

                    head = oldHeads[0];
                    oldHeads.RemoveAt(0);

                    created = mx;

                    mx = oldMx[0];
                    oldMx.RemoveAt(0);
                    break;
                }

                if(Message.typeOf(created) == Type.TERMINATOR && head == null && currents.Count == 0) {
                    continue;
                }

                if(Message.typeOf(created) == Type.SEPARATOR && mx != null) {
                    mx.Arguments.Add(head);
                    currents.Clear();
                    head = null;
                } else {
                    if(Message.typeOf(created) == Type.TERMINATOR && currents.Count > 1) {
                        while(currents.Count > 1) {
                            currents.RemoveAt(0);
                        }
                    }
                    Message.SetPrev(created, currents.Count > 0 ? currents[0] : null);

                    if(head == null && Message.typeOf(created) != Type.TERMINATOR) {
                        head = created;
                    }

                    if(currents.Count > 0) {
                        Message.SetNextOfLast(currents[0], created);
                        currents[0] = created;
                    } else {
                        currents.Insert(0, created);
                    }
                }
            }

            if(mx != null && head != null) {
                mx.Arguments.Add(head);
            }

            return mx == null ? (IokeObject)head : mx;
        }