「コンパイラ・スクリプトエンジン」相談室16 (649レス)
1-

114: 片山博文MZ次期CEO ◆T6xkBnTXz7B0 2014/11/29(土)15:46 ID:AWiICJMh(1) AAS
Caperで、Haxe用のパーサーが作れるようになったらしいぞ!!!

外部リンク[html]:jonigata.github.io
115: 2014/11/29(土)19:24 ID:bjHueY84(1/2) AAS
ということはjavaとphpとC#に対応したということか
116: 2014/11/29(土)19:25 ID:bjHueY84(2/2) AAS
って元からしてんじゃん…
117
(18): 2014/12/04(木)17:14 ID:hjxCxC4V(1/2) AAS
スレ立てるまでもない質問はここで 139匹目から来ました。

JavaCCで負の数と引き算を識別したいんですけど、どう定義したらいいでしょうか?

以下現状の一部抜粋(メソッド名についてはスルーしてください)
void enzan3() :
{}
{
enzan4()((<TASU>|<HIKU>)right=enzan4())*
}

void enzan4() :
{}
{
enzan5()((<KAKERU>|<WARU>)enzan5())*
}

void enzan5() :
{}
{
<MOZI>|[<HIKU>]<SUUZI>|"(" e=enzan3() ")"
}
118
(1): 2014/12/04(木)18:52 ID:jHjIGczB(1) AAS
>>117
そのスレの997以降のはやってないの?

number=0..9
plus::=<expr> + <expr>
minus::=<expr> - <expr>
expr::=<number>|<plus>|<minus>
な感じになるだろうし

単項のマイナスはexprにかからない形式で-が出てきた時だし間違いようがなさそうに思うんだけど
119
(1): 2014/12/04(木)20:49 ID:hjxCxC4V(2/2) AAS
あ。
そこの
>単項演算子と二項演算子の区別
についてはまだ調べてないです。
調べてみます。

二項演算子+,-の間に二項演算子*,/を含む式があって、
その中にカッコか数字か変数呼び出しなどがあるように定義するのではないのですか?
例えば
-1
1-2
-2*4
2/(-2+5)
などの書き方が使えるようになるといいなとか考えています。

>>118
::=って書き方は確かBNF記法でしたっけ?
その書き方についてぜんぜん知らないのでそれも調べてみます。
120
(2): 2014/12/06(土)17:09 ID:evyQIgPT(1) AAS
みんなBNFとかやってるのか
char配列にして解析してるから常に最後が';'だと楽なんだよね
'{'で+1、'}'で-1、+-0の状態で';'がきたらその構文が完結する
int a;, class {}; switch{}; void hey(){}; if(true){}; for(){};
121
(2): 2014/12/06(土)17:17 ID:djm9MkQZ(1) AAS
演算子の優先順位はどうしてんの?
122: 2014/12/06(土)17:30 ID:5oGFUyw+(1/2) AAS
べつに区切り文字が = だろうが : だろうが ::= だろうが BNF は BNF だ
123
(1): 117 2014/12/06(土)23:05 ID:BPhK2Nlg(1/3) AAS
>>120
>みんなBNFとかやってるのか
JavaCCの場合字句解析でトークン列に分解してくれて、
>>117にあるようにそのトークンの並びを書いて構文解析の定義をします。
なのでBNF記法とは違った書き方になります。

>>121
>演算子の優先順位はどうしてんの?

いい説明文が思い浮かばないので、
まずは例として1+2*3/4-5という式を構文木にしたものを以下にアップします。
外部リンク:fast-uploader.com
こんなかんじのまとまりです。
演算子:/ 左辺:3(enzan5) 右辺:4(enzan5) → ?(enzan4)
演算子:* 左辺:2(enzan5) 右辺:?(enzan4) → ?(enzan4)
演算子:- 左辺:?(enzan4) 右辺:5(enzan5) → ?(enzan4)
演算子:+ 左辺:1(enzan5) 右辺:?(enzan4) →?(enzan3)
124: 117 2014/12/06(土)23:06 ID:BPhK2Nlg(2/3) AAS
とりあえずenzan3の定義の先頭にマイナスの記号があるかもしれないという意味合いで
以下のようなコードに変えてみました。

void enzan3() :
{}
{
[<HIKU>]enzan4() //★
((<TASU>|<HIKU>)enzan4())*
}

