Ejemplo n.º 1
0
        //TODO: unused?
        private List <Token <String> > ParseScopedTokens(TokenType scopeStart, TokenType scopeEnd)
        {
            var scopedTokens = new List <Token <String> >();

            if (Tokens.ConsumeToken(scopeStart) == null)
            {
                Log.LogError("Expected '" + scopeStart.ToString() + "'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1));
                return(null);
            }

            int nestedLevel = 1;

            while (nestedLevel > 0)
            {
                if (CurrentTokenType == TokenType.EOF)
                {
                    return(null); // ERROR: Scope ended prematurely, are your scopes unbalanced?
                }
                if (CurrentTokenType == scopeStart)
                {
                    nestedLevel++;
                }
                else if (CurrentTokenType == scopeEnd)
                {
                    nestedLevel--;
                }

                scopedTokens.Add(Tokens.CurrentItem);
                Tokens.Advance();
            }
            // Remove the ending scope token:
            scopedTokens.RemoveAt(scopedTokens.Count - 1);
            return(scopedTokens);
        }
Ejemplo n.º 2
0
        public ASTNode ParseBody()
        {
            do
            {
                if (Tokens.CurrentItem.StartPosition.Equals(Body.StartPos))
                {
                    break;
                }
                Tokens.Advance();
            } while (!Tokens.AtEnd());

            if (Tokens.AtEnd())
            {
                return(Error("Could not find the code body for the current node, please contact the maintainers of this compiler!"));
            }

            var body = TryParseBody(false);

            if (body == null)
            {
                return(null);
            }
            Body.Statements = body.Statements;

            if (!Tokens.CurrentItem.StartPosition.Equals(Body.EndPos))
            {
                return(Error("Could not parse a valid statement, even though the current code body has supposedly not ended yet.",
                             CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
            }

            return(Body);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Creates a rule - metadata that allows invocation of a function on
        /// </summary>
        private void RuleDeclaration()
        {
            if (_EnclosingCompiler != null)
            {
                throw new CompilerException(Tokens.Peek(), "Rules must be globally scoped.");
            }
            Token triggerName = Tokens.Consume(IDENTIFIER, "Rule declarations must begin with a named trigger.");
            List <RuleCondition> conditions = new List <RuleCondition>();

            // rule conditions
            while (!Tokens.Match(RIGHT_BRACKET))
            {
                Token contextVariableName  = Tokens.Consume(IDENTIFIER, "Rule must contain list of comparison expressions (missing identifier).");
                Token comparisonOperation  = Tokens.Advance(); // we will check validity of this token after consuming the value
                Token contextVariableValue = Tokens.Consume(NUMBER, "Rule must contain list of comparison expressions (missing value)");
                switch (comparisonOperation.Type)
                {
                case BANG_EQUAL:
                    // conditions.Add(RuleCondition.ConditionNotEquals(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    throw new CompilerException(Tokens.Peek(), "Rule must contain list of comparison expressions (can't use != operator).");

                case EQUAL:
                case EQUAL_EQUAL:
                    conditions.Add(RuleCondition.ConditionEquals(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case GREATER:
                    conditions.Add(RuleCondition.ConditionGreaterThan(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case GREATER_EQUAL:
                    conditions.Add(RuleCondition.ConditionGreaterThanOrEqual(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case LESS:
                    conditions.Add(RuleCondition.ConditionLessThan(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                case LESS_EQUAL:
                    conditions.Add(RuleCondition.ConditionLessThanOrEqual(contextVariableName.Lexeme, contextVariableValue.LiteralAsNumber));
                    break;

                default:
                    throw new CompilerException(Tokens.Peek(), "Rule must contain list of comparison expressions (missing operator).");
                }
            }
            if (Tokens.Peek().Type == FUNCTION && Tokens.Peek(1).Type == IDENTIFIER)
            {
                string functionName = Tokens.Peek(1).Lexeme;
                _Rules.Add(new Rule(BitString.GetBitStr(triggerName.Lexeme), BitString.GetBitStr(functionName), conditions.ToArray()));
            }
            else
            {
                throw new CompilerException(Tokens.Peek(), "Rule declaration must be followed by function.");
            }
        }
Ejemplo n.º 4
0
        private bool ParseScopeSpan(TokenType scopeStart, TokenType scopeEnd,
                                    out SourcePosition startPos, out SourcePosition endPos)
        {
            startPos = null;
            endPos   = null;
            if (Tokens.ConsumeToken(scopeStart) == null)
            {
                Log.LogError("Expected '" + scopeStart.ToString() + "'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1));
                return(false);
            }
            startPos = Tokens.CurrentItem.StartPosition;

            int nestedLevel = 1;

            while (nestedLevel > 0)
            {
                if (CurrentTokenType == TokenType.EOF)
                {
                    Log.LogError("Scope ended prematurely, are your scopes unbalanced?", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1));
                    return(false);
                }
                if (CurrentTokenType == scopeStart)
                {
                    nestedLevel++;
                }
                else if (CurrentTokenType == scopeEnd)
                {
                    nestedLevel--;
                }

                // If we're at the end token, don't advance so we can check the position properly.
                if (nestedLevel > 0)
                {
                    Tokens.Advance();
                }
            }
            endPos = Tokens.CurrentItem.StartPosition;
            Tokens.Advance();
            return(true);
        }
Ejemplo n.º 5
0
        // === Error Handling ========================================================================================
        // ===========================================================================================================

        /// <summary>
        /// Discards tokens until it thinks it found a statement boundary. After catching a ParseError, we’ll call this
        /// and then we are hopefully back in sync. When it works well, we have discarded tokens that would have likely
        /// caused cascaded errors anyway and now we can parse the rest of the file starting at the next statement.
        /// </summary>
        protected override void Synchronize()
        {
            Tokens.Advance();
            while (!Tokens.IsAtEnd())
            {
                if (Tokens.Previous().Type == SEMICOLON)
                {
                    return;
                }
                switch (Tokens.Peek().Type)
                {
                case CLASS:
                case FUNCTION:
                case VAR:
                case FOR:
                case IF:
                case WHILE:
                case RETURN:
                    return;
                }
                Tokens.Advance();
            }
        }
Ejemplo n.º 6
0
        public State TryParseState()
        {
            Func <ASTNode> stateSkeletonParser = () =>
            {
                var specs = ParseSpecifiers(GlobalLists.StateSpecifiers);

                if (Tokens.ConsumeToken(TokenType.State) == null)
                {
                    return(null);
                }

                var name = Tokens.ConsumeToken(TokenType.Word);
                if (name == null)
                {
                    return(Error("Expected state name!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var parent = TryParseParent();

                if (Tokens.ConsumeToken(TokenType.LeftBracket) == null)
                {
                    return(Error("Expected '{'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                List <Function> ignores = new List <Function>();
                if (Tokens.ConsumeToken(TokenType.Ignores) != null)
                {
                    do
                    {
                        VariableIdentifier variable = TryParseVariable();
                        if (variable == null)
                        {
                            return(Error("Malformed ignore statement!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                        }

                        ignores.Add(new Function(variable.Name, null, null, null, null, variable.StartPos, variable.EndPos));
                    } while (Tokens.ConsumeToken(TokenType.Comma) != null);

                    if (Tokens.ConsumeToken(TokenType.SemiColon) == null)
                    {
                        return(Error("Expected semi-colon!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                    }
                }

                var      funcs = new List <Function>();
                Function func  = TryParseFunction();
                while (func != null)
                {
                    funcs.Add(func);
                    func = TryParseFunction();
                }

                var bodyStart = Tokens.CurrentItem.StartPosition;
                while (Tokens.CurrentItem.Type != TokenType.RightBracket && !Tokens.AtEnd())
                {
                    Tokens.Advance();
                }
                var bodyEnd = Tokens.CurrentItem.StartPosition;

                if (Tokens.ConsumeToken(TokenType.RightBracket) == null)
                {
                    return(Error("Expected '}'!", CurrentPosition, CurrentPosition.GetModifiedPosition(0, 1, 1)));
                }

                var body        = new CodeBody(new List <Statement>(), bodyStart, bodyEnd);
                var parentState = parent != null ? new State(parent.Name, null, null, null, null, null, null, parent.StartPos, parent.EndPos) : null;
                return(new State(name.Value, body, specs, parentState, funcs, ignores, null, name.StartPosition, name.EndPosition));
            };

            return((State)Tokens.TryGetTree(stateSkeletonParser));
        }