Last active
June 5, 2018 04:13
-
-
Save SergiyOsadchyy/4c4e79e198d6e478da7677342588663e to your computer and use it in GitHub Desktop.
lexical analyzer C#
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.IO; | |
using System.Collections.Generic; | |
namespace lexical_analyzer_Csharp | |
{ | |
class Program | |
{ | |
static void Main(string[] args) | |
{ | |
string input = File.ReadAllText(@"/Users/Sergiy/Documents/Навчання/3_курс/Основи_розробки_трансляторів/lexical_analyzer/lexical_analyzer/sample.txt"); | |
Console.WriteLine(input); | |
Console.WriteLine("\n"); | |
Lexer myLexer = new Lexer(input); | |
myLexer.allTokens(); | |
myLexer.printIdentifierTable(); | |
myLexer.printConstantTable(); | |
myLexer.printSymbolTable(); | |
myLexer.printMainTable(); | |
SyntaxAnalyser mySyntaxAnalyser = new SyntaxAnalyser(myLexer); | |
mySyntaxAnalyser.run(); | |
if (mySyntaxAnalyser._syntaxMistakesAvailable == false) | |
{ | |
mySyntaxAnalyser.printInputRPNlist(); | |
mySyntaxAnalyser.reversePolishNotation(); | |
mySyntaxAnalyser.printRPNoutputList(); | |
Interpreter myInterpreter = new Interpreter(mySyntaxAnalyser); | |
myInterpreter.run(); | |
} | |
//Console.ReadKey(); | |
} | |
} | |
public class Interpreter | |
{ | |
SyntaxAnalyser _syntaxAnalyser; | |
public Stack<Token> _stack = new Stack<Token>(); | |
public Interpreter(SyntaxAnalyser syntaxAnalyser) | |
{ | |
_syntaxAnalyser = syntaxAnalyser; | |
} | |
public void run() | |
{ | |
Console.WriteLine("\n\nInterpretation:\n"); | |
for ( int i = 0; i < this._syntaxAnalyser._outputList.Count; i++ ) | |
{ | |
if ( this._syntaxAnalyser._outputList[i]._type == TokenType.Identifier | |
|| this._syntaxAnalyser._outputList[i]._type == TokenType.Number | |
|| this._syntaxAnalyser._outputList[i]._type == TokenType.SymbolConstant ) | |
{ | |
this._stack.Push( this._syntaxAnalyser._outputList[i] ); | |
} | |
else | |
{ | |
switch ( this._syntaxAnalyser._outputList[i]._type ) | |
{ | |
case TokenType.Plus: | |
{ | |
Token myTempToken = this._stack.Pop(); | |
this._stack.Peek()._calculationResult += myTempToken._calculationResult; | |
break; | |
} | |
case TokenType.ReverseSign: | |
{ | |
this._stack.Peek()._calculationResult *= -1; | |
break; | |
} | |
case TokenType.Minus: | |
{ | |
Token myTempToken = this._stack.Pop(); | |
this._stack.Peek()._calculationResult -= myTempToken._calculationResult; | |
break; | |
} | |
case TokenType.Times: | |
{ | |
Token myTempToken = this._stack.Pop(); | |
this._stack.Peek()._calculationResult *= myTempToken._calculationResult; | |
break; | |
} | |
case TokenType.Div: | |
{ | |
Token myTempToken = this._stack.Pop(); | |
this._stack.Peek()._calculationResult /= myTempToken._calculationResult; | |
break; | |
} | |
case TokenType.Power: | |
{ | |
Token myTempToken = this._stack.Pop(); | |
this._stack.Peek()._calculationResult = (int)Math.Pow(this._stack.Peek()._calculationResult, myTempToken._calculationResult); | |
break; | |
} | |
case TokenType.Assign: | |
{ | |
Token myTempToken = this._stack.Pop(); | |
this._stack.Peek()._calculationResult = myTempToken._calculationResult; | |
break; | |
} | |
case TokenType.Read: | |
{ | |
this._stack.Peek()._calculationResult = Convert.ToInt32( Console.ReadLine( ) ) ; | |
break; | |
} | |
case TokenType.Write: | |
{ | |
Token myTempToken = this._stack.Pop(); | |
if ( myTempToken._type == TokenType.Identifier ) | |
{ | |
Console.WriteLine("{0}", myTempToken._calculationResult); | |
} | |
else if ( myTempToken._type == TokenType.SymbolConstant ) | |
{ | |
Console.WriteLine( "{0}", myTempToken._value.Trim('"') ); | |
} | |
break; | |
} | |
case TokenType.Write2: | |
{ | |
Token myTempToken1 = this._stack.Pop( ); | |
Token myTempToken2 = this._stack.Pop( ); | |
Console.WriteLine( "{0}{1}", myTempToken2._value.Trim('"') , myTempToken1._calculationResult ); | |
break; | |
} | |
case TokenType.LessThan: | |
{ | |
Token myTempToken2 = this._stack.Pop( ); | |
Token myTempToken1 = this._stack.Pop(); | |
if ( myTempToken1._calculationResult < myTempToken2._calculationResult ) | |
{ | |
this._stack.Push( new Token( TokenType.Number, "comparison result", 1, -1, -1, -1 ) ); | |
} | |
else | |
{ | |
this._stack.Push( new Token( TokenType.Number, "comparison result", 0, -1, -1, -1 ) ); | |
} | |
break; | |
} | |
case TokenType.LessThanOrEqual: | |
{ | |
Token myTempToken2 = this._stack.Pop(); | |
Token myTempToken1 = this._stack.Pop(); | |
if ( myTempToken1._calculationResult <= myTempToken2._calculationResult ) | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 1, -1, -1, -1)); | |
} | |
else | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 0, -1, -1, -1)); | |
} | |
break; | |
} | |
case TokenType.GreaterThan: | |
{ | |
Token myTempToken2 = this._stack.Pop(); | |
Token myTempToken1 = this._stack.Pop(); | |
if (myTempToken1._calculationResult > myTempToken2._calculationResult) | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 1, -1, -1, -1)); | |
} | |
else | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 0, -1, -1, -1)); | |
} | |
break; | |
} | |
case TokenType.GreaterThanOrEqual: | |
{ | |
Token myTempToken2 = this._stack.Pop(); | |
Token myTempToken1 = this._stack.Pop(); | |
if (myTempToken1._calculationResult >= myTempToken2._calculationResult) | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 1, -1, -1, -1)); | |
} | |
else | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 0, -1, -1, -1)); | |
} | |
break; | |
} | |
case TokenType.Equal: | |
{ | |
Token myTempToken2 = this._stack.Pop(); | |
Token myTempToken1 = this._stack.Pop(); | |
if (myTempToken1._calculationResult == myTempToken2._calculationResult) | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 1, -1, -1, -1)); | |
} | |
else | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 0, -1, -1, -1)); | |
} | |
break; | |
} | |
case TokenType.NotEqual: | |
{ | |
Token myTempToken2 = this._stack.Pop(); | |
Token myTempToken1 = this._stack.Pop(); | |
if (myTempToken1._calculationResult != myTempToken2._calculationResult) | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 1, -1, -1, -1)); | |
} | |
else | |
{ | |
this._stack.Push(new Token(TokenType.Number, "comparison result", 0, -1, -1, -1)); | |
} | |
break; | |
} | |
case TokenType.JumpZero: | |
{ | |
string myTempString; | |
myTempString = this._syntaxAnalyser._outputList[i]._value.Replace( "jumpZero to ", "" ); | |
if ( this._stack.Peek()._calculationResult == 0 ) | |
{ | |
for (int j = 0; j < this._syntaxAnalyser._outputList.Count; j++) | |
{ | |
if ( this._syntaxAnalyser._outputList[j]._value == myTempString ) | |
{ | |
i = j; | |
} | |
} | |
} | |
break; | |
} | |
case TokenType.Jump: | |
{ | |
string myTempString; | |
myTempString = this._syntaxAnalyser._outputList[i]._value.Replace( "jump to ", "" ); | |
for ( int k = 0; k < this._syntaxAnalyser._outputList.Count; k++ ) | |
{ | |
if ( this._syntaxAnalyser._outputList[k]._value == myTempString ) | |
{ | |
i = k; | |
} | |
} | |
break; | |
} | |
case TokenType.JumpToken: | |
{ | |
break; | |
} | |
default: | |
{ | |
Console.WriteLine("\nError in Interpreter"); | |
break; | |
} | |
} | |
} | |
} | |
} | |
} | |
public class StaticContainer | |
{ | |
public static int jumpTokenCounter = 0; | |
} | |
public class SyntaxAnalyser | |
{ | |
public Lexer _lexer; | |
public int _i; | |
public bool _syntaxMistakesAvailable; | |
public Stack<Token> _stack = new Stack<Token>(); | |
public List<Token> _outputList = new List<Token>(); | |
public List<Token> _inputRPNlist = new List<Token>(); | |
public SyntaxAnalyser(Lexer lexer) | |
{ | |
_lexer = lexer; | |
_i = 0; | |
_syntaxMistakesAvailable = false; | |
} | |
public void printInputRPNlist() | |
{ | |
Console.WriteLine( "\n\nInput List for reversePolishNotation:\n" ); | |
for ( int i = 0; i < this._inputRPNlist.Count; i++ ) | |
{ | |
Console.Write("{0}\t", i); | |
Console.WriteLine(this._inputRPNlist[i]._value); | |
} | |
} | |
public void reversePolishNotationRun(Token token) | |
{ | |
if (token._type == TokenType.Identifier | |
|| token._type == TokenType.Number | |
|| token._type == TokenType.Jump | |
|| token._type == TokenType.JumpZero | |
|| token._type == TokenType.JumpToken | |
|| token._type == TokenType.SymbolConstant) | |
{ | |
this._outputList.Add(token); | |
} | |
if (token._type == TokenType.Write || token._type == TokenType.Write2 || token._type == TokenType.Read || token._type == TokenType.While) | |
{ | |
this._stack.Push(token); | |
} | |
else if (token._type == TokenType.LeftParenthesis || token._type == TokenType.If) | |
{ | |
this._stack.Push(token); | |
} | |
else if (token._type == TokenType.RightParenthesis) | |
{ | |
while (this._stack.Count != 0 && this._stack.Peek()._type != TokenType.LeftParenthesis) | |
{ | |
this._outputList.Add(this._stack.Pop()); | |
} | |
this._stack.Pop(); | |
} | |
else if (token._type == TokenType.Then || token._type == TokenType.Else) | |
{ | |
while (this._stack.Count != 0 && this._stack.Peek()._type != TokenType.If) | |
{ | |
this._outputList.Add(this._stack.Pop()); | |
} | |
} | |
else if (token._type == TokenType.Semicolon) | |
{ | |
while (this._stack.Count != 0 && this._stack.Peek()._type != TokenType.If && this._stack.Peek()._type != TokenType.While) | |
{ | |
this._outputList.Add(this._stack.Pop()); | |
} | |
} | |
else if (token._type == TokenType.End) | |
{ | |
if (this._stack.Count != 0 && (this._stack.Peek()._type == TokenType.If || this._stack.Peek()._type == TokenType.While)) | |
{ | |
this._stack.Pop( ); | |
} | |
/*while ( this._stack.Count != 0 && ( this._stack.Peek( )._type != TokenType.If || this._stack.Peek()._type == TokenType.While ) ) | |
{ | |
this._outputList.Add( this._stack.Pop( ) ); | |
} | |
this._stack.Pop( );*/ | |
} | |
else if ( this.isOperator(token) == true ) | |
{ | |
while ( this._stack.Count != 0 && this.priority( this._stack.Peek( ) ) >= this.priority( token ) ) | |
{ | |
this._outputList.Add( this._stack.Pop( ) ); | |
} | |
this._stack.Push( token ); | |
} | |
} | |
public void reversePolishNotation( ) | |
{ | |
for ( int i = 0; i < this._inputRPNlist.Count; i++ ) | |
{ | |
this.reversePolishNotationRun( this._inputRPNlist[i] ); | |
} | |
while ( this._stack.Count != 0 ) // if any operators remain in the stack, pop all & add to output list until stack is empty | |
{ | |
this._outputList.Add( this._stack.Pop( ) ); | |
} | |
} | |
public void printRPNoutputList() | |
{ | |
Console.WriteLine("\n\nReverse Polish Notation:\n"); | |
for (int i = 0; i < this._outputList.Count; i++) | |
{ | |
Console.Write("{0}", this._outputList[i]._value); | |
Console.Write(" "); | |
} | |
Console.WriteLine(); | |
} | |
public bool isOperator(Token token) | |
{ | |
if (token._type == TokenType.LeftParenthesis | |
|| token._type == TokenType.If | |
|| token._type == TokenType.RightParenthesis | |
|| token._type == TokenType.Then | |
|| token._type == TokenType.Else | |
|| token._type == TokenType.Assign | |
|| token._type == TokenType.Semicolon | |
|| token._type == TokenType.LessThan | |
|| token._type == TokenType.LessThanOrEqual | |
|| token._type == TokenType.GreaterThan | |
|| token._type == TokenType.GreaterThanOrEqual | |
|| token._type == TokenType.Equal | |
|| token._type == TokenType.NotEqual | |
|| token._type == TokenType.Plus | |
|| token._type == TokenType.Minus | |
|| token._type == TokenType.Times | |
|| token._type == TokenType.Div | |
|| token._type == TokenType.ReverseSign | |
|| token._type == TokenType.Power) | |
{ | |
return true; | |
} | |
else | |
{ | |
return false; | |
} | |
} | |
public int priority(Token token) | |
{ | |
if (token._type == TokenType.LeftParenthesis || token._type == TokenType.If || token._type == TokenType.While) | |
{ | |
return 0; | |
} | |
else if (token._type == TokenType.RightParenthesis || token._type == TokenType.Then || token._type == TokenType.Else) | |
{ | |
return 1; | |
} | |
else if (token._type == TokenType.Assign || token._type == TokenType.Semicolon) | |
{ | |
return 2; | |
} | |
else if (token._type == TokenType.LessThan || token._type == TokenType.LessThanOrEqual || token._type == TokenType.GreaterThan || token._type == TokenType.GreaterThanOrEqual || token._type == TokenType.Equal || token._type == TokenType.NotEqual) | |
{ | |
return 3; | |
} | |
else if (token._type == TokenType.Plus || token._type == TokenType.Minus) | |
{ | |
return 4; | |
} | |
else if (token._type == TokenType.Times || token._type == TokenType.Div || token._type == TokenType.Write || token._type == TokenType.Write2 || token._type == TokenType.ReverseSign) | |
{ | |
return 5; | |
} | |
else if (token._type == TokenType.Power) | |
{ | |
return 6; | |
} | |
else | |
{ | |
return -1; | |
} | |
} | |
public void run() | |
{ | |
Console.WriteLine("Syntax Analyzer:\n"); | |
if (this._lexer._mainTable[this._i]._type == TokenType.Program) | |
{ | |
(this._i)++; // 1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Begin) | |
{ | |
(this._i)++; // 2 | |
int l = this._lexer._mainTable[this._i]._line; | |
int i = this._i; // 2 | |
if (this._lexer._mainTable[this._lexer._mainTable.Count - 1]._type != TokenType.EndProgram) | |
{ | |
Console.WriteLine("KeyWord endProgram is missing. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._lexer._mainTable.Count - 1]._line, this._lexer._mainTable[this._lexer._mainTable.Count - 1]._value); | |
return; | |
} | |
if (this.checkOperators(this._i)) | |
{ | |
i = this._lexer._mainTable.Count - 1; | |
if (this._lexer._mainTable[i]._type == TokenType.EndProgram) | |
{ | |
//this._inputRPNlist.Add( new Token( TokenType.EndOfInput ) ); | |
if (this._syntaxMistakesAvailable == false) | |
{ | |
Console.WriteLine("There are no Syntax mistakes"); | |
} | |
} | |
else | |
{ | |
Console.WriteLine("KeyWord endProgram is missing. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._lexer._mainTable.Count - 1]._line, this._lexer._mainTable[this._lexer._mainTable.Count - 1]._value); | |
} | |
} | |
else | |
{ | |
//Console.WriteLine("Wrong list of operators. Line: {0}", l ); | |
} | |
} | |
else | |
{ | |
Console.WriteLine("KeyWord begin is missing. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
} | |
} | |
else | |
{ | |
Console.WriteLine("KeyWord program is missing. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
} | |
} | |
public bool checkOperators(int p) | |
{ | |
bool found = false; | |
if (this.checkOperator(this._i)) | |
{ | |
found = true; | |
if ((this._i + 1) != (this._lexer._mainTable.Count - 1)) | |
{ | |
(this._i)++; | |
} | |
if ((this._lexer._mainTable[(this._i) + 1]._type != TokenType.EndProgram) && (this._lexer._mainTable[this._i]._type != TokenType.End) && (this._lexer._mainTable[(this._i)]._type != TokenType.Else)) | |
{ | |
found = this.checkOperators(this._i); | |
} | |
if (this._lexer._mainTable[(this._i)]._type == TokenType.Else) | |
{ | |
(this._i)--; | |
} | |
} | |
return found; | |
} | |
public bool checkOperator(int p) | |
{ | |
bool found = false; | |
int i = p; // | |
if (this.checkAssignment(this._i) || this.checkInput(this._i) || this.checkOutput(this._i) || this.checkConditional(this._i) || this.checkLoop(this._i)) | |
{ | |
return true; | |
} | |
return found; | |
} | |
public bool checkAssignment(int p) | |
{ | |
bool found = false; | |
int myTemp = this._i; | |
if (this._lexer._mainTable[this._i]._type == TokenType.Identifier) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Assign) | |
{ | |
(this._i)++; // +2 | |
if (this.checkExpression(this._i)) | |
{ | |
(this._i)++; // +3 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Semicolon) | |
{ | |
for (int i = myTemp; i <= this._i; i++) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[i]); | |
} | |
return true; | |
} | |
else | |
{ | |
Console.WriteLine("Semicolon in assignment operator is missing. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i - 1]._line, this._lexer._mainTable[this._i - 1]._value); | |
(this._i) = (this._i) - 3; // 2 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Wrong or missing expression in assignment operator. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 2; // 2 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Assignment operator is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i)--; // 2 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkInput(int p) | |
{ | |
bool found = false; | |
int myTemp = this._i; | |
if (this._lexer._mainTable[this._i]._type == TokenType.Read) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.LeftParenthesis) | |
{ | |
(this._i)++; // +2 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Identifier) | |
{ | |
(this._i)++; // +3 | |
if (this._lexer._mainTable[this._i]._type == TokenType.RightParenthesis) | |
{ | |
(this._i)++; // +4 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Semicolon) | |
{ | |
for (int i = myTemp; i <= this._i; i++) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[i]); | |
} | |
found = true; | |
} | |
else | |
{ | |
Console.WriteLine("Semicolon in input operator is missing. Line: {0}", this._lexer._mainTable[this._i - 1]._line); | |
(this._i) = (this._i) - 4; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Right parenthesis in input operator is missing. Line: {0}", this._lexer._mainTable[this._i]._line); | |
(this._i) = (this._i) - 3; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Wrong or missing identifier in input operator. Line: {0}", this._lexer._mainTable[this._i]._line); | |
(this._i) = (this._i) - 2; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Left parenthesis in input operator is missing. Line: {0}", this._lexer._mainTable[this._i]._line); | |
(this._i) = (this._i) - 1; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkOutput(int p) | |
{ | |
bool found = false; | |
int myTemp = this._i; | |
if (this._lexer._mainTable[this._i]._type == TokenType.Write) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.LeftParenthesis) | |
{ | |
(this._i)++; // +2 | |
if (this.checkOutputList(this._i)) | |
{ | |
(this._i)++; // +3 | |
if (this._lexer._mainTable[this._i]._type == TokenType.RightParenthesis) | |
{ | |
(this._i)++; // +4 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Semicolon) | |
{ | |
for (int i = myTemp; i <= this._i; i++) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[i]); | |
} | |
return true; | |
} | |
else | |
{ | |
Console.WriteLine("Semicolon in output operator is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i - 1]._line, this._lexer._mainTable[this._i - 1]._value); | |
(this._i) = (this._i) - 4; // | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Right parenthesis in output operator is missing. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 3; // | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Wrong or missing output list in output operator. Line: {0}", this._lexer._mainTable[this._i]._line); | |
(this._i) = (this._i) - 2; // | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Left parenthesis in output operator is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i)--; // | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkLoop(int p) | |
{ | |
bool found = false; | |
int myTempToken1; | |
string myTempJumpToken1; | |
string myTempJumpToken2; | |
if (this._lexer._mainTable[this._i]._type == TokenType.Do) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.While) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
myTempJumpToken1 = "JumpToken" + (++StaticContainer.jumpTokenCounter); | |
this._inputRPNlist.Add(new Token(TokenType.JumpToken, myTempJumpToken1, this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 39)); | |
(this._i)++; // +2 | |
if (this._lexer._mainTable[this._i]._type == TokenType.LeftParenthesis) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
(this._i)++; // +3 | |
if (this.checkInequality(this._i)) | |
{ | |
(this._i)++; // +4 | |
if (this._lexer._mainTable[this._i]._type == TokenType.RightParenthesis) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
myTempToken1 = this._inputRPNlist.Count; | |
this._inputRPNlist.Add(new Token(TokenType.JumpZero, "jumpZero to ", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 38)); | |
(this._i)++; // +5 | |
if (this.checkOperator(this._i)) | |
{ | |
found = true; | |
(this._i)++; // 6 | |
if (this._lexer._mainTable[(this._i) + 1]._type != TokenType.End) | |
{ | |
found = this.checkOperator(this._i); | |
} | |
if (this._lexer._mainTable[(this._i) + 1]._type == TokenType.End) | |
{ | |
this._inputRPNlist.Add(new Token(TokenType.Jump, "jump to " + myTempJumpToken1, this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 37)); | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i + 1]); | |
myTempJumpToken2 = "JumpToken" + (++StaticContainer.jumpTokenCounter); | |
this._inputRPNlist.Add(new Token(TokenType.JumpToken, myTempJumpToken2, this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 39)); | |
this._inputRPNlist[myTempToken1]._value = this._inputRPNlist[myTempToken1]._value + myTempJumpToken2; | |
//--- | |
(this._i)++; | |
} | |
else | |
{ | |
return found; | |
} | |
} | |
return found; | |
} | |
else | |
{ | |
Console.WriteLine("Right parenthesis in loop operator is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 4; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Wrong or missing inequality expression in loop operator. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 3; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Left parenthesis in loop operator is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 2; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("KeyWord while is missing in loop operator. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 1; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkConditional(int p) | |
{ | |
bool found = false; | |
int myTempToken1; | |
int myTempToken2; | |
string myTempJumpToken1; | |
string myTempJumpToken2; | |
if (this._lexer._mainTable[this._i]._type == TokenType.If) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.LeftParenthesis) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
(this._i)++; // +2 | |
if (this.checkInequality(this._i)) | |
{ | |
(this._i)++; // +3 | |
if (this._lexer._mainTable[this._i]._type == TokenType.RightParenthesis) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
(this._i)++; // +4 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Then) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
(this._i)++; // +5 | |
myTempToken1 = this._inputRPNlist.Count; | |
this._inputRPNlist.Add(new Token(TokenType.JumpZero, "jumpZero to ", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 38)); | |
if (this.checkOperators(this._i)) | |
{ | |
(this._i)++; // +6 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Else) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
(this._i)++; // +7 | |
myTempToken2 = this._inputRPNlist.Count; | |
this._inputRPNlist.Add(new Token(TokenType.Jump, "jump to ", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 37)); | |
myTempJumpToken1 = "JumpToken" + (++StaticContainer.jumpTokenCounter); | |
this._inputRPNlist.Add(new Token(TokenType.JumpToken, myTempJumpToken1, this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 39)); | |
this._inputRPNlist[myTempToken1]._value = this._inputRPNlist[myTempToken1]._value + myTempJumpToken1; | |
if (this.checkOperators(this._i)) | |
{ | |
if (this._lexer._mainTable[this._i]._type == TokenType.End) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[this._i]); | |
myTempJumpToken2 = "JumpToken" + (++StaticContainer.jumpTokenCounter); | |
this._inputRPNlist.Add(new Token(TokenType.JumpToken, myTempJumpToken2, this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._column, 39)); | |
this._inputRPNlist[myTempToken2]._value = this._inputRPNlist[myTempToken2]._value + myTempJumpToken2; | |
found = true; | |
} | |
else | |
{ | |
Console.WriteLine("KeyWord end is missing in conditional operator. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 8; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Wrong list of operators in conditional operator. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 7; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("KeyWord else is missing in conditional operator. Line: {0}", this._lexer._mainTable[this._i]._line); | |
(this._i) = (this._i) - 6; | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Wrong list of operators in conditional operator. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 5; // 15 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("KeyWord then is missing in conditional operator. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 4; // 15 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Right parenthesis in conditional operator is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 3; // 15 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Wrong or missing inequality expression in conditional operator. Line: {0}. Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i) = (this._i) - 2; // 15 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("Left parenthesis in conditional operator is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
(this._i)--; // 15 | |
this._syntaxMistakesAvailable = true; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkExpression(int p) | |
{ | |
bool found = false; | |
if (this.checkMinusExpression(this._i) || this.checkTerm(this._i) || this.checkExpressionAndTerm(this._i) || this.checkParenthesisExpression(this._i)) | |
{ | |
found = true; | |
if (this._syntaxMistakesAvailable == true) | |
{ | |
return false; | |
} | |
if (this._lexer._mainTable[this._i + 1]._type == TokenType.Plus || this._lexer._mainTable[this._i + 1]._type == TokenType.Minus || this._lexer._mainTable[this._i + 1]._type == TokenType.Times || this._lexer._mainTable[this._i + 1]._type == TokenType.Div || this._lexer._mainTable[this._i + 1]._type == TokenType.Power) | |
{ | |
// toDo take Arithmetic operator | |
this._i = this._i + 2; | |
found = this.checkExpression(this._i); | |
} | |
} | |
return found; | |
} | |
public bool checkTerm(int p) | |
{ | |
bool found = false; | |
if (this._syntaxMistakesAvailable == true) | |
{ | |
return false; | |
} | |
if (this.checkMultiplier(this._i) || this.checkTermAndMultiplier(this._i)) | |
{ | |
found = true; | |
} | |
return found; | |
} | |
public bool checkMinusExpression(int p) | |
{ | |
bool found = false; | |
if (this._syntaxMistakesAvailable == true) | |
{ | |
return false; | |
} | |
int myTemp = this._i; | |
if (this._lexer._mainTable[this._i]._type == TokenType.Minus || this._lexer._mainTable[this._i]._type == TokenType.ReverseSign) | |
{ | |
(this._i)++; // +1 | |
if (this.checkExpression(this._i)) | |
{ | |
this._lexer._mainTable[myTemp]._type = TokenType.ReverseSign; | |
this._lexer._mainTable[myTemp]._value = "@"; | |
this._lexer._mainTable[myTemp]._lexemeСode = 35; | |
return true; | |
} | |
else | |
{ | |
this._i = this._i - 1; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkExpressionAndTerm(int p) | |
{ | |
bool found = false; | |
if (this._syntaxMistakesAvailable == true) | |
{ | |
return false; | |
} | |
if (this.checkExpression(this._i)) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Plus || this._lexer._mainTable[this._i]._type == TokenType.Minus) | |
{ | |
(this._i)++; // +2 | |
if (this.checkTerm(this._i)) | |
{ | |
return true; | |
} | |
else | |
{ | |
this._i = this._i - 2; | |
return false; | |
} | |
} | |
else | |
{ | |
this._i = this._i - 1; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkMultiplier(int p) | |
{ | |
bool found = false; | |
if (this._syntaxMistakesAvailable == true) | |
{ | |
return false; | |
} | |
if (this.checkPrimaryExpression(this._i) || this.checkMultiplierAndPrimaryExpression(this._i)) | |
{ | |
found = true; | |
} | |
return found; | |
} | |
public bool checkTermAndMultiplier(int p) | |
{ | |
bool found = false; | |
if (this.checkTerm(this._i)) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Times || this._lexer._mainTable[this._i]._type == TokenType.Div) | |
{ | |
(this._i)++; // +2 | |
if (this.checkMultiplier(this._i)) | |
{ | |
found = true; | |
} | |
else | |
{ | |
this._i = this._i - 2; | |
return false; | |
} | |
} | |
else | |
{ | |
this._i = this._i - 1; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkPrimaryExpression(int p) | |
{ | |
bool found = false; | |
if (this._syntaxMistakesAvailable == true) | |
{ | |
return false; | |
} | |
if (this._lexer._mainTable[this._i]._type == TokenType.Identifier || this._lexer._mainTable[this._i]._type == TokenType.Number || this.checkParenthesisExpression(this._i)) | |
{ | |
found = true; | |
} | |
return found; | |
} | |
public bool checkMultiplierAndPrimaryExpression(int p) | |
{ | |
bool found = false; | |
if (this.checkMultiplier(this._i)) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Power) | |
{ | |
(this._i)++; // +2 | |
if (this.checkPrimaryExpression(this._i)) | |
{ | |
return true; | |
} | |
else | |
{ | |
this._i = this._i - 1; | |
return false; | |
} | |
} | |
else | |
{ | |
this._i = this._i - 1; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkParenthesisExpression(int p) | |
{ | |
bool found = false; | |
if (this._syntaxMistakesAvailable == true) | |
{ | |
return false; | |
} | |
if (this._lexer._mainTable[this._i]._type == TokenType.LeftParenthesis) | |
{ | |
(this._i)++; // +1 | |
if (this.checkExpression(this._i)) | |
{ | |
(this._i)++; // +2 | |
if (this._lexer._mainTable[this._i]._type == TokenType.RightParenthesis) | |
{ | |
return true; | |
} | |
else | |
{ | |
Console.WriteLine("Right parenthesis in expression is missing. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
this._syntaxMistakesAvailable = true; | |
this._i = this._i - 2; | |
found = false; | |
} | |
} | |
else | |
{ | |
Console.WriteLine("There is mistake in parenthesis expression. Line: {0} Lexema: {1}", this._lexer._mainTable[this._i]._line, this._lexer._mainTable[this._i]._value); | |
this._i = this._i - 1; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkOutputList(int p) | |
{ | |
bool found = false; | |
if (this.checkOutputElements(this._i) || this.checkOutputElement(this._i)) | |
{ | |
found = true; | |
} | |
return found; | |
} | |
public bool checkOutputElement(int p) | |
{ | |
bool found = false; | |
if (this._lexer._mainTable[this._i]._type == TokenType.Identifier || this._lexer._mainTable[this._i]._type == TokenType.SymbolConstant) | |
{ | |
return true; | |
} | |
return found; | |
} | |
public bool checkOutputElements(int p) | |
{ | |
bool found = false; | |
int myTemp = this._i - 2; | |
if (this.checkOutputElement(this._i)) | |
{ | |
(this._i)++; // +1 | |
if (this._lexer._mainTable[this._i]._type == TokenType.Comma) | |
{ | |
(this._i)++; // +2 | |
if (this.checkOutputElement(this._i)) | |
{ | |
this._lexer._mainTable[myTemp]._type = TokenType.Write2; | |
this._lexer._mainTable[myTemp]._value = "write2"; | |
this._lexer._mainTable[myTemp]._lexemeСode = 36; | |
return true; | |
} | |
else | |
{ | |
this._i = this._i - 2; | |
return false; | |
} | |
} | |
else | |
{ | |
this._i = this._i - 1; | |
return false; | |
} | |
} | |
return found; | |
} | |
public bool checkInequality(int p) | |
{ | |
bool found = false; | |
int myTemp = this._i; | |
if (this.checkExpression(this._i)) | |
{ | |
this._i++; // +1 | |
if (this.checkInequalitySymbols(this._i)) | |
{ | |
this._i++; // +2 | |
if (this.checkExpression(this._i)) | |
{ | |
for (int i = myTemp; i <= this._i; i++) | |
{ | |
this._inputRPNlist.Add(this._lexer._mainTable[i]); | |
} | |
found = true; | |
} | |
else | |
{ | |
this._i = this._i - 2; | |
} | |
} | |
else | |
{ | |
(this._i)--; | |
} | |
} | |
return found; | |
} | |
public bool checkInequalitySymbols(int p) | |
{ | |
bool found = false; | |
int i = p; | |
if (this._lexer._mainTable[i]._type == TokenType.LessThan || this._lexer._mainTable[i]._type == TokenType.LessThanOrEqual || this._lexer._mainTable[i]._type == TokenType.GreaterThan || this._lexer._mainTable[i]._type == TokenType.GreaterThanOrEqual || this._lexer._mainTable[i]._type == TokenType.Equal || this._lexer._mainTable[i]._type == TokenType.NotEqual) | |
{ | |
found = true; | |
} | |
return found; | |
} | |
} | |
public enum TokenType | |
{ | |
// Identifires and literals | |
Program, // program | |
Begin, // begin | |
EndProgram, // endProgram | |
Read, // read | |
Write, // write | |
Write2, // write two arguments | |
Do, // do | |
While, // while | |
End, // end | |
If, // if | |
Then, // then | |
Else, // else | |
// ??? | |
Keyword, | |
Identifier, | |
Operator, | |
String, | |
Number, | |
Unrecognized, | |
SymbolConstant, | |
// Arithmetic operators | |
Plus, // + | |
Minus, // - | |
Times, // * | |
Div, // / | |
Power, // ↑ ^ | |
// Comparison operators | |
LessThan, // < | |
LessThanOrEqual, // <= | |
GreaterThan, // > | |
GreaterThanOrEqual, // >= | |
Equal, // == | |
NotEqual, // != | |
// Assignment operator | |
Assign, // := | |
// Parenthesis | |
LeftParenthesis, // ( | |
RightParenthesis, // ) | |
// | |
ReverseSign, // @ | |
Semicolon, // ; | |
Colon, // : | |
Comma, // , | |
Exclamation, // ! | |
Quotes, // " | |
Equals, // = | |
// | |
EndOfInput, | |
// Jump operators | |
Jump, // unconditional jump | |
JumpZero, // conditional jump | |
JumpToken // jump address | |
}; | |
public class Token | |
{ | |
public TokenType _type; | |
public string _value; | |
public int _calculationResult; | |
public int _line; | |
public int _column; | |
public int _lexemeСode; | |
public int _indexInTable; | |
public Token(TokenType type, string value, int line, int column, int lexemeСode) | |
{ | |
_type = type; | |
_value = value; | |
_calculationResult = 0; | |
_line = line; | |
_column = column; | |
_lexemeСode = lexemeСode; | |
_indexInTable = 0; | |
} | |
public Token(TokenType type, string value, int calculationResult, int line, int column, int lexemeСode) | |
{ | |
_type = type; | |
_value = value; | |
_calculationResult = calculationResult; | |
_line = line; | |
_column = column; | |
_lexemeСode = lexemeСode; | |
_indexInTable = 0; | |
} | |
public Token(TokenType type) | |
{ | |
_type = type; | |
_value = type.ToString(); | |
_calculationResult = 0; | |
_line = 10000; | |
_column = 10000; | |
_lexemeСode = 10000; | |
_indexInTable = 10000; | |
} | |
public string toString() | |
{ | |
return String.Format("{0, -20}{1, -10} line {2, 5} \tcolumn {3, 5}", this._type.ToString(), this._value.ToString(), this._line, this._column); | |
} | |
} | |
public class Lexer | |
{ | |
public string _input; | |
public int _position; | |
public int _line; | |
public int _column; | |
public List<Token> _mainTable = new List<Token>(); | |
public List<Token> _identifierTable = new List<Token>(); | |
public List<Token> _constantTable = new List<Token>(); | |
public List<Token> _symbolTable = new List<Token>(); | |
public Lexer(string input) | |
{ | |
_input = input; | |
_position = 0; | |
_line = 1; | |
_column = 1; | |
} | |
public void printIdentifierTable() | |
{ | |
Console.WriteLine("\nLexical Analyzer:"); | |
Console.WriteLine("\n\n\tIdentifier Table"); | |
Console.WriteLine("+--------------------+-----+"); | |
Console.WriteLine("|{0, -20}|{1, 5}|", "Name", "Index"); | |
Console.WriteLine("+--------------------+-----+"); | |
int count = 0; | |
foreach (Token x in this._identifierTable) | |
{ | |
count++; | |
Console.WriteLine("|{0, -20}|{1, 5}|", x._value, count); | |
} | |
Console.WriteLine("+--------------------+-----+"); | |
} | |
public void printConstantTable() | |
{ | |
Console.WriteLine("\n\n\tConstant Table"); | |
Console.WriteLine("+--------------------+-----+"); | |
Console.WriteLine("|{0, -20}|{1, 5}|", "Substring", "Index"); | |
Console.WriteLine("+--------------------+-----+"); | |
int count = 0; | |
foreach (Token x in this._constantTable) | |
{ | |
count++; | |
Console.WriteLine("|{0, -20}|{1, 5}|", x._value, count); | |
} | |
Console.WriteLine("+--------------------+-----+"); | |
} | |
public void printSymbolTable() | |
{ | |
Console.WriteLine("\n\n\tSymbol constant Table"); | |
Console.WriteLine("+------------------------------------------------------------+-----+"); | |
Console.WriteLine("|{0, -60}|{1, 5}|", "Symbol constant", "Index"); | |
Console.WriteLine("+------------------------------------------------------------+-----+"); | |
int count = 0; | |
foreach (Token x in this._symbolTable) | |
{ | |
count++; | |
Console.WriteLine("|{0, -60}|{1, 5}|", x._value, count); | |
} | |
Console.WriteLine("+------------------------------------------------------------+-----+"); | |
} | |
public void printMainTable() | |
{ | |
Console.WriteLine("\n\n\tMain Table"); | |
Console.WriteLine("+------------------------------------------------------------------+-----------+---------------+"); | |
Console.WriteLine("|{0, -5}|{1, -60}|{2, 11}|{3, 15}|", "Line", "\tSubstring", "Lexeme Сode", "Index in tables"); | |
Console.WriteLine("+------------------------------------------------------------------+-----------+---------------+"); | |
foreach (Token x in this._mainTable) | |
{ | |
string indexInTable = ""; | |
if (x._indexInTable != 0) | |
{ | |
indexInTable = x._indexInTable.ToString(); | |
} | |
Console.WriteLine("|{0, 5}|{1, -60}|{2, 11}|{3, 15}|", x._line, x._value, x._lexemeСode, indexInTable); | |
Console.WriteLine("+------------------------------------------------------------------+-----------+---------------+"); | |
} | |
Console.WriteLine(); | |
} | |
public Token nextToken() | |
{ | |
if (this._position >= this._input.Length) | |
{ | |
return new Token(TokenType.EndOfInput); | |
} | |
this.skipWhitespacesAndNewLines(); | |
char character = this._input[_position]; | |
if (Char.IsLetter(character)) | |
{ | |
return this.recognizeIdentifier(); | |
} | |
if (Char.IsDigit(character)) | |
{ | |
return this.recognizeNumber(); | |
} | |
if (character == '+' || character == '-' || character == '*' || character == '/' || character == '^' || character == '!' || character == ':' || character == '<' || character == '=' || character == '>' || character == '@') | |
{ | |
return this.recognizeOperator(); | |
} | |
if (character == '(' || character == ')') | |
{ | |
return this.recognizeParenthesis(); | |
} | |
if (character == ';' || character == ',' || character == '"') | |
{ | |
return this.recognizeSymbol(); | |
} | |
return new Token(TokenType.Unrecognized, character.ToString(), _line, _column, 0); | |
} | |
public void skipWhitespacesAndNewLines() | |
{ | |
while (this._position < this._input.Length && Char.IsWhiteSpace(this._input[this._position])) | |
{ | |
this._position += 1; | |
if (this._input[this._position - 1] == '\n') | |
{ | |
this._line += 1; | |
this._column = 0; | |
} | |
else | |
{ | |
this._column += 1; | |
} | |
} | |
} | |
public Token recognizeIdentifier() | |
{ | |
string identifier = ""; | |
int position = this._position; | |
int line = this._line; | |
int column = this._column; | |
while (position < this._input.Length) | |
{ | |
char character = this._input[position]; | |
if (!(Char.IsLetter(character) || Char.IsDigit(character))) | |
{ | |
break; | |
} | |
identifier += character; | |
position += 1; | |
} | |
this._position += identifier.Length; | |
this._column += identifier.Length; | |
if (identifier == "program") | |
{ | |
return new Token(TokenType.Program, identifier, line, column, 1); | |
} | |
else if (identifier == "begin") | |
{ | |
return new Token(TokenType.Begin, identifier, line, column, 2); | |
} | |
else if (identifier == "endProgram") | |
{ | |
return new Token(TokenType.EndProgram, identifier, line, column, 3); | |
} | |
else if (identifier == "read") | |
{ | |
return new Token(TokenType.Read, identifier, line, column, 4); | |
} | |
else if (identifier == "write") | |
{ | |
return new Token(TokenType.Write, identifier, line, column, 5); | |
} | |
else if (identifier == "do") | |
{ | |
return new Token(TokenType.Do, identifier, line, column, 6); | |
} | |
else if (identifier == "while") | |
{ | |
return new Token(TokenType.While, identifier, line, column, 7); | |
} | |
else if (identifier == "end") | |
{ | |
return new Token(TokenType.End, identifier, line, column, 8); | |
} | |
else if (identifier == "if") | |
{ | |
return new Token(TokenType.If, identifier, line, column, 9); | |
} | |
else if (identifier == "then") | |
{ | |
return new Token(TokenType.Then, identifier, line, column, 10); | |
} | |
else if (identifier == "else") | |
{ | |
return new Token(TokenType.Else, identifier, line, column, 11); | |
} | |
else | |
{ | |
if ( this._identifierTable.Exists( x => x._value == identifier ) ) | |
{ | |
Token myTempToken = this._identifierTable.Find( x=> x._value == identifier ); | |
return myTempToken; | |
} | |
else | |
{ | |
return new Token( TokenType.Identifier, identifier, line, column, 33 ); | |
} | |
} | |
} | |
public Token recognizeNumber() | |
{ | |
int number = 0; | |
int position = this._position; | |
int line = this._line; | |
int column = this._column; | |
while (position < this._input.Length) | |
{ | |
char character = this._input[position]; | |
if (!Char.IsDigit(character)) | |
{ | |
break; | |
} | |
number = 10 * number + (int)Char.GetNumericValue(character); | |
position += 1; | |
this._position += 1; | |
this._column += 1; | |
} | |
return new Token(TokenType.Number, number.ToString(), number, line, column, 34); | |
} | |
public Token recognizeOperator() | |
{ | |
char character = this._input[_position]; | |
if (character == '<' || character == '=' || character == '>' || character == ':' || character == '!') | |
{ | |
return this.recognizeComparisonOperator(); | |
} | |
if (character == '+' || character == '-' || character == '*' || character == '/' || character == '^' || character == '@') | |
{ | |
return this.recognizeArithmeticOperator(); | |
} | |
return new Token(TokenType.Operator); | |
} | |
public Token recognizeComparisonOperator() | |
{ | |
int position = this._position; | |
int line = this._line; | |
int column = this._column; | |
char character = this._input[position]; | |
char lookahead; | |
if ((position + 1) < this._input.Length) | |
{ | |
lookahead = this._input[position + 1]; | |
} | |
else | |
{ | |
lookahead = ' '; | |
} | |
bool isLookaheadEqualSymbol = (lookahead != ' ') && (lookahead == '='); | |
this._position += 1; | |
this._column += 1; | |
if (isLookaheadEqualSymbol) | |
{ | |
this._position += 1; | |
this._column += 1; | |
} | |
switch (character) | |
{ | |
case '>': | |
if (isLookaheadEqualSymbol) | |
{ | |
return new Token(TokenType.GreaterThanOrEqual, ">=", line, column, 20); | |
} | |
else | |
{ | |
return new Token(TokenType.GreaterThan, ">", line, column, 19); | |
} | |
case '<': | |
if (isLookaheadEqualSymbol) | |
{ | |
return new Token(TokenType.LessThanOrEqual, "<=", line, column, 18); | |
} | |
else | |
{ | |
return new Token(TokenType.LessThan, "<", line, column, 17); | |
} | |
case '=': | |
if (isLookaheadEqualSymbol) | |
{ | |
return new Token(TokenType.Equal, "==", line, column, 21); | |
} | |
else | |
{ | |
return new Token(TokenType.Equals, "=", line, column, 24); | |
} | |
case ':': | |
if (isLookaheadEqualSymbol) | |
{ | |
return new Token(TokenType.Assign, ":=", line, column, 23); | |
} | |
else | |
{ | |
return new Token(TokenType.Colon, ":", line, column, 28); | |
} | |
case '!': | |
if (isLookaheadEqualSymbol) | |
{ | |
return new Token(TokenType.NotEqual, "!=", line, column, 22); | |
} | |
else | |
{ | |
return new Token(TokenType.Exclamation, "!", line, column, 30); | |
} | |
default: | |
break; | |
} | |
return new Token(TokenType.Operator); | |
} | |
public Token recognizeArithmeticOperator() | |
{ | |
int position = this._position; | |
int line = this._line; | |
int column = this._column; | |
char character = this._input[position]; | |
this._position += 1; | |
this._column += 1; | |
switch (character) | |
{ | |
case '+': | |
return new Token(TokenType.Plus, "+", line, column, 12); | |
break; | |
case '-': | |
return new Token(TokenType.Minus, "-", line, column, 13); | |
break; | |
case '*': | |
return new Token(TokenType.Times, "*", line, column, 14); | |
break; | |
case '/': | |
return new Token(TokenType.Div, "/", line, column, 15); | |
break; | |
case '^': | |
return new Token(TokenType.Power, "^", line, column, 16); | |
break; | |
case '@': | |
return new Token(TokenType.ReverseSign, "@", line, column, 35); | |
break; | |
default: | |
break; | |
} | |
return new Token(TokenType.Operator); | |
} | |
public Token recognizeParenthesis() | |
{ | |
int position = this._position; | |
int line = this._line; | |
int column = this._column; | |
char character = this._input[position]; | |
this._position += 1; | |
this._column += 1; | |
if (character == '(') | |
{ | |
return new Token(TokenType.LeftParenthesis, "(", line, column, 25); | |
} | |
return new Token(TokenType.RightParenthesis, ")", line, column, 26); | |
} | |
public Token recognizeSymbol() | |
{ | |
int position = this._position; | |
int line = this._line; | |
int column = this._column; | |
char character = this._input[position]; | |
this._position += 1; | |
this._column += 1; | |
if (character == ';') | |
{ | |
return new Token(TokenType.Semicolon, ";", line, column, 27); | |
} | |
else if (character == ',') | |
{ | |
return new Token(TokenType.Comma, ",", line, column, 29); | |
} | |
return this.recognizeText(); | |
} | |
public Token recognizeText() | |
{ | |
string text = "\""; | |
int position = this._position; | |
int line = this._line; | |
int column = this._column; | |
while (position < this._input.Length - 1) | |
{ | |
char character = this._input[position]; | |
text += character; | |
if (this._input[position + 1] == '"') | |
{ | |
text += '"'; | |
break; | |
} | |
position += 1; | |
} | |
this._position += text.Length - 1; | |
this._column += text.Length - 1; | |
return new Token(TokenType.SymbolConstant, text, line, column, 32); | |
} | |
public void allTokens() | |
{ | |
Token token = this.nextToken(); | |
while (token._type != TokenType.EndOfInput) | |
{ | |
this._mainTable.Add(token); | |
if (token._type == TokenType.Identifier) | |
{ | |
if (!this._identifierTable.Exists(x => x._value == token._value)) | |
{ | |
this._identifierTable.Add(token); | |
token._indexInTable = this._identifierTable.Count; | |
} | |
else | |
{ | |
token._indexInTable = this._identifierTable.FindIndex(0, x => x._value == token._value) + 1; | |
} | |
} | |
if (token._type == TokenType.Number) | |
{ | |
if (!this._constantTable.Exists(x => x._value == token._value)) | |
{ | |
this._constantTable.Add(token); | |
token._indexInTable = this._constantTable.Count; | |
} | |
else | |
{ | |
token._indexInTable = this._constantTable.FindIndex(0, x => x._value == token._value) + 1; | |
} | |
} | |
if (token._type == TokenType.SymbolConstant) | |
{ | |
if (!this._symbolTable.Exists(x => x._value == token._value)) | |
{ | |
this._symbolTable.Add(token); | |
token._indexInTable = this._symbolTable.Count; | |
} | |
else | |
{ | |
token._indexInTable = this._symbolTable.FindIndex(0, x => x._value == token._value) + 1; | |
} | |
} | |
token = this.nextToken(); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
program | |
begin | |
write("please, enter min value of range"); | |
read(lhs); | |
write("please, enter max value of range"); | |
read(rhs); | |
if (rhs <= lhs) then | |
do while ( rhs <= lhs ) | |
write("please, enter max value of range greater then min value"); | |
read(rhs); | |
end | |
range := rhs - lhs ; | |
else | |
range := rhs - lhs ; | |
end | |
write("range = ", range); | |
endProgram |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Граматика мови | |
<програма>::= program begin <список операторів> endProgram | |
<список операторів>::= <оператор> | <cписок операторів> <оператор> | |
<оператор>::= <присвоювання> | <введення> | <вивід> | <цикл> | <умовний перехід> | |
<присвоювання>::= <ідентифікатор> := <вираз>; | |
<ідентифікатор>::= <буква> | <ідентифікатор><буква> | <ідентифікатор><цифра> | |
<буква>::= q|w|e|r|t|y|u|i|o|p|a|s|d|f|g|h|j|k|l|z|x|c|v|b|n|m | |
<цифра>::= 0|1|2|3|4|5|6|7|8|9 | |
<вираз>::= -<вираз> | <вираз>+<терм> | <вираз>-<терм> | <терм> | |
<терм>::= <терм>*<множник> | <терм>/<множник> | <множник> | |
<множник>::= <множник>↑<первинний вираз> | <первинний вираз> | |
<первинний вираз>::= <ідентифікатор> | <константа> | (<вираз>) | |
<константа>::= <цифра> | <константа><цифра> | |
<введення>::= read(<ідентифікатор>); | |
<вивід>::= write(<список виводу>); | |
<список виводу>::= <елемент виводу> | <елемент виводу>, <елемент виводу> | |
<елемент виводу>::= <ідентифікатор> | "<текст>" | |
<текст>::= <символ> | <текст><символ> | |
<символ>::= <буква> | <цифра> | = | |
<цикл>::= do while (<відношення>) <список операторів> end | |
<відношення>::= <вираз><знак відношення><вираз> | |
<знак відношення>::= < | <= | > | >= | == | != | |
<умовний перехід>::= if (<відношення>) then <список операторів> else <список операторів>end |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Таблиця лексем | |
Лексема Код | |
Identifiers and literals | |
Program program 1 | |
Begin begin 2 | |
EndProgram endProgram 3 | |
Read read 4 | |
Write write 5 | |
Write2 write2 36 | |
Do do 6 | |
While while 7 | |
End end 8 | |
If if 9 | |
Then then 10 | |
Else else 11 | |
Arithmetic operators | |
Plus + 12 | |
Minus - 13 | |
Times * 14 | |
Div / 15 | |
Power ^ 16 | |
Comparison operators | |
LessThan < 17 | |
LessThanOrEqual <= 18 | |
GreaterThan > 19 | |
GreaterThanOrEqual >= 20 | |
Equal == 21 | |
NotEqual != 22 | |
Assignment operator | |
Assign := 23 | |
Equals = 24 | |
Parenthesis | |
LeftParenthesis ( 25 | |
RightParenthesis ) 26 | |
ReverseSign @ 35 | |
Semicolon ; 27 | |
Colon : 28 | |
Comma , 29 | |
Exclamation ! 30 | |
Quotes " 31 | |
SymbolConstant символьна константа 32 | |
Identifier ідентифікатор 33 | |
Number константа 34 | |
Jump operators | |
Jump jump 37 | |
JumpZero jumpZero 38 | |
JumpToken jumpToken 39 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Таблиця приорітетів | |
Лексема Приорітет | |
( 0 | |
if 0 | |
while 0 | |
) 1 | |
then 1 | |
else 1 | |
:= 2 | |
; 2 | |
< 3 | |
<= 3 | |
> 3 | |
>= 3 | |
== 3 | |
!= 3 | |
+ 4 | |
- 4 | |
* 5 | |
/ 5 | |
write 5 | |
write2 5 | |
@ 5 | |
^ 6 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment