例6:電卓 - 括弧、単項演算子と歴史を追加
1.calculator3.jj
私達はちょうどあなたが可能な四則計算のいずれかを取得することができ、いくつかの機能を追加する必要があります。変更のこのバージョンでは、我々は負のプログラムブラケットを、受け取ることができるように、また、最後に計算結果の$記号によって参照することができます。
字句記述ファイルの変更を以下に示し、私たちは次の3行を追加します。
TOKEN : { < OPEN_PAR : "(" > }
TOKEN : { < CLOSE_PAR : ")" > }
TOKEN : { < PREVIOUS : "$" > }
私たちは、MINUSのこのトークンを定義しているため、負の特殊なトークンを作成する必要はありません。
構文記述の修正された部分については、それは4つのうち主に可能な値のうち、主に反映されている:(前の例のように)値、$記号、括弧式、数陰性その後、最初の3のいずれかに従ってください。BNF記号式は次のよう:
Primary --> NUMBER
| PREVIOUS
| OPEN_PAR Expression CLOSE_PAR
| MINUS Primary
2再帰があるBNF生産。最後の選択肢は直接再帰である式は、最終的に原発に依存しているため、最後のオプションの2番目は、間接的な再帰です。BNF生産の再帰式は問題ありません、もちろん、いくつかの制限があり、我々は後についてお話します。
次の式を考えてみます。
- - 22
その後プライマリは次の図、部品であります:
パーサは、上記入力を実行するときに、各ブロックについて、プライマリ一度呼び出されます。同様に、次の入力のために:
12 * ( 42 + 19 )
次のように私たちは、原発箱から出して、取得することができます。
ネストされたボックスは、実際には、それは、プライマリ相互再帰的なメソッド呼び出しを意味します。
ここJavaCCのは、一次生産のタイプであります:
double Primary() throws NumberFormatException :
{
Token t ;
double d ;
}
{
t=<NUMBER>
{ return Double.parseDouble( t.image ) ; }
| <PREVIOUS>
{ return previousValue ; }
| <OPEN_PAR> d=Expression() <CLOSE_PAR>
{ return d ; }
| <MINUS> d=Primary()
{ return -d ; }
}
2.テスト
上記変形例によれば、文書の次のフルcalculator3.jjを取得します:
/* calculator0.jj An interactive calculator. */
options {
STATIC = false ;
}
PARSER_BEGIN(Calculator)
import java.io.PrintStream ;
class Calculator {
public static void main( String[] args )
throws ParseException, TokenMgrError, NumberFormatException {
Calculator parser = new Calculator( System.in ) ;
parser.Start( System.out ) ;
}
double previousValue = 0.0 ;
}
PARSER_END(Calculator)
SKIP : { " " }
TOKEN : { < EOL : "\n" | "\r" | "\r\n" > }
TOKEN : { < PLUS : "+" > }
TOKEN : { < MINUS : "-" > }
TOKEN : { < TIMES : "*" > }
TOKEN : { < DIVIDE : "/" > }
TOKEN : { < OPEN_PAR : "(" > }
TOKEN : { < CLOSE_PAR : ")" > }
TOKEN : { < PREVIOUS : "$" > }
TOKEN : { < NUMBER : <DIGITS>
| <DIGITS> "." <DIGITS>
| <DIGITS> "."
| "."<DIGITS> >
}
TOKEN : { < #DIGITS : (["0"-"9"])+ > }
void Start(PrintStream printStream) throws NumberFormatException :
{}
{
(
previousValue = Expression()
<EOL> { printStream.println( previousValue ) ; }
)*
<EOF>
}
double Expression() throws NumberFormatException :
{
double i ;
double value ;
}
{
value = Term()
(
<PLUS>
i = Term()
{ value += i ; }
| <MINUS>
i = Term()
{ value -= i ; }
)*
{ return value ; }
}
double Term() throws NumberFormatException :
{
double i ;
double value ;
}
{
value = Primary()
(
<TIMES>
i = Primary()
{ value *= i ; }
| <DIVIDE>
i = Primary()
{ value /= i ; }
)*
{ return value ; }
}
double Primary() throws NumberFormatException :
{
Token t ;
double d ;
}
{
t=<NUMBER>
{ return Double.parseDouble( t.image ) ; }
| <PREVIOUS>
{ return previousValue ; }
| <OPEN_PAR> d=Expression() <CLOSE_PAR>
{ return d ; }
| <MINUS> d=Primary()
{ return -d ; }
}
下記3、正しい計算結果-9 - *(1 + 2)を算出
これは、電卓を完了します。実際には、公式文書の例「テキスト処理」、時間が制限され、翻訳されていないがあります。あなたは、元の英語版を読むために直接行くことができますが、まだ理解することは比較的容易です。ディープ上記の例によって導かれ、私たちは大体JavaCCのを行うことができますし、それがどのように動作するかを知ってみましょう。あなたはより多くの事をするJavaCCのを使用したい場合は、提案はまだ理解するために英語の原稿読み取り、そしてより多くの練習の最後の例です。