8

こんにちは!

セミコロンやバックスラッシュを必要とせずに複数行の式を処理する単純な ANTLR 文法を作成するにはどうすればよいですか?

式の単純な DSL を作成しようとしています。

# sh style comments
ThisValue = 1
ThatValue = ThisValue * 2
ThisOtherValue = (1 + 2 + ThisValue * ThatValue)
YetAnotherValue = MAX(ThisOtherValue, ThatValue)

全体として、アプリケーションでスクリプトに名前付きの初期値をいくつか提供し、最終結果を引き出す必要があります。しかし、私は構文に夢中になっています。次のような複数行の式をサポートしたいと思います。

# Note: no backslashes required to continue expression, as we're in brackets
# Note: no semicolon required at end of expression, either
ThisValueWithAReallyLongName = (ThisOtherValueWithASimilarlyLongName
                               +AnotherValueWithAGratuitouslyLongName)

私は次のような ANTLR 文法から始めました。

exprlist
    : ( assignment_statement | empty_line )* EOF!
    ;
assignment_statement
    : assignment NL!?
    ;
empty_line
    : NL;
assignment
    : ID '=' expr
    ;

// ... and so on

それは簡単に思えますが、私はすでに改行に問題があります:

warning(200): StackOverflowQuestion.g:11:20: Decision can match input such as "NL" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input

グラフィカルに、org.antlr.works.IDE で:

意思決定は、複数の選択肢を使用して NL に一致させることができます http://img.skitch.com/20090723-ghpss46833si9f9ebk48x28b82.png

私は文法を蹴散らしましたが、常に期待される動作に違反してしまいます:

  • ファイルの末尾に改行は必要ありません
  • 空行は許容されます
  • ポンド記号以降の行はすべてコメントとして破棄されます
  • 代入はセミコロンではなく行末で終わる
  • 括弧で囲まれている場合、式は複数の行にまたがることができます

これらの特徴の多くを備えた ANTLR 文法の例を見つけることができます。それらを切り詰めて表現力を必要なものだけに制限すると、何かが壊れてしまうことがわかりました。他は単純すぎて、表現力をつけながら壊していきます。

この文法でどの角度を取るべきですか? 自明または完全なチューリング完全言語ではない例を教えてください。

4

3 に答える 3

6

改行ルールを文法に混ぜるのではなく、トークナイザーに面倒な作業を任せます。

  • 括弧、括弧、および中括弧をカウントし、閉じていないグループがある間は NL トークンを生成しません。これにより、文法をあまり知らなくても、無料で行を継続できます。

  • 最後の行が文字で終わっているかどうかに関係なく、常にファイルの最後に NL トークンを生成し'\n'ます。そうすれば、NL のないステートメントの特殊なケースについて心配する必要はありません。ステートメントは常にNL で終わります。

2 番目のポイントでは、文法を次のように単純化できます。

exprlist
    : ( assignment_statement | empty_line )* EOF!
    ;
assignment_statement
    : assignment NL
    ;
empty_line
    : NL
    ;
assignment
    : ID '=' expr
    ;
于 2009-07-23T03:35:36.783 に答える
0

これはどう?

exprlist
    : (expr)? (NL+ expr)* NL!? EOF!
    ;
expr 
    : assignment | ...
    ;
assignment
    : ID '=' expr
    ;
于 2009-07-23T03:39:43.543 に答える
0

入力コードの最後のステートメントは改行で終わる必要がないため、NL をオプションにすることを選択したと思います。

それは非常に理にかなっていますが、パーサーの生活を非常に困難にしています。区切りトークン (NL など) は、あいまいさを解消し、競合の可能性を減らすため、大切にする必要があります。

あなたの場合、パーサーは「割り当て NL」または「割り当て empty_line」を解析する必要があるかどうかを知りません。それを解決する方法はたくさんありますが、それらのほとんどは、賢明でない設計上の選択に対する応急処置にすぎません。

私のお勧めは無邪気なハックです: NL を必須にし、入力ストリームの最後に常に NL を追加してください!

少し不快に思えるかもしれませんが、実際には、将来の頭痛の種を大幅に節約できます.

于 2017-01-10T14:23:36.300 に答える