Beispiel #1
0
        /// <summary>
        /// variable-declaration-part :: [ "var" variable-declaration ';' { variable-declaration ';' } ] .
        /// variable-declaration :: identifier-list ':' type-denoter .
        /// identifier-list :: identifier { ',' identifier } .
        /// type-denoter :: "integer" | "real" | "char" | "boolean" | "string" .
        /// </summary>
        /// <param name="programBlock">A program block containing this variables declaration list.</param>
        private void ParseVariableDeclarationPart(IProgramBlock programBlock)
        {
            if (Tokenizer.CurrentToken.TokenCode != TokenCode.TOK_KEY_VAR)
            {
                return;
            }

            // Eat "var".
            Tokenizer.NextToken();

            while (true)
            {
                ParseVariableDeclaration(programBlock);

                // Get the token behind the last variable-declaration.
                var t = Tokenizer.CurrentToken;

                // ';' ?
                if (t.TokenCode != TokenCode.TOK_SEP)
                {
                    throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "The end of variable declaration list (';') expected.");
                }

                // Eat ';'.
                t = Tokenizer.NextToken();

                if (t.TokenCode != TokenCode.TOK_IDENT)
                {
                    break;
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="parentBlock">The parent program block of this command.</param>
        public EmptyCommand(IProgramBlock parentBlock)
        {
            if (parentBlock == null)
            {
                throw new ArgumentNullException(nameof(parentBlock));
            }

            Parent = parentBlock;
        }
Beispiel #3
0
        /// <summary>
        /// compound-statement :: "begin" statement-sequence "end" .
        /// </summary>
        /// <param name="currentBlock">The currently parsed program block.</param>
        private void ParseCompoundStatement(IProgramBlock currentBlock)
        {
            // "BEGIN".
            ExpectAndEat(TokenCode.TOK_KEY_BEGIN, "The 'BEGIN' key word expected.");

            ParseStatementSequence(currentBlock);

            // "END".
            ExpectAndEat(TokenCode.TOK_KEY_END, "The 'END' key word expected.");
        }
Beispiel #4
0
        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="parentBlock">The parent program block of this command.</param>
        public WritelnCommand(IProgramBlock parentBlock, string parameter = null)
        {
            if (parentBlock == null)
            {
                throw new ArgumentNullException(nameof(parentBlock));
            }

            Parent    = parentBlock;
            Parameter = parameter;
        }
Beispiel #5
0
        /// <summary>
        /// --block :: variable-declaration-part "begin" [ command { ';' command } ] "end" .
        ///
        /// block :: variable-declaration-part statement-part .
        /// variable-declaration-part :: [ "var" variable-declaration ';' { variable-declaration ';' } ] .
        /// statement-part :: compound-statement .
        /// compound-statement :: "begin" statement-sequence "end" .
        /// statement-sequence :: statement { ';' statement } .
        /// </summary>
        /// <param name="parentBlock">A parent program block.</param>
        /// <returns>An ICompiledProgramPart instance representing this compiled program part.</returns>
        private ICompiledProgramPart ParseBlock(IProgramBlock parentBlock)
        {
            var block = (parentBlock == null)
                ? (IProgramBlock) new ProgramBlock(parentBlock)
                : (IProgramBlock) new Block(parentBlock);

            ParseVariableDeclarationPart(block);
            ParseStatementPart(block);

            return(block);
        }
Beispiel #6
0
        /// <summary>
        /// expression :: string .
        /// </summary>
        /// <param name="parentBlock"></param>
        /// <returns></returns>
        private ICompiledProgramPart ParseExpression(IProgramBlock parentBlock)
        {
            if (Tokenizer.CurrentToken.TokenCode == TokenCode.TOK_STR)
            {
                var s = Tokenizer.CurrentToken.StringValue;

                Eat();

                return(new Expression(parentBlock, s));
            }

            throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "An expression value expected.");
        }
Beispiel #7
0
        /// <summary>
        /// statement :: [ label ':' ] ( simple-statement | structured-statement ) .
        /// simple-statement :: empty-statement | assignment-statement | procedure-statement | goto-statement .
        /// empty-statement :: .
        /// assignment-statement :: ( variable-access | function-identifier ) ":=" expression .
        /// procedure-statement :: procedure-identifier ( [ actual-parameter-list ] | read-parameter-list | readln-parameter-list | write-parameter-list | writeln-parameter-list ) .
        /// goto-statement :: "goto" label .
        /// structured-statement :: compound-statement | conditional-statement | repetitive-statement | with-statement .
        /// </summary>
        /// <param name="parentBlock">A parent program block.</param>
        /// <returns>An ICompiledProgramPart instance representing this compiled program part.</returns>
        private ICompiledProgramPart ParseStatement(IProgramBlock parentBlock)
        {
            var t = Tokenizer.CurrentToken;

            if (t.TokenCode == TokenCode.TOK_IDENT)
            {
                // TODO: Procedure or assignment or function?
                return(ParseProcedureStatement(parentBlock));
            }
            else if (t.TokenCode == TokenCode.TOK_SEP || t.TokenCode == TokenCode.TOK_KEY_END)
            {
                return(new EmptyCommand(parentBlock));
            }

            throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, $"Unexpected token: {t}");
        }
