Esempio n. 1
0
    private void Block(LexemeSet stopSet, BlockNode containingBlock)
    {
        logger.LogDebug($"Block: {currentLexeme} [{stopSet}]");
        CheckOrSkip(stopSet + startBlock, stopSet + startBlock);
        if (currentLexeme.Type == LexemeType.Begin)
        {
            NextLexeme();

            Block(stopSet + LexemeType.Semicolon + LexemeType.End, containingBlock);

            CheckOrSkip(LexemeSet.From(LexemeType.Semicolon, LexemeType.End), stopSet + LexemeType.Semicolon + startBlock);

            while ((startBlock + LexemeType.Semicolon).Contains(currentLexeme.Type))
            {
                StepOverCurrentLexemeIfItsA(LexemeType.Semicolon);
                Block(stopSet + LexemeType.Semicolon + LexemeType.End, containingBlock);
                CheckOrSkip(LexemeSet.From(LexemeType.Semicolon, LexemeType.End), stopSet + LexemeType.Semicolon + startBlock);
            }
            StepOverCurrentLexemeIfItsA(LexemeType.End);
        }
        else
        {
            // StepOverCurrentLexemeIfItsA(LexemeType.Semicolon);
            var statement = Statement(stopSet);
            if (statement != null)
            {
                containingBlock.Nodes.Add(statement);
            }
        }
    }
Esempio n. 2
0
    public static LexemeSet operator-(LexemeSet left, LexemeType right)
    {
        LexemeSet res = new LexemeSet(left);

        res.Remove(right);
        return(res);
    }
Esempio n. 3
0
    public static LexemeSet operator+(LexemeSet left, LexemeType right)
    {
        LexemeSet res = new LexemeSet(left);

        res.Add(right);
        return(res);
    }
Esempio n. 4
0
    private AstNode Factor(LexemeSet stopSet)
    {
        logger.LogDebug($"Factor: {currentLexeme} [{stopSet}]");
        if (CheckOrSkip(startExpression, stopSet))
        {
            switch (currentLexeme.Type)
            {
            case LexemeType.Identifier:
                // TODO: check that id exists in the symbol table in the semantic analysis pass
                var name = currentLexeme.Value.ToString();
                NextLexeme();
                return(new IdentifierNode(name));

            case LexemeType.Constant:
                var value = (ushort)currentLexeme.Value;
                NextLexeme();
                return(new ConstantNode(value));

            case LexemeType.LBracket:
                NextLexeme();
                var res = Expression((stopSet + LexemeType.RBracket));
                if (CheckOrSkip(LexemeType.RBracket, stopSet))
                {
                    NextLexeme();
                }
                return(res);

            case LexemeType.Read:
                NextLexeme();
                return(new ReadNode());
            }
        }

        throw new CompilerException($"Could not parse factor from {currentLexeme}");
    }
Esempio n. 5
0
    private void IdList(LexemeSet stopSet)
    {
        bool complete;

        do
        {
            // we expect an identifier
            if (CheckOrSkip(LexemeSet.From(LexemeType.Identifier), stopSet + LexemeType.Semicolon + LexemeType.Comma))
            {
                // we got an identifier add it to the symbol table
                // adding a duplicate symbol outputs a warning, this is really semantic analysis
                // but we do that in this phase for convinience
                symbolTable.Declare(currentLexeme.Value.ToString());
                NextLexeme();
            }

            // move past the training comma or the terminating semi colon
            CheckOrSkip(LexemeSet.From(LexemeType.Semicolon, LexemeType.Comma), stopSet + LexemeType.Identifier + LexemeType.Comma);

            // were are complete if the next token _isn't_ a comma or another identifier
            complete = currentLexeme.Type is not(LexemeType.Comma or LexemeType.Identifier);

            // if we are on a comma step over it
            StepOverCurrentLexemeIfItsA(LexemeType.Comma);
        } while (!complete);

        StepOverCurrentLexemeIfItsA(LexemeType.Semicolon);
    }
Esempio n. 6
0
    public void SubtractOperator_WhenUsedWithALexemeSet_ShouldRemoveIt()
    {
        var sut = CreateSut(LexemeType.Do, LexemeType.Assign, LexemeType.Comma);
        var res = sut - LexemeSet.From(LexemeType.Assign, LexemeType.Comma);

        res.Contains(LexemeType.Do).Should().BeTrue();
        res.Contains(LexemeType.Assign).Should().BeFalse();
        res.Contains(LexemeType.Comma).Should().BeFalse();
    }
Esempio n. 7
0
    public static LexemeSet operator-(LexemeSet left, LexemeSet right)
    {
        LexemeSet res = new LexemeSet(left);

        foreach (var lexemeType in right)
        {
            res.Remove(lexemeType);
        }
        return(res);
    }
Esempio n. 8
0
    private bool CheckOrSkip(LexemeSet okSet, LexemeSet skipList)
    {
        if (okSet.Contains(currentLexeme.Type))
        {
            return(true);
        }

        // Error message
        logger.LogDebug($"Line {currentLexeme.LineNumber}: Found token: '{currentLexeme.Type}', Expected (one of): [{okSet}]");

        while (!skipList.Contains(currentLexeme.Type))
        {
            logger.LogDebug("skipped lexeme " + currentLexeme.Type);
            NextLexeme();
        }

        return(false);
    }
