parsing - 解决语法问题的实用解决方案

标签 parsing vb6 grammar recursive-descent left-recursion

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

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

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

万一你需要它,一些很难的例子。
(( 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 <> "")

最佳答案

你有几个我看到的问题。

您将 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 的样式使用右递归来避免左递归。您应该更改 Concat、Sum 和 Factor 规则以遵循类似的风格;您所拥有的非常复杂且难以理解。

关于parsing - 解决语法问题的实用解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6621958/

相关文章:

c++ - 在 C++ 中将不断变化的 json 值转换为 int

java - Elasticsearch:在传输层捕获异常

visual-studio - Visual Studio 6 Windows 公共(public)控件 6.0 (sp6) Windows 7,64 位

python - Python 变量作用域是如何工作的?

php - PHP解析/语法错误;以及如何解决它们

vb6 - 有没有办法抑制VB6中的 "procedure too large"错误?

dll - 如何解决 "Run-time error ' 42 9': ActiveX component can' t create object”?

ocaml - 关于 ocamlyacc,函数应用语法和优先级

grammar - 对 Raku 中无限的 &lt;!before> 模式家族进行反匹配

ruby-on-rails - Ruby,从文本中获取第一张图片