Exemplo n.º 1
0
        void parseBracketClose()
        {
            currentTokenKind = TokenKind.VALUE;

            Operator op;

            while ((op = operators.PopOrDefault()).operation != NT.BRACKET_OPEN)
            {
                if (op.operation == NT.UNDEFINED)
                {
                    throw Jolly.unexpected(token);
                }
                pushOperator(op);
            }

            Context context = contextStack.Pop();

            while (context.kind != Context.Kind.SUBSCRIPT)
            {
                contextEnd(context);
                context = contextStack.Pop();
            }

            if (context.hasColon)
            {
                var node = values.Peek();
                if (node.nodeType == NT.MODIFY_TYPE)
                {
                    ((AST_ModifyType)node).target = context.target;
                }
                else if (node.nodeType != NT.SLICE)
                {
                    throw Jolly.unexpected(node);
                }
            }
            else
            {
                AST_Node a = values.PopOrDefault();

                if (a == null)
                {
                    var mod = new AST_ModifyType(op.location, context.target, AST_ModifyType.TO_ARRAY);
                    ast.Add(mod);
                    values.Push(mod);
                    return;
                }
                var opNode = new AST_Operation(token.location, NT.SUBSCRIPT, a, null, false);
                values.Push(opNode);
                ast.Add(opNode);
            }

            if (values.Peek() == null)
            {
                values.Pop();
            }
        }
Exemplo n.º 2
0
 static void inferOperands(AST_Operation op)
 {
     if (op.leftToRight)
     {
         op.a.infer?.Invoke(op.a, op.b, instructions);
         op.b?.infer?.Invoke(op.b, op.a, instructions);
     }
     else
     {
         op.b?.infer?.Invoke(op.b, op.a, instructions);
         op.a.infer?.Invoke(op.a, op.b, instructions);
     }
 }
Exemplo n.º 3
0
        static void analyseNode(AST_Node node)
        {
            Action <AST_Node> action;

            if (!analysers.TryGetValue(node.nodeType, out action))
            {
                throw Jolly.unexpected(node);
            }
            // TODO: Find a better way to do this
            AST_Operation op = node as AST_Operation;

            if (op != null)
            {
                inferOperands(op);
            }
            action(node);
        }
Exemplo n.º 4
0
        void pushOperator(Operator op)
        {
            AST_Node a, b = null;

            if (op.valCount == 2)
            {
                b = values.PopOrDefault();
                a = values.PopOrDefault();

                if (op.operation == NT.COMMA)
                {
                    if (a == null)
                    {
                        values.Push(null);
                        if (!(b is AST_Tuple))
                        {
                            var tup = new AST_Tuple(b.location, NT.TUPLE);
                            tup.values.Add(b);
                            values.Push(tup);
                            return;
                        }
                        values.Push(b);
                        return;
                    }

                    AST_Tuple tuple = a as AST_Tuple;
                    if (tuple?.closed ?? true)
                    {
                        tuple = new AST_Tuple(b.location, NT.TUPLE);
                        tuple.values.Add(a);
                    }
                    tuple.values.Add(b);
                    values.Push(tuple);
                    return;
                }
                else if (op.operation == NT.SLICE)
                {
                    if (a == null & b == null)
                    {
                        var mod = new AST_ModifyType(op.location, null, AST_ModifyType.TO_SLICE);
                        values.Push(mod);
                        ast.Add(mod);
                        return;
                    }
                    // Slice allows a value to be null
                    var slice = (a == null) ?
                                new AST_Operation(op.location, NT.SLICE, b, null, true) :
                                new AST_Operation(op.location, NT.SLICE, a, b, true);
                    values.Push(slice);
                    ast.Add(slice);
                    return;
                }

                if (a == null)
                {
                    throw Jolly.addError(op.location, "Expecting 2 values");
                }
                if (op.operation == NT.GET_MEMBER && b.nodeType == NT.NAME)
                {
                    b.nodeType = NT.MEMBER_NAME;
                }
            }
            else
            {
                a = values.PopOrDefault();
                if (a == null)
                {
                    throw Jolly.addError(op.location, "Invalid expression term");
                }
            }

            if (op.isSpecial)
            {
                if (op.operation == NT.LOGIC_AND)
                {
                    int memberCount = ast.Count - op.operatorIndex;
                    var logic       = new AST_Logic(op.location, NT.LOGIC_OR, memberCount, memberCount, condition: a, a: b, b: null);
                    values.Push(logic);
                    ast.Insert(op.operatorIndex, logic);
                    return;
                }
                else if (op.operation == NT.LOGIC_OR)
                {
                    int memberCount = ast.Count - op.operatorIndex;
                    var logic       = new AST_Logic(op.location, NT.LOGIC_AND, memberCount, memberCount, condition: a, a: b, b: null);
                    values.Push(logic);
                    ast.Insert(op.operatorIndex, logic);
                    return;
                }
                else if (op.operation == NT.TERNARY)
                {
                    Context context = contextStack.Pop();
                    while (context.kind != Context.Kind.TERNARY)
                    {
                        contextEnd(context);
                        context = contextStack.Pop();
                    }
                    context.target = a;
                    contextStack.Push(context);
                    values.Push(b);
                    return;
                }
                else if (op.operation == NT.TERNARY_SELECT)
                {
                    Context context = contextStack.Pop();
                    while (context.kind != Context.Kind.TERNARY)
                    {
                        contextEnd(context);
                        context = contextStack.Pop();
                    }

                    int memberCount = ast.Count - context.index,
                        count       = op.operatorIndex - context.index;
                    var logic       = new AST_Logic(op.location, NT.TERNARY, memberCount, count, context.target, a, b);
                    values.Push(logic);
                    ast.Insert(context.index, logic);
                    return;
                }
                Jolly.addNote(op.location, "Compiler: unnecessary operator marked special {0}".fill(op.operation));
            }     // if(op.isSpecial)

            AST_Operation opNode = new AST_Operation(op.location, op.operation, a, b, op.leftToRight);

            values.Push(opNode);
            ast.Add(opNode);
        } // pushOperator()