Introduction
This is an update to a great article Evaluation Engine by Donald Snowdy.
Background
There are some changes that I made to the article that makes it a typical C-Compiler. It is a good starting point for making a compiler. With a few changes, you can complete it as a real C-Compiler !!
RPN-Reverse Polish Notation
The "if
" keyword checks the true
or false
state of a statement and decides where the runtime pointer should jump. This compiler needs specific characters to use them as flags as you see in figure 1. "if
" has three set of states:
Token_if_True
: Refers to end of "if
" statement which is ')
' at this point if the statement was True
runtime pointer continues on its journey until it meets its End Point and jumps to End Point.Token_IF_False
: If the statement failed, runtime Pointer jumps to Fail Point.Token_IF_END
: If statement finished its True Block or Fail Block, runtime jump to EndPoint
In the RPN tab, you can see all tokens related to the compiled code:
Versioning
Version | Changes | |
1.1 | Using parenthesis for functions sin[3*3.14] -- > sin(3*3.14) and free square brackets for further uses | Done / Tested OK |
1.2 | Changing equation from = to == more C# like and changing assignment operator from := to = | Done / Tested OK |
1.3 | Adding if( statement as a function of comparison and related handling | Done / Testing |
1.4 | Adding for( statement as a function and related handling | To Do |
1.5 | Adding Function Declarative and block handling with all parameters push and pops to add for execution | To Do |
Using the Code
"if
" handling:
The code below locates if
-related characters that I used as a flag and are located right after making RPN Queue function so that you can make sure that there is no token to be added to the list of token Queue. At this point, all positions of Queue are fixed so you can use the pointer to the queue as a line code. For instance, if you want to jump to a location you can use this number in "if
" computer verify the statement and if the statement is True
, continue the process and as the True
block is finished, the computer must jump to finishing point of if
:
if (this.AnyErrors == false) MakeRPNQueue();
Support.ExQueue<int> pos = new Support.ExQueue<int>();
Stack<TokenItem> BlockEnd = new Stack<TokenItem>();
IF = new Stack<TokenItem>();
Stack<TokenItem> Else = new Stack<TokenItem>();
Stack<TokenItem> Element = new Stack<TokenItem>();
Stack<bool> isOpen = new Stack<bool>();
Stack<bool> isTrueBlock = new Stack<bool>();
for (int i = 0; i < rpn_queue.Count; i++)
{
TokenItem tok = rpn_queue[i];
if (tok.TokenName == "if(")
{
isTrueBlock.Push(true);
Element.Push(tok);
IF.Push(tok);
}
if (tok.TokenName == "{")
{
Element.Push(tok);
tok.TokenType = TokenType.LeftCurlyBracket;
}
if (tok.IF_FirstLevel != null && tok.TokenName == "]")
{
if (!(isTrueBlock.Peek() == true && tok.TokenName == "{"))
{
if (isTrueBlock.Peek())
{
tok.TokenType = TokenType.Token_if_True;
tok.IF_FirstLevel.TruePosition = i;
Element.Push(tok);
}
}
}
if (tok.TokenName == "else")
{
Element.Push(tok);
Else.Push(tok);
tok.IF_FirstLevel = IF.Peek();
isTrueBlock.Pop();
isTrueBlock.Push(false);
IF.Peek().FalsePosition = i;
tok.TokenType = TokenType.Token_IF_False;
}
if (tok.TokenName == "}")
{
if (isTrueBlock.Peek() == true)
{
if (i + 1 >= rpn_queue.Count || rpn_queue[i + 1].TokenName != "else")
{tok.TokenType = TokenType.Token_IF_FalseAndEnd;
tok.IF_FirstLevel = IF.Peek();
isTrueBlock.Pop();
IF.Peek().EndPosition = i;
IF.Pop();
}
}
else
{ isTrueBlock.Pop();
tok.IF_FirstLevel = IF.Peek();
tok.IF_FirstLevel.EndPosition = i;
Else.Pop();
tok.TokenType = TokenType.Token_IF_End;
}
Element.Push(tok);
}
if (tok.TokenName == ";")
{
if(Element.Count>0)
if ( Element.Peek().TokenName == "]" || Element.Peek().TokenName == "else")
{
if (isTrueBlock.Peek() == true)
{
if ((i + 1 >= rpn_queue.Count && Element.Peek().TokenName != "else") ||
(i + 1 < rpn_queue.Count && rpn_queue[i + 1].TokenName != "else"))
{tok.TokenType = TokenType.Token_IF_FalseAndEnd;
isTrueBlock.Pop();
IF.Peek().EndPosition = i;
IF.Peek().FalsePosition = i;
IF.Pop();
}
}
else
{
if (isTrueBlock.Count != 0 && Element.Peek().TokenName == "else")
{ isTrueBlock.Pop();
Else.Pop();
tok.TokenType = TokenType.Token_IF_End;
IF.Peek().EndPosition = i ;
IF.Pop();
}
}
Element.Push(tok);
}
}
}
Points of Interest
Writing a compiler was a dream for me because I could do anything I wanted when I felt the limitation of standard compiler. If I finish this, I can write a Universal compiler for all sorts of ICs such as Atmel AtMega / PIC families and complete my own PLC.
For more information about me and my project, please visit HexWay.com.