3

私はPrologでパーサーを書きました。まだ終わっていません。これはコードの一部です。次のステップは、文字列内のすべての空白を削除することです。

parse(Source, Tree) :-  kill_whitespace(Source, CleanInput), % remove whitespaces
                        actual_parse(CleanInput, Tree).

actual_parse(CleanInput, Tree):- phrase(expr(Tree),CleanInput).

expr(Ast) --> term(Ast1), expr_(Ast1,Ast).
expr_(Acc,Ast) --> " + ", !, term(Ast2), expr_(plus(Acc,Ast2), Ast).
expr_(Acc,Ast) --> " - ", !, term(Ast2), expr_(minus(Acc,Ast2), Ast).
expr_(Acc,Acc) --> [].

term(Ast) --> factor(Ast1), term_(Ast1,Ast).
term_(Acc,Ast) --> " * ", !, factor(Ast2), term_(mul(Acc,Ast2),Ast).
term_(Acc,Ast) --> " ** ", !, factor(Ast2), term_(pol(Acc,Ast2),Ast).
term_(Acc,Acc) --> [].

factor(Ast) --> "(", !, expr(Ast), ")".
factor(D)--> [X], { X >= 48 , X=<57 , D is X-48 }.
factor(id(N,E)) --> "x", factor(N), ":=", expr(E), ";".

例えば:

?- parse("x2:=4",T).
    T = id(2, 4)

本当です!しかし、私が書くとき:

?- parse("x2 := 4",T).
false.

それも真である必要があり、フィルターである必要がありますkill_whitespace(Source, CleanInput)

さまざまなソリューションは非効率的です。どうやってやるの?

4

3 に答える 3

1

簡単な方法は、文字列を解析して空白を削除するか、フィルター述語で非空白のみを保持することです。ただし、これには 2 番目の解析が必要です。

それを修正する別の方法は、独自の述語を使用して文字を「取得」することです。
つまり、 where is のようなものにfoo --> "a".なります。foo --> get("a").get//1

get(X) --> [X].
get(X) --> whitespace, get(X).
于 2013-01-16T19:31:35.537 に答える
1

私は通常、スペースが発生する可能性のある「スキップ」非端末を配置します。このようなスキップは通常、コメントやその他の「興味のない」テキストを破棄します。

できるだけシンプルにするために:

% discard any number of spaces
s --> "" ; " ", s.

文法をきれいに保つために、短い名前を好みます。改行なども破棄するには:

s --> "" ; (" ";"\t";"\n";"\r"), s.

「スタイル」ノート: 代わりに

parse(Source, Tree) :-
   expr(Tree, Source, []).

あなたは考えることができます

parse(Source, Tree) :-
   phrase(expr(Tree), Source).
于 2013-01-16T20:28:20.780 に答える
0

パーサーを作成する通常の方法は、2 段階で作成することです。

第 1 段階では、字句解析が行われ、トークンのストリームが生成されます。この時点で、解析に重要でない空白やその他の「トークン」(コメントなど) は破棄されます。

第 2 段階では、字句解析器によって生成されたトークンのリストを調べて、解析自体を実行します。

于 2013-01-17T19:04:06.947 に答える