2009-08-21 9 views
1

一部のWebサービスのクエリを構築するために、テキスト入力から論理構造を抽出できるようにするためにパーサを作成する必要があります。テキスト入力用の論理ブールパーサーを作成するにはどうすればよいですか?

正規表現を使用しようとしましたが、作成ロジックを処理するのが本当に複雑になるので、私は助けを求めることにしました。

例:

((foo1 and bar) or (foo2 and bar2)) and ((foo3 and bar3) or foo4) and "this is quoted" 

結果はこのようなものでなければなりません:使用

{ 
    { 
     foo1 
     AND 
     bar 
    } 
    OR 
    { 
     foo2 
     AND 
     bar2 
    } 
} 
AND 
{ 
    { 
     foo3 
     AND 
     bar3 
    } 
    OR 
    foo4 
} 
AND 
{ 
    "this is quoted" 
} 

言語は、ActionScript 3であるが、私は、Javaのバージョンを適応させることができます。

+0

:JSONを解析するJSONパーサーを含んas3corelibを、確認してください。 JSONは "JavaScript Object Notation"を意味します。実際、それはオブジェクトリテラルを表すJavaScriptのサブセットです。それはAS3でも完全に有効な表記法なので、それに慣れておきたいかもしれません。あなたは本当にそれを見てください。 JSONは可能なオブジェクト構造を宣言しているため、論理式も取り込むことができます。そのような悪い考えではありません。 ["a"、 "AND"、["b"、 "OR"、 "c"]]はネストされた配列の構造内で同じセマンティクスを取得することができます。 – back2dos

答えて

5

だけでなく、パーサは(私はあなたが自分でそれらを書くことができますねので、私は、コンストラクタを省略します)まず、あなたがもののかなり多くが必要になります...

非常に簡単です:

式(出力):

class Expression {} 
class Operation extends Expression { 
    public var operand1:Expression; 
    public var operator:String; 
    public var operand2:Expression; 
} 
class Atom extends Expression { 
    public var ident:String; 
} 

トークン(中間形式):

class Token { 
    public var source:String; 
    public var pos:uint; 
} 
class Identiefier extends Token { 
    public var ident:String; 
} 
class OpenParenthesis extends Token {} 
class CloseParenthesis extends Token {} 
class Operator extends Token { 
    public var operator:String; 
} 
class Eof extends Token {} 

とします(トークナイザ) - - >トークン - (パーサkenizerは、それは

はとても道がソースである...私はあなた自身がトークン化する方法を見つけ出すますね

interface TokenStream { 
    function read():Token; 
} 

このインタフェースを実装する必要があります) - >式...

、ここで解析ルーチンは、少しヘルパーで:

function parse(t:TokenStream):Expression { 
    var tk:Token = t.read(); 
    switch ((tk as Object).constructor) {//this is a really weird thing about AS3 ... need to cast to object, before you can access the constructor 
     case OpenParanthesis: 
      var e1:Expression = parse(t); 
      tk = t.read(); 
      switch ((tk as Object).constructor) { 
       case CloseParenthesis: 
        return e1; 
       case Operator: 
        var op:String = (tk as Operator).operator; 
        var e2:Expression = parse(t); 
        tk = t.read(); 
        if (tk is CloseParenthesis) 
         return new Operation(e1,op,e2); 
        else 
         unexpected(tk); 
      } 
      else 
       unexpected(tk); 
     break; 
     case Identifier: 
      return new Atom((tk as Identifier).ident); 
     default: 
      unexpected(tk); 
    } 
} 
function unexpected(tk:Token) { 
    throw "unexpected token "+tk.source+" at position "+tk.pos; 
} 

これは特に良いパーサはありませんが、それはルーチンを解析するの裸の基本を示しています... w実は、私は実装をチェックしませんでしたが、それはうまくいくはずです...それは非常に原始的であり、受け入れられません...オペレータの優先順位などのものは完全に欠落しています...しかし、それを行ってください...

btw。 haXeを列挙型で使用すると、コード全体がはるかに短くて美しく見えるはずです...あなたはそれを見たいかもしれません...そして...

幸運;)

greetz

back2dos redtunaのポストにあなたの質問に応じて

+0

ありがとう、私はそれを掘るでしょう。 –

0

パーサーが必要です。最も簡単な方法は、既存のものを再利用することです。私はそれが普及し、あなたが探しているものに非常に近いので、JSONを試してみることをお勧めします。

(AND(BまたはC))のようなクエリがそのようにコード化されることがあります。

 
{ "left": "a", 
    "op": "AND", 
    "right": 
    { 
    "left": "b", 
    "op": "OR", 
    "right": "c" 
    } 
} 

次の3つのフィールドを持つオブジェクトを取得します解析した後、オペアンプを左、右と呼ばれます。そこから簡単にクエリを構築できるはずです。

これは、入力の形式を選択できる場合にのみ有効です。できない場合は、自分でパーサーを作成する必要があります。あなたの例の構文は単純なので、おそらく再帰的な降下のようなものを使うことができます。

+0

私はJSONに慣れていないので、私は運がない "JSON論理パーサ"のために調査をしました。 JSONで文字列を解析するのを手伝ってもらえますか?試してみますか? –

関連する問題