void enzan4() :
{}
{
enzan5()
((<KAKERU>|<WARU>)enzan5()
}

void enzan5() :
{}
{
<MOZI>|<SUUZI>|"(" enzan3() ")"
}

<>:トークン |:左右のどちらかの構文(||やOr演算子のようなもの) []:省略可能構文
125: 117 2014/12/06(土)23:07 ID:BPhK2Nlg(3/3) AAS
すると、以下のような警告が出ました。

Warning: Choice conflict in (...)* construct at line 608, column 9.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: <HIKU>
Consider using a lookahead of 2 or more for nested expansion.

内容は選択の突出(Choice conflict)と言うもので、
私が作った構文の定義があいまいのようで
608行目(ここでは★を付けた行)の定義が他の定義とかぶっているらしく、
先頭に出てくる<HIKU>トークンが共通点らしいです。
そもそもの考え方が間違っているかもしれませんが、
それを抜きにしてもまずなぜこのような警告が出ているかわかりません。
一体なぜ出ているかわかる人いれば教えてださい。
126: 2014/12/06(土)23:08 ID:q7blqefO(1) AAS
>>120
java(というよりC)のforは()の内部に;が出てくるのが
>>119
javaccの書き方と大差ないみたいよ
127
(1): 2014/12/06(土)23:27 ID:5oGFUyw+(2/2) AAS
この文脈でconflictは「衝突」と言う。
そのメッセージの通り、複数の定義で共通してるトークンがあるから、どっちの定義のほうだとして
解釈していいかわからないからエラーになる。
そのメッセージでは「Consider using a lookahead of 2 or more for nested expansion.」2個あるいはそれ以上の
先読みを使うことを検討してみろ、と言っているが、それに従ったところでうまくいくかどうかは
わからんけどね。
128
(2): 2014/12/07(日)01:31 ID:bfkTF4nN(1/3) AAS
>>123
>>121は重要なヒント
-(1+2)とか、1+(-2)とかにその定義で対応できる?

たとえば★の行をenzan5に移してみるなり、演算子の優先順位を変えてやりなおすとか
それとは関係ないけど、3*2/4って直感的には( (3 * 2) / 4 )になりそうだけどその構文木だと右から左なのね
129: 2014/12/07(日)01:36 ID:bfkTF4nN(2/3) AAS
>>128
勘違いしたわすれて
130
(1): 117 2014/12/07(日)21:58 ID:OacxF8nB(1) AAS
>>127
選択の衝突でしたね。
間違えて覚えました;
かぶってるらしいからLOOKAHEADで先読みをしなくてはならないのはわかるのですが、
そのコードでどのパターンとどのパターンでかぶってるのかがわからなくて。

>>128
>-(1+2)とか、1+(-2)とかにその定義で対応できる?
1+(-2)のパターンは意識していましたが、-(1+2)のパターンは忘れてました。
きちんと考えなおしてきます。
131: 2014/12/07(日)22:37 ID:bfkTF4nN(3/3) AAS
>>130
試しに四則演算のみ行う言語をjavaccで作ってみたけど単行演算子程度ならLookAheadいらないよ
132
(1): 117 2014/12/08(月)00:25 ID:yQ2quuvD(1/3) AAS
いろいろ考えているうちに構文規則がおかしなことになってきました;
とりあえず負の数やかっこを含む数式の構文木を一通り考えてみたつもりなんですけど、
以下のような感じであっているでしょうか?
外部リンク:fast-uploader.com
また、他に欠けているパターンはないでしょうか?
133
(1): 2014/12/08(月)18:02 ID:3czqE9B9(1) AAS
>>132
単項演算子はどこに行ったんだ
134: 117 2014/12/08(月)21:29 ID:yQ2quuvD(2/3) AAS
>>133
あれは構文木と言うより抽象構文木というか内部構造と言うかそんなかんじのものですね;
負の数をどう計算するか考えてたらその式や数字に-1をかければいいかなと思って作ってました。
今度はきちんと抽象じゃない構文木を考えます。 はい。
135: 117 2014/12/08(月)23:27 ID:yQ2quuvD(3/3) AAS
とりあえず自分がわかっている範囲で -(1+2)*4 の解析木を作ってみました。
外部リンク:fast-uploader.com
enzan番号という名前はやめてみました。
空欄部分は下位置調節のためや何を入れたらいいかわからない部分です。
136
(1): 117 2014/12/09(火)21:43 ID:KYZ3f1RL(1/3) AAS
構文規則作ってみましたが、選択の衝突が消えません。
tasuhikuのkakewaruをkakewaru2に変えると消えます。
kakewaruで呼んでるminusの[<HIKU>]がtasuhikuの<HIKU>と競合しているのかと思いましたが、
なぜなのかわかりません。
どこが間違っているでしょうか?

警告なのでとりあえず無視してjavacコンパイルして解析&実行させてみると、以下の式はきちんと実行できました。
1+2+3
-9-3
1+2*3/4-5
7+(-2)
-6*2
-(1+2)*4
(-1+2)*4
-1+2*4
4-(-2/5)
-(-(-39))/13
一応ある程度のパターンを網羅していると思います。

Warning: Choice conflict in (...)* construct at line 608, column 9.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: <HIKU>
Consider using a lookahead of 2 or more for nested expansion.
137: 117 2014/12/09(火)21:44 ID:KYZ3f1RL(2/3) AAS
void tasuhiku():
{}
{
kakewaru() //608行目
((<TASU>|<HIKU>)kakewaru2())*
}

void kakewaru():
{}
{
minus()
((<KAKERU>|<WARU>)sikikakko())*
}

void kakewaru2():
{}
{
sikikakko()
((<KAKERU>|<WARU>)sikikakko())*
}
138: 117 2014/12/09(火)21:45 ID:KYZ3f1RL(3/3) AAS
void minus():
{}
{
[<HIKU>]sikikakko()
}

void sikikakko():
{}
{
("(" tasuhiku() ")"
|atai())
}

void atai():
{}
{
<SUUZI>
}
139
(1): 2014/12/10(水)06:22 ID:ICK0nNNi(1) AAS
荒らされてるなぁ・・・
140
(1): 2014/12/10(水)14:14 ID:lFxVBhH5(1/5) AAS
>>136
文法作るのはものすごく難しいんだよ。
同じ文書を受理する複数の文法が存在し、複数の間で優劣がある。
しかも、優劣を機械的に評価することが難しい。

「こいつを使えば簡単にできる」というようなソフトウェア紹介を見かけると
思うけど、そんな魔法の杖みたいなソフトは無いから。
そういうこと言ってる人は、付属してきたサンプルを動かして簡単といってるだけ。
信じちゃだめだ。

構文解析器の生成系を自分で作れるようにならないと文法を作れないと思っていい。
少なくともその程度の理解は必要。

まずドラゴンブックを買ったらどうかと思うんだが。
141
(1): 2014/12/10(水)14:18 ID:lFxVBhH5(2/5) AAS
まずドラゴンブックを買う。
実際に作ってみる。

この作ったものは実用にはならないよ。
テーブルが大きすぎるからね。

それでも作ることが重要。

その後に、市中に出回る生成系を使ってみたらどうだろう。
俺はこの順番が良いと思うよ。

中身の動作を知らないと使えないって、ツールとしては下等だけど、
今はまだその程度の世界なんだよ。
142
(1): 117 2014/12/10(水)16:50 ID:pQyEQrGQ(1/3) AAS
>>139
私のことだったら荒らそうと言うつもりは全くありません。
でも荒らしに見えてしまっていたならすいません。

>>140-141
ドラゴンブックってこれのことですかね?
外部リンク:www.amazon.co.jp
(私にとって)安くないですし今そこから勉強している余裕はないので・・・。
すいません。

よそでパーサジェネレータ使った方がいいとか言われて、
Javaが好きなどの理由でJavaCCを使うようになりました。
なんにせよ周りに作ったことある人とかいないので、
外部リンク[html]:www.sbcr.jp
とか
外部リンク:item.rakuten.co.jp
とか片手に独学でやってます。
143
(2): 2014/12/10(水)17:17 ID:lFxVBhH5(3/5) AAS
>>142
そこが勘違いなんだよ。

JavaCCを使うにはJavaCCを作れる程度の知識が必要。
だからドラゴンブックが必須。
ドラゴンブックは決して読みやすい書籍ではないよ。
どうとでもとれる表現がいくつもある。
読み解きながら理解する必要があるので、結局生成系を自分で一つ書き上げる必要がある。

「JavaCCを使えば知識がなくてもこんなに簡単」的なことを書く人は
実はJavaCCを使っていないんだよ。
そこに騙されてはいけない。
文法を作るには深い理解が必要なんだよ。
簡単にできる方法はない。
1-
あと 506 レスあります
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ

ぬこの手 ぬこTOP 0.023s