我们有很少的vb6代码片段(唯一使用的是功能的子集),这些代码片段得到了非程序员的支持。这些被称为规则。对于编写这些内容的人来说,他们很难调试,所以有人编写了一种add hoc解析器,能够评估子表达式,从而更好地显示问题所在。
这个addhoc解析器非常糟糕,并没有真正起作用。所以我试着写一个真正的解析器(因为我手工编写它(没有解析器生成器,我可以用vb6后端理解)我想用递归正确的解析器)。我不得不对语法进行反向工程,因为我能找到任何东西。 (事实上,我发现了一些http://www.notebar.com/GoldParserEngine.html,但它的LALR和它的方式比我需要的更大)
这是VB子集的语法。
<Rule> ::= expr rule | e
<Expr> ::= ( expr )
| Not_List CompareExpr <and_or> expr
| Not_List CompareExpr
<and_or> ::= Or | And
<Not_List> ::= Not Not_List | e
<CompareExpr> ::= ConcatExpr comp CompareExpr
|ConcatExpr
<ConcatExpr> ::= term term_tail & ConcatExpr
|term term_tail
<term> ::= factor factor_tail
<term_tail> ::= add_op term term_tail | e
<factor> ::= add_op Value | Value
<factor_tail> ::= multi_op factor factor_tail | e
<Value> ::= ConstExpr | function | expr
<ConstExpr> ::= <bool> | number | string | Nothing
<bool> ::= True | False
<Nothing> ::= Nothing | Null | Empty
<function> ::= id | id ( ) | id ( arg_list )
<arg_list> ::= expr , arg_list | expr
<add_op> ::= + | -
<multi_op> ::= * | /
<comp> ::= > | < | <= | => | =< | >= | = | <>
总而言之,这里有一些非常好的例子:
my_function(1, 2 , 3)
看起来像
(Programm
(rule
(expr
(Not_List)
(CompareExpr
(ConcatExpr
(term
(factor
(value
(function
my_function
(arg_list
(expr
(Not_List)
(CompareExpr
(ConcatExpr (term (factor (value 1))) (term_tail))))
(arg_list
(expr
(Not_List)
(CompareExpr
(ConcatExpr (term (factor (value 2))) (term_tail))))
(arg_list
(expr
(Not_List)
(CompareExpr
(ConcatExpr (term (factor (value 3))) (term_tail))))
(arg_list))))))))
(term_tail))))
(rule)))
现在我的问题是什么?
如果您的代码看起来像这样(( true OR false ) AND true)
我有一个无限递归但真正的问题是(true OR false) AND true
(在第一个( expr )
之后)只被理解为{{ 1}}。
这是Parstree:
那么如何解决这个问题。我应该以某种方式更改语法还是使用一些实施黑客?
如果您需要它,可能会有一些困难。
(true or false)
答案 0 :(得分:1)
我看到了几个问题。
您将OR和AND视为相同的优先级运算符。 OR应该有单独的规则,对于AND。否则,对于表达式A OR B AND C,您将具有错误的优先级(因此评估)。
因此,作为第一步,我将修改您的规则如下:
<Expr> ::= ( expr )
| Not_List AndExpr Or Expr
| Not_List AndExpr
<AndExpr> ::=
| CompareExpr And AndExpr
| Not_List CompareExpr
下一个问题是您的(expr)位于列表的顶层。如果我写的话怎么办?
A AND (B OR C)
要解决此问题,请更改以下两条规则:
<Expr> ::= Not_List AndExpr Or Expr
| Not_List AndExpr
<Value> ::= ConstExpr | function | ( expr )
我认为你的Not的实现是不合适的。不是运营商, 只有一个操作数,所以它的“树”应该有一个Not节点和一个子节点 表达式是Notted。你有没有操作数的Nots列表。 试试这个:
<Expr> ::= AndExpr Or Expr
| AndExpr
<Value> ::= ConstExpr | function | ( expr ) | Not Value
我没看过,但我认为VB6表达式中还有其他杂乱的东西。
如果你注意到,Expr和AndExpr的样式我已经编写了使用 right 递归来避免 left 递归。您应该更改Concat,Sum和Factor规则以遵循类似的风格;你所拥有的是非常复杂和难以理解的。
答案 1 :(得分:0)
如果他们只是创建片段,那么也许VB5“足够好”来创建它们。如果VB5足够好,免费的VB5 Control Creation Edition可能值得追踪,以供他们使用:
http://www.thevbzone.com/vbcce.htm
你可以让他们从他们添加片段的“测试工具”项目开始,他们甚至可以测试它们。
通过一个小方向,这可能比手工制作语法分析器更实用,而且更有用,因为它们可以测试的不仅仅是正确的语法。
缺少VB5时,你可能在“测试工具”中包含一个静态模块,它提供了一个粗略的,准备好的Split(),Replace()等等: