ANTLRの「セマンティック述語」とは何ですか?
質問
何ですか セマンティック述語 ANTLRで?
解決
ANTLR 4
ANTLR 4の述語については、これらをチェックアウトします スタックオーバーフロー Q&A:
ANTLR 3
a セマンティック述語 プレーンコードを使用して文法アクションに追加の(セマンティック)ルールを実施する方法です。
セマンティック述語には3種類あります。
- 検証 セマンティック述語;
- ゲート セマンティック述語;
- 曖昧性を乱す セマンティック述語。
例の文法
白い空間を無視して、コンマによって区切られた数字のみで構成されるテキストのブロックがあるとしましょう。この入力を解析して、数値が最大3桁の「長い」(最大999)であることを確認します。次の文法(Numbers.g
)そのようなことをする:
grammar Numbers;
// entry point of this parser: it parses an input string consisting of at least
// one number, optionally followed by zero or more comma's and numbers
parse
: number (',' number)* EOF
;
// matches a number that is between 1 and 3 digits long
number
: Digit Digit Digit
| Digit Digit
| Digit
;
// matches a single digit
Digit
: '0'..'9'
;
// ignore spaces
WhiteSpace
: (' ' | '\t' | '\r' | '\n') {skip();}
;
テスト
文法は、次のクラスでテストできます。
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
ANTLRStringStream in = new ANTLRStringStream("123, 456, 7 , 89");
NumbersLexer lexer = new NumbersLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
NumbersParser parser = new NumbersParser(tokens);
parser.parse();
}
}
lexerとパーサーを生成し、すべてをコンパイルしてテストします .java
ファイルと実行 Main
クラス:
java -cp antlr-3.2.jar org.antlr.Tool Numbers.g javac -cp antlr-3.2.jar *.java java -cp .:antlr-3.2.jar Main
そうするとき、コンソールに印刷されるものは何もありません。これは、何もうまくいかなかったことを示しています。変更してみてください:
ANTLRStringStream in = new ANTLRStringStream("123, 456, 7 , 89");
の中へ:
ANTLRStringStream in = new ANTLRStringStream("123, 456, 7777 , 89");
そして、もう一度テストを行います:文字列の直後にコンソールにエラーが表示されるのが表示されます 777
.
セマンティック述語
これにより、セマンティックな述語になります。長さ1〜10桁の数字を解析したいとしましょう。次のようなルール:
number
: Digit Digit Digit Digit Digit Digit Digit Digit Digit Digit
| Digit Digit Digit Digit Digit Digit Digit Digit Digit
/* ... */
| Digit Digit Digit
| Digit Digit
| Digit
;
面倒になります。セマンティックな述語は、このタイプのルールを簡素化するのに役立ちます。
1.セマンティック述語の検証
a セマンティック述語の検証 コードのブロックに続いて質問マークが続きます。
RULE { /* a boolean expression in here */ }?
上記の問題を解決するには 検証 セマンティック述語、変更 number
文法のルールへのルール:
number
@init { int N = 0; }
: (Digit { N++; } )+ { N <= 10 }?
;
部品 { int N = 0; }
と { N++; }
パーサーが「入る」ときに最初の声明が初期化されているプレーンジャワステートメントです number
ルール。実際の述語は次のとおりです。 { N <= 10 }?
, 、パーサーにスローしますFailedPredicateException
数字が10桁以上の長さであるときはいつでも。
以下を使用してテストしてください ANTLRStringStream
:
// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890");
これは例外ではありませんが、以下は例外を抑えます。
// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");
2.ゲートされたセマンティック述語
a ゲートセマンティック述語 aに似ています セマンティック述語の検証, 、 のみ ゲート バージョンは、aの代わりに構文エラーを生成します FailedPredicateException
.
aの構文 ゲートセマンティック述語 は:
{ /* a boolean expression in here */ }?=> RULE
代わりに、上記の問題を使用して解決します ゲート あなたが書く長さ10桁までの数値を一致させる述べ:あなたが書くでしょう:
number
@init { int N = 1; }
: ( { N <= 10 }?=> Digit { N++; } )+
;
両方で再度テストします:
// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890");
と:
// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");
そして、あなたは最後のオンがエラーを投げることを見るでしょう。
3.セマンティックの予測を掘り下げます
述語の最後のタイプはaです セマンティックな述語を曖昧にします, 、これは検証済みの述語のように見えます({boolean-expression}?
)、しかし、ゲートのセマンティック述語のように機能します(ブール式の式が評価する場合、例外は投げられません false
)。ルールの開始時に使用して、ルールのいくつかのプロパティを確認し、パーサーの一致に基づいたルールかどうかを確認できます。
特に作成した例を作成しましょう Number
0..999の範囲の数値と一致するトークン(パーサールールの代わりにレクサールール)。パーサーでは、低い数値とハイト数を区別したいと思います(低:0..500、高:501..999)。これは、を使用して行うことができます セマンティックな述語を曖昧にします ストリームの次のトークンを検査する場所(input.LT(1)
)それが低いか高であるかを確認する。
デモ:
grammar Numbers;
parse
: atom (',' atom)* EOF
;
atom
: low {System.out.println("low = " + $low.text);}
| high {System.out.println("high = " + $high.text);}
;
low
: {Integer.valueOf(input.LT(1).getText()) <= 500}? Number
;
high
: Number
;
Number
: Digit Digit Digit
| Digit Digit
| Digit
;
fragment Digit
: '0'..'9'
;
WhiteSpace
: (' ' | '\t' | '\r' | '\n') {skip();}
;
あなたが今文字列を解析するなら "123, 999, 456, 700, 89, 0"
, 、次の出力が表示されます。
low = 123
high = 999
low = 456
high = 700
low = 89
low = 0
他のヒント
私はいつも非常に典型的な参照を使用しています ANTLR述語 私のガイドとしてwincent.comで。