【问题标题】:Practical solution to fix a Grammar Problem解决语法问题的实用解决方案
【发布时间】:2011-07-08 08:37:24
【问题描述】:

我们几乎没有非程序员编写的 vb6 代码的 sn-ps(仅使用部分功能)。这些被称为规则。对于编写这些的人来说,他们很难调试,所以有人写了一种附加的解析器来评估子表达式,从而更好地显示问题所在。

这个临时解析器非常糟糕,并且不能真正工作。所以我试图编写一个真正的解析器(因为我是手工编写的(没有解析器生成器我可以用 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 ) 之后)被理解为只有 (true or false)

这里是 Parstree:

那么如何解决这个问题。我应该以某种方式更改语法还是使用一些实施技巧?

如果你需要的话,一些很难的例子。

(( f1 OR f1 ) AND (( f3="ALL" OR f4="test" OR f5="ALL" OR f6="make" OR f9(1, 2) ) AND ( f7>1 OR f8>1 )) OR f8 <> "")

【问题讨论】:

  • 您可能应该阅读标记为left-recursion 的其他三个问题的答案。
  • VB6 难以解析,主要是由于文档不佳,但也由于语句内语句和跨行语句之间的交互奇怪。有强大的 VB6 解析器。查看我公司的解析器:semanticdesigns.com/Products/FrontEnds/VisualBasicFrontEnd.html

标签: parsing vb6 grammar recursive-descent left-recursion


【解决方案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 节点和一个子节点 是表达式 be Notted。你有一个没有操作数的 Not 列表。 试试这个:

<Expr>  ::= AndExpr Or Expr   
            | AndExpr

<Value> ::= ConstExpr | function | ( expr ) | Not Value

我没看过,但是我觉得VB6表达式里面还有其他乱七八糟的东西。

如果你注意到,我写的 Expr 和 AndExpr 的风格使用 right 递归来避免 left 递归。您应该更改 Concat、Sum 和 Factor 规则以遵循类似的风格;您所拥有的非常复杂且难以理解。

【讨论】:

    【解决方案2】:

    如果他们只是在创建 sn-ps,那么 VB5 可能“足够好”来创建它们。如果 VB5 足够好,免费的 VB5 Control Creation Edition 可能值得他们跟踪使用:

    http://www.thevbzone.com/vbcce.htm

    您可以让他们从添加了 sn-ps 的“测试工具”项目开始,他们甚至可以对其进行测试。

    稍加指导,这可能会比手工制作语法分析器更实用,而且更有用,因为它们可以测试的不仅仅是正确的语法。

    如果缺少 VB5,您可能会在“测试工具”中包含一个静态模块,该模块提供一个粗略且现成的等价于 Split()、Replace() 等:

    http://support.microsoft.com/kb/188007

    【讨论】:

    • VB5CCE 甚至可以接受像 MZ-Tools 3.0 这样的 IDE 插件,最终你可以让这些人更有效率。