文法スペックはシフト/競合を減らすことを解決します
-
13-12-2019 - |
質問
私はJison(Bison)を使ってシンプルなマークアップ言語を作成します。私は明らかにこれには新しくなっていますが、わずかなバリエーションは非常にうまく機能しています。S / Rの紛争の原因はわかりません。
「テキスト」が2つのレクサーアクション(さまざまな開始条件付き)によって返されるようには思われません。。私はコンテキストに関係なく 'テキスト'のルールを共通化させようとしました、そして私はそれぞれのトークンを別の名前に与えることも試みました、しかしそれはすべて一緒になったときにs / rの競合に影響を与えないようです。
パーサーは、プレーンテキスト、サブアレイ、およびさまざまな特殊ノードを持つJSONオブジェクトを作成することになっています。
仕様:
/* lexical grammar */
%lex
%s bracketed
%%
<bracketed>(\\.|[^\\\,\[\]])+ { yytext = yytext.replace(/\\(.)/g, '$1'); return 'Text'; }
<INITIAL>(\\.|[^\\\[])+ { yytext = yytext.replace(/\\(.)/g, '$1'); return 'Text'; }
"[" { this.begin('bracketed'); return '['; }
"]" { this.popState(); return ']'; }
"," return ','
<<EOF>> return 'END'
/lex
%start template
%%
template
: sentence END
;
sentence
: /* empty */
| sentence Text
| sentence '[' ']'
| sentence '[' dynamic ']'
;
dynamic
: sentence
/*| dynamic ',' sentence*/
;
.
警告:
Conflict in grammar: multiple actions possible when lookahead token is ] in state 5
- reduce by rule: sentence ->
- shift token (then go to state 6)
States with conflicts:
State 5
sentence -> sentence [ .] #lookaheads= END Text [ ]
sentence -> sentence [ .dynamic ] #lookaheads= END Text [ ]
dynamic -> .sentence #lookaheads= ]
sentence -> . #lookaheads= ] Text [
sentence -> .sentence Text
sentence -> .sentence [ ]
sentence -> .sentence [ dynamic ]
.
異なる発電機アルゴリズムには多かれ少なかれ問題がありますが、それらはすべて問題を抱えているようです。
ありがとう!
解決
紛争は基本的にこれら2つの規則から来ます:
sentence: sentence '[' Text ']'
| sentence '[' sentenceList ']'
.
sentence
と[
を参照して、Text
である次のトークンを見ると、パーサーはText
をシフトし、最初のルールに一致させるか、そのText
を扱うかどうかをわからないためです。 sentenceList
は2番目の規則を一致させるために行く。
2トークンルックアヘッドを使用するパーサージェネレータを持っていた場合、これは問題にならないでしょうが、Bisonはlalr(1)です(1)(1が1つのトークンルックアヘッド)。
試してみることができるいくつかのものがあります:
-
は、2つの異なるトークンとしてテキストに続いてテキストを区別し、次にこれらのトークンの両方を使用するようにルールを書き換えるために、LexerのLookAhakeadをテキストに従って区別します。
-
Bisonの%GLR-Parser機能を使用してGLRパーサーを使用します。これは文章を解析し、後で
と一致しないものを捨てます。
-
文法をリファクタリングして、2トークンルックアヘッドを必要としない。
あなたのケースで機能する1つのリファクタリングは、sentence
ルールを左再帰的ではなくすべての右再帰的にするように書き換えることです:
sentence: /* empty */
| Text sentence
| '[' ']' sentence
| '[' Text ']' sentence
| '[' sentenceList ']' sentence
;
.
これは、sentence
ルールのNULLの削減で、sentence
(またはsentenceList
などのsentence: /*empty*/
で始まる他の任意のルール)を回避します。そのため、パーサーは、次のトークンを見るまで減少を延期する問題のある場合には、Text
を自由にシフトさせることができます。ただし、入力全体をパーサスタックに基本的にシフトさせ、次に一度に1文を短くするパーサーが生じるので、メモリを使用します。
別のリファクタリングは、[Text]
および[]
コンストラクトを[sentenceList]
:
sentence: /* empty */
| sentence Text
| sentence '[' sentenceList ']'
;
sentenceList: sentence
| sentenceList ',' sentence
.
だからsentenceList
は、(2つ以上の)カンマで区切られた1つ以上の文で、sentence '[' sentenceList ']'
ルールのアクションでは、sentenceList
が2つ以上の文であるかどうかを確認して適切に機能します。 。