Esempio n. 9
0
    private void Program()
    {
        // check if variables are being defined
        if (currentLexeme.Type == LexemeType.Var)
        {
            // skip the VAR keyword
            NextLexeme();

            // read a comma seperated list of IDS, terminated by a semicolon
            IdList(LexemeSet.From(LexemeType.Begin, LexemeType.Semicolon, LexemeType.Dot));
        }

        do
        {
            ast.Root = new BlockNode();
            Block(LexemeSet.From(LexemeType.Dot), ast.Root);
            // wile we are not at the terminating period
        } while (!CheckOrSkip(LexemeType.Dot, LexemeSet.Empty));

        ast.Display();
    }
Esempio n. 10
0
    private AstNode Term(LexemeSet stopSet)
    {
        logger.LogDebug($"Term: {currentLexeme} [{stopSet}]");
        var res       = Factor(stopSet + LexemeType.MulOp);
        var currentOp = currentLexeme.Value;

        logger.LogDebug($"first factor: {res}");
        while (currentLexeme.Type == LexemeType.MulOp)
        {
            logger.LogDebug($"Term: {currentLexeme} [{stopSet}]");
            NextLexeme();
            var nextFactor = Factor(stopSet + LexemeType.MulOp);
            logger.LogDebug($"next factor: {nextFactor}");
            res = new PairNode()
            {
                Left = res, Right = nextFactor, Operator = currentOp.ToString()
            };
        }

        return(res);
    }
Esempio n. 11
0
    private AstNode Expression(LexemeSet stopSet)
    {
        logger.LogDebug($"Expression: {currentLexeme} [{stopSet}]");

        // left
        var res       = Term(stopSet + LexemeType.AddOp);
        var currentOp = currentLexeme.Value;

        while (currentLexeme.Type == LexemeType.AddOp)
        {
            logger.LogDebug($"Expression: {currentLexeme} [{stopSet}]");
            NextLexeme();

            var nextTerm = Term(stopSet + LexemeType.AddOp);
            res = new ExpressionNode {
                Left = res, Right = nextTerm, Operator = currentOp.ToString()
            };
        }

        return(res);
    }
Esempio n. 12
0
    private PairNode Comparison(LexemeSet stopSet)
    {
        logger.LogDebug($"Comparison: {currentLexeme} [{stopSet}]");

        // left
        var    left      = Expression(stopSet + LexemeType.RelOp);
        object operation = null;

        if (CheckOrSkip(LexemeType.RelOp, stopSet + startExpression))
        {
            operation = currentLexeme.Value;
            NextLexeme();
        }

        // right
        var right = Expression(stopSet + startBlock - LexemeType.Identifier);

        return(new PairNode()
        {
            Left = left,
            Right = right,
            Operator = operation.ToString()
        });
    }
Esempio n. 13
0
 private LexemeSet CreateSut(params LexemeType[] args)
 {
     return(LexemeSet.From(args));
 }
Esempio n. 14
0
 private bool CheckOrSkip(LexemeType expected, LexemeSet skipList)
 {
     return(CheckOrSkip(LexemeSet.From(expected), skipList));
 }
Esempio n. 15
0
    private AstNode Statement(LexemeSet stopSet)
    {
        AstNode res = null;

        logger.LogDebug($"Statement: {currentLexeme} [{stopSet}]");
        if (CheckOrSkip(stopSet + startBlock, stopSet))
        {
            switch (currentLexeme.Type)
            {
            case LexemeType.Identifier:
                string identifier = currentLexeme.Value.ToString();
                // check id exists in the symbol table in the semantic analysis pass
                NextLexeme();

                if (CheckOrSkip(LexemeType.Assign, stopSet + startExpression))
                {
                    NextLexeme();
                    res = new AssignmentNode()
                    {
                        Identifier = new IdentifierNode(identifier),
                        Expression = Expression(stopSet),
                    };
                }
                break;

            case LexemeType.If:
                NextLexeme();

                IfNode ifNode = new IfNode();

                ifNode.Comparison = Comparison(stopSet + LexemeType.Then + startBlock - LexemeType.Identifier);
                if (CheckOrSkip(LexemeType.Then, stopSet + startBlock))
                {
                    NextLexeme();
                }
                Block(stopSet, ifNode.Statements);
                res = ifNode;
                break;

            case LexemeType.While:
                NextLexeme();

                WhileNode whileNode = new WhileNode();
                whileNode.Comparison = Comparison(stopSet + LexemeType.Do + startBlock - LexemeType.Identifier);
                if (CheckOrSkip(LexemeType.Do, stopSet + startBlock))
                {
                    NextLexeme();
                }
                Block(stopSet, whileNode.Statements);
                res = whileNode;
                break;

            case LexemeType.Write:
                NextLexeme();
                if (CheckOrSkip(LexemeType.LBracket, stopSet + LexemeType.RBracket + startExpression))
                {
                    NextLexeme();
                }

                WriteNode writeNode = new WriteNode();
                writeNode.Expression = Expression(stopSet + LexemeType.RBracket);
                if (CheckOrSkip(LexemeType.RBracket, stopSet))
                {
                    NextLexeme();
                }

                res = writeNode;
                break;
            }
        }

        return(res);
    }