3

非プログラマーによって作成される 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)

パースツリーは次のとおりです。 解析木

では、これを解決する方法。どういうわけか文法を変更するか、実装ハックを使用する必要がありますか?

必要な場合に備えて、何か難しい例を示します。

(( 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 <> "")
4

2 に答える 2

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)

これを修正するには、次の 2 つのルールを変更します。

<Expr>  ::= Not_List AndExpr Or Expr   
            | Not_List AndExpr

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

あなたの Not の実装は適切ではないと思います。Not はオペランドが 1 つのみの演算子であるため、その「ツリー」には Not ノードと、式 be Notted である子が必要です。オペランドのない Nots のリストがあります。代わりにこれを試してください:

<Expr>  ::= AndExpr Or Expr   
            | AndExpr

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

私は見ていませんが、VB6 式には他にも厄介なものがあると思います。

お気づきのように、私が書いた Expr と AndExpr のスタイルは、再帰を避けるために再帰を使用しています。同様のスタイルに従うように、Concat、Sum、および Factor ルールを変更する必要があります。あなたが持っているものはかなり複雑で、従うのが難しい.

于 2011-07-08T15:53:36.753 に答える
0

スニペットを作成するだけの場合は、おそらく VB5 でスニペットを作成するのに「十分」です。また、VB5 で十分な場合は、無料の VB5 Control Creation Edition を追跡して使用する価値があるかもしれません。

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

スニペットを追加する「テスト ハーネス」プロジェクトから開始してもらい、テストすることもできます。

少しオリエンテーションを行えば、構文アナライザーを手作業で作成するよりもはるかに実用的であり、正しい構文以上のものをテストできるため、はるかに便利であることが証明されるでしょう。

VB5 が不足している場合は、「テスト ハーネス」に静的モジュールを含めることができます。これは、Split()、Replace() などと同等のものを提供します。

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

于 2011-07-09T03:20:33.410 に答える