2011-07-26 3 views
1

私はBisonを使ってパーサを生成しようとしています。文法はうまくいきますが、私はその行動に素早く問題を抱えています。ここに簡単なサンプルがあります:Bisonのアクションオーダー

statements 
: statement 
| statements statement; 

私の知る限り、これはかなり普通のことです。私が持っている質問は、最初に導き出されたものです。私は

statement statement statement statement 

のように見えるの入力を持っている場合、私はのリンクリストを構築しようとしている

statement (statement (statement (statement)))) 

または

(((statement) statement) statement) statement 

として例えば、Bisonは私の行動を呼ぶんルールはここで呼び出され、入力と同じ順序でリストを保持したい。 OK、私はこのような何かを行うことができます:今、私は

statements 
: statement 
{ 
    $$ = $1; 
} 
| statements statement 
{ 
    dynamic_cast<ParsedFile::Statement*>($1)->Next = dynamic_cast<ParsedFile::Statement*>($2); 
    $$ = $1; 
}; 

編集持っ

switch_statement 
: SWITCH '(' expression ')' 
{ 
    auto Switch = p.Make<ParsedFile::SwitchStatement>(); 
    Switch->Test = dynamic_cast<ParsedFile::Expression*>($3); 
    p.NewScope(); 
    $$ = Switch; 
} 
'{' case_statements '}' 
{ 
    auto Switch = dynamic_cast<ParsedFile::SwitchStatement*>($5); 
    Switch->Cases = p.statements.top(); 
    p.PopScope(); 
    p.AddToCurrentScope(Switch); 
}; 

default_statement 
: DEFAULT ':' 
{ 
    auto Default = p.Make<ParsedFile::DefaultStatement>(); 
    p.NewScope(); 
    $$ = Default; 
} 
statements 
{ 
    auto Default = dynamic_cast<ParsedFile::DefaultStatement*>($3); 
    Default->Statements = p.statements.top(); 
    p.PopScope(); 
    p.AddToCurrentScope(Default); 
}; 

case_statement 
: CASE expression 
{ 
    auto case = p.Make<ParsedFile::CaseStatement>(); 
    p->Value = dynamic_cast<ParsedFile::Expression*>($2); 
    p.NewScope(); 
    $$ = case; 
} 
DOUBLE_COLON statements 
{ 
    auto Case = dynamic_cast<ParsedFile::CaseStatement*>($3); 
    Case->Statements = p.statements.top(); 
    p.PopScope(); 
    p.AddToCurrentScope(Case); 
}; 

case_statements 
: case_statement 
| case_statements case_statement 
| case_statements default_statement; 
+0

なぜdownvoteですか? – Praetorian

+0

@DeadMG: '$ 2'を' $ 1'に追加し、 '$$'を使って' $ 1'を "返す"ので、次の派生の後に同じノードの 'Next'ポインタをリセットする*でしょう。あなたが必然的にリンクリストを望むなら(なぜ、 'vector'や' deque'ではなく?)、その頭とその尾の両方へのポインタを保持しなければなりません。 –

+0

@larsmans:ベクターやデュークを使用していないのは、私が依存できる場所をどこにも格納していないからです。スタック(Cスタイルの文法)にはいくつかの 'statements 'があり、Bisonは複雑なコンテナを保持することは実際にはありません。実際には、考えてみると、実際のスタックになることは決してありませんでしたので、ユーザー提供の引数に格納し、中央の引数を使用してプッシュしてポップすることができます。 – Puppy

答えて

4

それは左に関連付け、すなわち

(((statement) statement) statement) statement 

あなたが言うことができますこれが唯一の可能性であることは、プロダクションの1つであるstatements statementに減らすことができるからです。

statement (statement (statement (statement)))) 

他のオプションは、あなたの作品のない一つですstatement statements、に削減しなければならないであろう。ただし、代わりに右結合を必要とする場合はこれを使用できます。

-であるように、他に1文を接合した後、あなたは 最初の文へのポインタを返すので、あなたのコードはので、次の文は、あなたの周りに来るときは Nextポインタを上書きしている、リンクリストを生成しません

最初の声明の

順序を右結合に変更すると、これを解決することができますが、これには文の数に線形パーサースタックスペースが必要になることに注意してください。多くのステートメントが必要な場合は、リンクリストを逆に作成することを検討する必要があります。

+0

ありがとうございました。同じ問題に別の戦略を反映させるためにOPを編集しました。私はあなたの回答に感謝します。そうでなければ、元の質問に答えるように答えを受け入れます。 – Puppy

+0

@DeadMG:私は物事の順序に従うのが難しいかもしれないので、行動にステートフルなコードを書くのは避ける傾向があります。 '$$ = foo($ 1、$ 2)'の形式であなたの行動を書くことを検討してください。 'foo(foo(foo(bar(first)、second)、3番目)、4番目)'と書いていたのと同じです。 – hammar

+0

スコープには、正しいスコープを決定するために、そのようなものが必要です。私はそれが実行可能ではなかったと思う他の方法をやっている。しかし、式のようなスコープレス構成の場合、ステートフルではなく機能的に構築されます。 – Puppy