プログラム言語の処理系の勉強のために、実際に処理系を作成してみています
四則演算などの基礎的なところが動くようになって喜んでいたのですが
次のような文法で大きく解析速度が落ちてしまうという問題が起きてしまいました
(構文解析だけで1分ほどかかってしまいました)
->(n) do
if(
n.(==)(1),
do 1 end,
do n.(*)(fact(n.(-)(1))) end
)
end
文法の詳細は何となく察していただくとして
解析速度の大きな低下の原因を探ってみたところ
括弧「()」の入れ子階層が深く入り組むほど倍々ゲームで解析速度が落ちている処まで絞り込めてきました
おそらく閉じ括弧「)」を先読みしても間違ったものを拾って失敗しているのではないかなと推測しています
一応使っている環境は下に挙げますが
おそらくはLL(n)構文解析での一般的な問題だと思いました
どうすれば高速化できるか教えていただけないでしょうか?
・開発言語はC#
・パーサー・コンビネーターでSparacheというライブラリを使用させていただきました
https://github.com/sprache/Sprache
・ライブラリは開始括弧「(」をっ見つけると閉じ括弧「)」の先読みを、してくれている…様子です
・トークナイズや中間表現への変更は行わないで直接文字列をプログラムとして評価しています
はじめて作ってみた処理系なので失敗してはその原因を調べなおして勉強しているものですが
お知恵を貸していただければ幸いです
A 回答 (3件)
- 最新から表示
- 回答順に表示
No.3
- 回答日時:
構文解析における文法定義は、普通のプログラムにおけるソースコードなので、「文法察してください」っていうのは、「テキスト処理してるんですがうまく動きません。
ソースコードは晒せませんが、入力はこんな感じです。原因を特定してください」って言ってるようなものです。できるわけありません。そして文法も謎です。察せません。なんか関数型言語をイメージしているような雰囲気はしますが…。
LL(k)文法は最大k個のトークンを先読みすれば、バックトラックなしに一意に決定できる文法です。LL(k)パーサはその事に基づき、トークンとスタックの先頭を見て動作を決めるアルゴリズムなので、「(」を読むと「)」を先読みするという動作が不可解です。
入れ子の階層が深くなるほど重くなるというのも…。
トークナイズしてないせいで、異常なサイズの解析表が構築されているとかでしょうか?
単に文法が悪いかもしれませんし、ライブラリの問題かもしれません。
いずれにしても、この辺はSparacheを知らないため私はこれ以上のアドバイスできませんが…。
まぁ、個人的にはいきなりLINQ使ったパーサーコンビネーターみたいな変態的な代物で、参考にできるものが少ない変な文法に挑戦しないで、まずは適当な本でも見ながら、再帰下降パーサーとかLL(1)パーサーで、四則算電卓を作るところからはじめて、JavaScriptとかBASICライクなメジャーで簡単な文法に挑戦した方がいいと思います。
(もっとも、私が初めて書いたパーサもHaskellのParsecを使ったものだったのであまり人のこと言えないかもしれませんがwww)
正直、言語ひとつを理解するためには、できないといけない範囲が広すぎるので
最初はある程度ツールの力を借りてでもひとつ作ってみて、その後興味の続いた分野を深堀していく姿勢でないといけないと思うのです
その結果アレ?って事になってここで質問を行っている人間の言葉ではないのかもしれませんが・・・
Parsecの場合は先読みしたい場合はtry関数に食べさせてあげる必要がありますので
文法が複雑になってくると、後でtry地獄になりますが、Sparacheはそういうのが表に出てこないので
やりやすいなと思っていたのですが、最後になって問題が浮いてくるタイプでしたね
今回のような入れ子の関係が確定している場合はLL(1)文法の方が良いよいです
ちょっとデフォルトが先読みをきかせているので、先読み聞かせない方法を探します
No.2
- 回答日時:
マイクロコンピュータのための
コンパイラ・コンパイラ
サイエンス社
では、Gコードを使って高速化しています。
文法はLL(1)です。
ベクターには、WINDOWS で動くものも公開されています。
無料ですので、一度試してみたらいかがでしょう。
そうですね、変に先読みしようとしている感じがしますので
基本的に「関数名+(」まで検知できればほとんどの文法を一意に決められるので
LL(2)もあればほとんどの解析はうまくいくはずので
ちょっとライブラリの中調べなおして
まともな速度が出る方法調べてきます
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 発達障害・ダウン症・自閉症 中学の時にIQ82の境界知能と診断されました。 今の私も、やはり境界知能でしょうか? そしてこれは、 3 2023/02/19 00:37
- 宇宙科学・天文学・天気 AIが答えた方程式 1 2023/02/20 00:12
- 教育・学術・研究 仕事の方向性を変えたい。経営分析→数値解析 1 2023/06/18 16:51
- その他(プログラミング・Web制作) 大学のゼミのレポートがムカつきます。 R言語というデータ分析に特化したプログラム言語を用いた授業の課 1 2023/06/29 00:50
- 大学受験 3浪しようと思うので、アドバイスお願いします。 自分としては結構メンタルきつくて後期でいいから、東京 3 2023/02/13 21:47
- 大学受験 国立受験 11月からの大逆転劇を起こすには 7 2022/11/14 19:24
- 大学受験 娘の大学受験勉強 6 2022/06/30 19:58
- 国家公務員・地方公務員 公務員試験の数的処理で苦戦しています。 1 2023/01/30 08:56
- 大学受験 自己推薦書の添削や意見・アドバイスお願いします 2 2022/08/27 19:34
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
0除算して、落ちるプログラムと...
-
C++ で、「)」が必要 というエ...
-
io.hをincludeするとそのような...
-
Visual C++とVisual C++.NETの違い
-
コンパイルできない
-
どのプログラミング言語ででき...
-
volatile修飾について
-
Visual StudioのGUIとコマンド...
-
makeのエラーについて
-
__extension__
-
バイナリファイルとソースコー...
-
C言語のワーニングメッセージの...
-
C++でアボート(Abort)で処理が...
-
ccコマンドの使い方
-
isnanの取り扱いについて
-
コンパイラの制限 : ヒープの領...
-
プリコンパイラとは?
-
Fortranのサブルーチン呼び出し...
-
UNIX フォートラン 数値計算精度
-
困っています。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
0除算して、落ちるプログラムと...
-
C++ で、「)」が必要 というエ...
-
コンパイルできない
-
C++でアボート(Abort)で処理が...
-
変数(関数)名の頭に_
-
Visual C++とVisual C++.NETの違い
-
Eclipseの環境設定について
-
volatile修飾について
-
コンパイラについて
-
linuxのセキュリティ対策と致し...
-
__extension__
-
io.hをincludeするとそのような...
-
コンパイラフラグ(compiler fla...
-
PICマイコンによる乱数の表示に...
-
conio.h? curses.h?
-
【エラー】Cpadで初めてコンパイル
-
ABAQUS ユーザーサブルーチン...
-
関数の戻り値による変数の初期化
-
Delphiの逆コンパイル
-
プリコンパイラとは?
おすすめ情報