29
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ANTLRを使って構文解析を行う

Last updated at Posted at 2021-07-27

0. はじめに

ANTLRを使って少し構文解析を行いましたので、備忘録として記事にしてみました。

1. ANTLRとは

アントラーと読みます。
構文解析を行うためのツールになります。
解析のためのルールを記述する**grammar(グラマー)をいうファイルを作成することで、与えられたテキストをそのルールに応じて振り分けすることができます。
グラマーは
lexer(レクサー)parser(パーサー)**という文法を使って記述します。
以下は公式サイトのサンプルgrammarファイルになります。

sample.g4
grammar Expr;		

/**
 * parser
 */
prog:	(expr NEWLINE)* ;
expr:	expr ('*'|'/') expr
    |	expr ('+'|'-') expr
    |	INT
    |	'(' expr ')'
    ;

/**
 * lexer
 */
NEWLINE : [\r\n]+ ;
INT     : [0-9]+ ;

1-1. lexer

  • lexerとは、字句解析器になります。
  • 正規表現を使って「この変数にはこんな値が入るよ」を定義します。
  • 上記サンプルgrammarファイルの「lexer」部分になります。

1-2. parser

  • parserとは、構文解析器になります。
  • 「解析する構文はこんな感じで振り分けるよ」を定義します。
  • 上記サンプルgrammarファイルの「parser」部分になります。

2. 環境構築

※VSCodeはインストールされている前提とさせて頂きます。
VSCodeに、拡張機能であるANTLR4 grammar syntax supportをぶち込みます。

元々環境構築やデバッグが少し手間だったのですが、これを使えばめちゃくちゃ楽になります。
自分が使った機能としては、以下のようなものがあります。

  • シンタックスハイライト機能
  • デバッグ機能(構文解析結果がイメージで確認できる)
  • 言語に応じたジェネレート機能

他にもたくさんのことができるようです。詳しくはvscode-antlr4をご参照ください。

キャプチャ.PNG

3. グラマーファイルを作成する

それでは、グラマーファイルを作成していきます。
lexerとparser、1ファイルで書くことも、別々のファイルで書くこともできますが、当記事では1ファイルで書いています。
そして今回は子供達にも喜んでもらえるよう、きめつちっくな構文を解析してみます。

| 入力文字列(例) | | 種別 | 番号 | 名前 | オプション |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 水の呼吸拾壱の型凪 | | 水 | 拾壱 | 凪 | - |
| 雷の呼吸壱の型霹靂一閃(六連) | | 雷 | 壱 | 霹靂一閃 | 六連 |

「入力文字列」を与えることで、「種別」「番号」「名前」「オプション」として解析できるようにします。
オプションてなんやねんて感じですが、六連なのか八連なのか神速なのか、名前だけでは情報が不足する場合もあるので。。。
結果、グラマーファイルは以下のように書いてみました。

Breathing.g4
grammar Breathing;

/**
 * parser
 */
breathing :
    // [TYPE]の呼吸[NUM]の型[NAME]([OPTION])
    type '\u306e\u547c\u5438' num '\u306e\u578b' name ('('option')')?
    ;

type :
    TYPE
    ;

name :
    (ANY)+
    ;

num :
    NUMBER
    ;

option :
    (NUMBER | ANY)+
    ;

/**
 * lexer
 */
TYPE :
    // 水炎雷風岩蟲花恋蛇音獣月日
    [\u6c34\u708e\u96f7\u98a8\u5ca9\u87f2\u82b1\u604b\u86c7\u97f3\u7363\u6708\u65e5]
    ;

NUMBER :
    // 壱弐参四五六七八九拾
    [\u58f1\u5f10\u53c2\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u62fe]+
    ;

ANY : 
    .
    ;

4. テキストを与えてデバッグしてみる

4-1. launch.jsonを作成

.vscodeフォルダ配下に、launch.jsonファイルを作成し、以下のように記載します。

launch.json
{
  "version": "1.0.0",
  "configurations": [
      {
          "name": "Debug ANTLR4 grammar", // 任意の名前
          "type": "antlr-debug",          // 決め打ち(多分)
          "request": "launch",            // 決め打ち(多分)
          "input": "input.txt",           // 入力となるテキストを記述したファイル
          "grammar": "Breathing.g4",      // 使用するグラマーファイル
          "printParseTree": true,         // デバッグ結果をデバッグコンソールに表示するか
          "visualParseTree": true         // デバッグ結果をグラフィカルなツリーで表示するか
      },
    ]
}

4-2. デバッグ実行①

input.txtに、以下を入力して、VSCodeでデバッグ実行します。

input.txt
水の呼吸拾壱の型凪

以下のような実行結果になればOK!

2.PNG

4-3. デバッグ実行②

input.txtに、以下を入力して、VSCodeでデバッグ実行します。

input.txt
雷の呼吸壱の型霹靂一閃(六連)

以下のような実行結果になればOK!

3.PNG

5. プログラミング言語に合わせたコードを出力する

5-1. settings.jsonを作成

.vscodeフォルダ配下に、settings.jsonファイルを作成し、以下のように記載します。
なお、他にも色々な設定することができます。詳しくはvscode-antlr4(extension-settings)をご参照ください。

settings.json
{
	"antlr4.generation":{
		"mode": "external",   // 決め打ち(多分)
		"language": "CSharp", // 出力したいプログラミング言語名
		"listeners": true,    // listener形式で出力するか
		"visitors": false,    // visitor形式で出力するか
		"alternativeJar": "antlr-4.9-complete.jar", // ANTLRのjarファイル(※)
		"outputDir": "parser" // 出力先のフォルダ名
	}
}

(※)ANTLRのバージョンを指定したい場合に設定します。指定しないと4.8で出力されます。ANTLRの各バージョンのjarはこちらからダウンロードできます。

5-2. コードを出力する

グラマーファイルを保存(Ctrl + s)すれば、outputDirで指定したフォルダにコードが生成されます。

1.PNG

6. GitHub

antlr_breathing

7. おわりに

個人的に普段は使わないような技術なので、新鮮な気持ちで取り組むことができました:innocent:
当技術をピンポイントで使うことはあまりないかもしれませんが、何かしらに応用できればと思います:innocent:

8. 参考

29
17
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
17

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?