bambooflow Note

SimpleCalc

最終更新:

bambooflow

- view
メンバー限定 登録/ログイン

SimpleCalc


簡単な構文からANTLRの基礎の基礎を固める。


まずは簡単な足し算器を


  • SimpleCalc.g
grammar SimpleCalc;
 
options { language = Ruby; }
 
prog returns [result]
  : r1=INTEGER '+' r2=INTEGER { $result = $r1.text.to_i + $r2.text.to_i }
  ; 
 
INTEGER : DIGIT+ ;
 
fragment
DIGIT : '0' .. '9' ;
 
WS: (' '|'\t'|'\n')+ {$channel=HIDDEN};
 

% antlr4ruby SimpleCalc.g

次にテスト用のスクリプトファイルを用意

  • test.rb
require 'rubygems'
require 'SimpleCalcLexer'
require 'SimpleCalcParser'
 
fetch =
  begin
    require 'readline'
    proc do
      Readline.readline ">>>", true
    end
  rescue LoadError
    proc do
      print ">>>"
      l = $stdin.gets and l.chomp
    end
  end
 
puts "enter calculator expressions or 'quit' to exit"
 
loop do
  case line = fetch.call
  when /q(uit)?/i, /e(xit)?/i, nil then break
  else
    printf "\t=> %s\n", SimpleCalc::Parser.new( line ).prog
  end
end
 

この記述は、1行ごと構文解析を行う。
別の場所でも使いまわしができる。


  • 実行してみる

% ruby test.rb
enter calculator expressions or 'quit' to exit
>>>2+3
        =>5

Tokenのメソッド


ここでTokenのメソッドがどのようなものがあるか気になったので少し調べてみた。
r1,r2はTokenモジュール。
Tokenはlib/antlr3/token.rbで定義されている。

メソッド DataType 説明
text String or nil トークンを文字列として取得
type Integer トークンの名前, SimpleCalcなら"INTEGER"とか
line Integer トークンの行位置
column Integer トークンの列位置
channel Symbol チャネル設定,HIDDEN_CHANNELが設定されたトークンは字句解析の対象から除外される
index Integer トークン番号
input トークン入力
start Integer トークン開始位置
stop Integer トークン終了位置
<=>
concrete? boolean
imaginary? boolen
name String typeを取得
source_name String
hidden? boolean トークンがhiddenかどうか
inspect 検査、デバッグ用?
hide! トークンをhidden(隠し)に設定
pretty_print inspect内容を引数のprinterに渡す
range
to_i Integer indexを数値として取得(注意としてトークンを数値に変換するものではない=>.text.to_iを使う)
to_s String text.to_sと同義

よく使うのはもっぱらtextくらいかな。
あとは内部制御で使うものが多い。

つまり、トークンを扱うときは"text"だけ覚えておけばとりあえず問題なさそう。


メモ


  • grammar SimpleCalc;とすることで、SimpleLexerクラスとSimpleParserクラスを生成する
  • options { language = Ruby; }で出力形式をRuby言語とする
  • fragmentはそれ自体をトークンとせずマクロ扱いにする
  • $channel=HIDDEN は一致したトークンを字句解析から除外する(隠す)


足し算と引き算をする


足し算器に引き算器を追加してみた。

grammar SimpleCalc;
 
options { language = Ruby; }
 
 
prog returns [result]
  : r=expression { $result = $r.result }
  ;
 
expression returns [result]
  : r1=atom
  ( '+' r2=atom { $r1.result += $r2.result }
  | '-' r2=atom { $r1.result -= $r2.result }
  )* { $result = $r1.result }
  ;   
 
 
atom returns [result]
  : n=INTEGER { $result = n.text.to_i }
  ;
 
INTEGER : DIGIT+ ;
 
fragment
DIGIT : '0' .. '9' ;
 
WS: (' '|'\t'|'\n')+ {$channel=HIDDEN};
 


構文にexpressionとatomを追加した。
expressionは加減算、atomはトークン文字列を数値に変換している。
expressionをみると、returnsで返すresultを使って計算している。これで計算結果を渡す。

タグ:

ANTLR ruby
記事メニュー
目安箱バナー