Beispiel #8
0
        /// <summary>
        /// actual-parameter-list :: '(' actual-parameter { ',' actual-parameter } `)' .
        /// actual-parameter :: expression | variable-access | procedure-identifier | function-identifier .
        /// writeln-parameter-list :: '(' ( file-variable | write-parameter ) { ',' write-parameter } ')' .
        /// write-parameter :: expression [ ':' expression [ ':' expression ] ] .
        /// expression :: string .
        /// </summary>
        /// <param name="parentBlock">A parent program block.</param>
        /// <returns>An ICompiledProgramPart instance representing this compiled program part.</returns>
        private ICompiledProgramPart ParseWritelnParameterList(IProgramBlock parentBlock)
        {
            // Eat "(";
            var t = Tokenizer.NextToken();

            if (t.TokenCode == TokenCode.TOK_STR)
            {
                var expression = (Expression)ParseExpression(parentBlock);

                // ')'.
                ExpectAndEat(TokenCode.TOK_RBRA, "The end of procedure parameters ')' expected.");

                return(new WritelnCommand(parentBlock, expression.SValue));
            }

            throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "A procedure parameter expected.");
        }
Beispiel #9
0
        /// <summary>
        /// procedure-statement :: procedure-identifier [ ( actual-parameter-list | read-parameter-list | readln-parameter-list | write-parameter-list | writeln-parameter-list ) ] .
        /// </summary>
        /// <param name="parentBlock"></param>
        /// <returns></returns>
        private ICompiledProgramPart ParseProcedureStatement(IProgramBlock parentBlock)
        {
            var procedureIdentifier = Tokenizer.CurrentToken.StringValue.ToUpperInvariant();

            if (procedureIdentifier == "WRITELN")
            {
                // Eat "writeln".
                var t = Tokenizer.NextToken();
                if (t.TokenCode == TokenCode.TOK_LBRA)
                {
                    return(ParseWritelnParameterList(parentBlock));
                }

                return(new WritelnCommand(parentBlock));
            }

            throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, $"Undefined identifier: {procedureIdentifier}");
        }
Beispiel #10
0
        /// <summary>
        /// statement-sequence :: statement { ';' statement } .
        /// </summary>
        /// <param name="currentBlock">The currently parsed program block.</param>
        private void ParseStatementSequence(IProgramBlock currentBlock)
        {
            var t = Tokenizer.CurrentToken;

            while (t.TokenCode != TokenCode.TOK_EOF)
            {
                currentBlock.AddCompiledProgramPart(ParseStatement(currentBlock));

                t = Tokenizer.CurrentToken;
                if (t.TokenCode == TokenCode.TOK_KEY_END)
                {
                    break;
                }

                if (t.TokenCode == TokenCode.TOK_SEP)
                {
                    t = Tokenizer.NextToken();

                    continue;
                }

                throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "The ';' command separator expected.");
            }
        }
Beispiel #11
0
 /// <summary>
 /// statement-part :: compound-statement .
 /// </summary>
 /// <param name="parentBlock"></param>
 /// <returns></returns>
 private void ParseStatementPart(IProgramBlock parentBlock)
 {
     ParseCompoundStatement(parentBlock);
 }
Beispiel #12
0
        /// <summary>
        /// variable-declaration :: identifier-list ':' type-denoter .
        /// identifier-list :: identifier { ',' identifier } .
        /// type-denoter :: "integer" | "real" | "char" | "boolean" | "string" .
        /// </summary>
        /// <param name="programBlock"></param>
        /// <param name="currentToken"></param>
        private void ParseVariableDeclaration(IProgramBlock programBlock)
        {
            var t = Tokenizer.CurrentToken;

            if (t.TokenCode != TokenCode.TOK_IDENT)
            {
                throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "An identifier in the variable declaration list expected.");
            }

            var variablesList = new List <string>();

            while (t.TokenCode == TokenCode.TOK_IDENT)
            {
                variablesList.Add(t.StringValue);

                // Eat the identifier.
                t = Tokenizer.NextToken();

                // ','.
                if (t.TokenCode == TokenCode.TOK_LIST_SEP)
                {
                    // Eat the ','.
                    t = Tokenizer.NextToken();

                    if (t.TokenCode == TokenCode.TOK_IDENT)
                    {
                        continue;
                    }

                    throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "An identifier in the variable declaration list expected.");
                }

                // At the end of the variables list?
                break;
            }

            // ':'?
            if (t.TokenCode != TokenCode.TOK_DDOT)
            {
                throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "A variable type specification part expected.");
            }

            // Eat ':'.
            t = Tokenizer.NextToken();

            // A type identifier.
            if (t.TokenCode != TokenCode.TOK_IDENT)
            {
                throw new CompilerException(Tokenizer.CurrentLine, Tokenizer.CurrentLinePosition, "A type denoter in variable declaration expected.");
            }

            var typeName = t.StringValue;

            // Eat identifier.
            Tokenizer.NextToken();

            // Declare all found variables.
            foreach (var variableName in variablesList)
            {
                programBlock.AddVariableDeclaration(variableName, typeName);
            }
        }
Beispiel #13
0
 public ProgramBlock(IProgramBlock parentBlock)
     : base(parentBlock)
 {
 }
Beispiel #14
0
 public Expression(IProgramBlock parentBlock, string sValue)
 {
     ParentBlock = parentBlock;
     SValue      = sValue;
 }
Beispiel #15
0
 protected AProgramBlockBase(IProgramBlock parentBlock)
 {
     Parent = parentBlock;
     VariableDeclarations = new Dictionary <string, VariableDeclaration>();
     Children             = new List <ICompiledProgramPart>();
 }