65.9K
CodeProject 正在变化。 阅读更多。
Home

计算引擎 1.3

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.79/5 (12投票s)

2009年4月14日

CPOL

2分钟阅读

viewsIcon

43157

downloadIcon

821

计算引擎是一个解析器和解释器,可以用来构建业务规则引擎。 它允许使用数学和布尔表达式、操作数函数、变量、变量赋值、注释和短路求值。 还包括一个语法编辑器。

引言

这是对一篇优秀文章 计算引擎 的更新,作者是 Donald Snowdy

背景

我对这篇文章做了一些修改,使它成为一个典型的 C 编译器。 这是一个制作编译器的良好起点。 稍作修改,您就可以完成它,使其成为真正的 C 编译器!!

RPN-逆波兰表示法

if”关键字检查语句的 truefalse 状态,并决定运行时指针应该跳转到哪里。这个编译器需要特定的字符来作为标志使用,如图 1 所示。“if”有三组状态

  1. Token_if_True:指的是“if”语句的结尾,如果语句为 True,此时为 ')',运行时指针继续它的旅程,直到它遇到它的结束点并跳转到结束点。
  2. Token_IF_False:如果语句失败,运行时指针跳转到失败点。
  3. Token_IF_END:如果语句完成了它的 True Block 或 Fail Block,运行时跳转到 EndPoint

在 RPN 选项卡中,您可以看到所有与编译代码相关的令牌

版本控制

版本 变更
1.1 使用括号表示函数 sin[3*3.14] --> sin(3*3.14),并免费使用方括号以作其他用途 完成 / 测试通过
1.2 将等式从 = 更改为 == 更像 C#,并将赋值运算符从 := 更改为 = 完成 / 测试通过
1.3 添加 if( 语句作为比较函数和相关处理 完成 / 测试中
1.4 添加 for( 语句作为函数和相关处理 待办事项
1.5 添加函数声明和块处理,包含所有参数的推送和弹出以添加执行 待办事项

Using the Code

if”处理

下面的代码定位了我用作标志的 if 相关字符,并且位于制作 RPN 队列函数之后,以便您可以确保没有要添加到令牌队列列表中的令牌。 此时,队列的所有位置都是固定的,因此您可以使用指向队列的指针作为行代码。 例如,如果您想跳转到某个位置,您可以在“if”中使用此数字,计算机验证该语句,如果该语句为 True,则继续该过程,并且当 True 块完成后,计算机必须跳转到 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(")
{
//tok.TokenType = TokenType.Token_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 == "}") //E
{
if (isTrueBlock.Peek() == true)
{
if (i + 1 >= rpn_queue.Count || rpn_queue[i + 1].TokenName != "else")
{///E&F
tok.TokenType = TokenType.Token_IF_FalseAndEnd;
tok.IF_FirstLevel = IF.Peek();
isTrueBlock.Pop();
IF.Peek().EndPosition = i;
IF.Pop();
}
}
else
{ ///E
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 == ";") //E
{
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"))
{///E&F
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")
{ ///E
isTrueBlock.Pop();
Else.Pop();
tok.TokenType = TokenType.Token_IF_End;
IF.Peek().EndPosition = i ;
IF.Pop();
}
}
Element.Push(tok);
}
}
}

关注点

编写编译器是我的一个梦想,因为当我觉得标准编译器有限制时,我可以做任何我想做的事情。 如果我完成这个,我可以为所有类型的 IC 编写一个通用编译器,例如 Atmel AtMega / PIC 系列,并完成我自己的 PLC。

有关我和我的项目的更多信息,请访问 HexWay.com

© . All rights reserved.