我正在寻找一种可以解决如下内容的语言解析器:
(x=7 OR y=1) AND (x>0)
我正在考虑使用ANTLR Parser Generator。在更高级的.NET框架(.NET 3.5,.NET 4.0)中是否有更简单的语言分析器?
答案 0 :(得分:4)
如果问题只是涉及monadic和binary运算符,括号,变量值和常量操作数的表达式,则可以编写一个递归下降解析器/求值器,它将同时解析和计算表达式。无需建造树木或IL或......
[如果你需要编写更复杂的语法,如语句和方法,你需要一个更复杂的解析器,然后解析器生成器得到回报]
对于一个表达式,您可以直接从BNF为表达式编写递归下降解析器。确保你 第一个左因子是每个规则的共性,例如,不是
SUM = TERM '+' TERM ;
SUM = TERM '-' TERM ;
但
SUM = TERM ( '+' TERM | '-' TERM ) ;
对于每个左侧非终结符,创建一个(可能是递归的)子例程,将索引放入要解析的字符串中,返回表达式的值(假设为float),或者抛出(语法)错误。对于每个右侧令牌,您编写测试代码;如果令牌不存在,它将控制传递给替代,或者如果没有其他替代方法则抛出语法错误。如果令牌存在,则评估令牌:如果终值(例如,数字或可变量)获得该值并推进输入;如果是非终结符,则调用它以查看是否存在该语法;如果一个操作员,只是忽略它但推进输入。如果您的测试与右侧的所有元素匹配,请计算表达式结果并将其返回。
所以对于语法:
EXP = SUM ;
SUM = TERM ( '+' TERM | '-' TERM ) ;
TERM = PRIMARY ( '*' PRIMARY | '/' PRIMARY ) ;
PRIMARY = '-' PRIMARY | '(' EXP ')' | NUMBER | VARIABLE ;
给定包含表达式的字符INPUT缓冲区, 和全局变量I是INPUT的索引,代码大致是:
float EXP()
{ return SUM();
}
float SUM()
{ float t=TERM();
if MATCH("+") return t+TERM();
if MATCH("-") return t-TERM();
throw SYNTAXERROR;
}
float TERM()
{ float t= PRIMARY();
if MATCH("*") return t*PRIMARY();
if MATCH("/") return t/PRIMARY();
throw SYNTAXERROR;
}
float PRIMARY()
{ float t;
if MATCH("-") return -PRIMARY();
if MATCH("(")
{ t=EXP();
if MATCH(")") return t;
else throw SYNTAXERROR
}
try t=NUMBER();
catch SYNTAXERROR
return VARIABLE();
endtry
}
float NUMBER() // simple float input conversion
{ float t=0;
fractiondigits=0;
exponent=0;
switch INPUT(I)
{ case "0".."9":
{ t=t*10+INPUT(I)-"0"; I++;
while ISDIGIT(INPUT(I))
{ t=t*10+INPUT(I)-"0"; I++ }
if MATCH(".")
goto collect_fraction;
else goto collect_exponent
}
case ".": goto collect_fraction;
default: throw SYNTAXERROR
}
collect_fraction:
while ISDIGIT(INPUT(I))
{ t=t*10+INPUT(I)-"0"; I++; fraction_digits++; }
collect_exponent:
if MATCH("E")
{ sign=false;
if MATCH("-") sign=true;
if !ISDIGIT(INPUT(I)) throw SYNTAXERROR;
while ISDIGIT(INPUT(I))
{ exponent=exponent*10+INPUT(I)-"0"; I++; }
if sign=true then exponenent=-exponent;
}
return t*10^(exponent-fractiondigits);
}
float VARIABLE() // handles single letter variable names.
{ if ISLETTER(INPUT(I))
{ I++;
return VARIABLEVALUE[INPUT(I)-"A"]
}
else throw SYNTAXERROR
}
boolean MATCH(c: char)
{ if INPUT(I)==c
{ I++;
return true;
}
else return false
您显然希望为要评估的表达式编写语法。但假设您只添加关系和AND,OR和NOT运算符,遵循此样式,您需要大约30分钟来编写整个代码。
这不考虑输入表达式如何被收集到INPUT缓冲区中,也没有解决变量如何得到值的问题;我假设变量名称到值的映射已经提前以某种方式神奇地填充。如果你想允许简单的赋值和表达式,只需通过添加一个允许赋值的规则来扩展BNF,例如,
EXP = VARIABLE ':=' EXP ;
处理分配需要一些技巧:当您匹配各个部分并发现VARIABLE时,您需要一种方法来捕获变量名称(修改VARAIBLE以记住全局变量名称),以及已识别分配规则的语法,将变量名称的映射更新为已收集的值。
浮点输入代码是一个hack,并且可以产生稍微不正确的输入值(但它很容易编码:)如果你想要更精确的浮点输入转换,你应该简单地收集构成浮点数常量的字符,并且然后将它们交给库字符串到浮点转换例程。
答案 1 :(得分:0)
如果您只需要像示例中那样的简单表达式,则可以使用NCalc。快速和容易使用。
答案 2 :(得分:0)
您可以在示例中查看Irony和示例表达式评估程序。
并here's a good article开始(如果你知道定义语法的基础知识,你会很快准备好):
答案 3 :(得分:-1)
对于给出的简单表达式,我会写一个递归下降解析器。首先写出你的BNF,然后编写代码。您可以在评估方面采用以下三种方法之一:
我选择(1),因为这是最简单的方法。