class YbookMLParser prechigh left CHARACTER nonassoc LOW preclow rule target : text { p val[0] } | /* none */ { "" } text : text string { result = val[0] + val[1] } | string string : command | word = LOW command : '*' word arguments { result = "\\#{val[1]}#{val[2]}" } | word argument { last_char = val[0][val[0].size - 1] result = val[0][0..(val[0].size - 2)] + "\\ff#{last_char}#{val[1]}"} arguments : arguments argument { result = val[0] + val[1] } | argument argument : '[' text ']' { result = "{#{val[1]}}" } word : word CHARACTER { result = val[0] + val[1] } | CHARACTER end ---- header require 'strscan' require 'pp' OPERATOR = %w(* [ ]) ---- inner def initialize end def parse(text) @text = text @s = StringScanner.new(text) @scaned = [] while m = scan_operator || plain do @scaned.push m # enqueue end pp @scaned do_parse end def next_token @scaned.shift # dequeue end def scan_operator OPERATOR.each do |op| if @s.scan(Regexp.new(Regexp.escape(op))) return [@s[0], @s[0]] end end nil end def plain if @s.scan(/./m) [:CHARACTER, @s[0]] end end def on_error(t, val, vstack) raise ParseError, "\nunexpected token #{val.inspect}" end ---- footer if $0 == __FILE__ parser = YbookMLParser.new p parser.parse(STDIN.read) end =begin #ふりがな 対象の文字:x 振るふりがな:y とすると x[y] のように表記する 例.  本[ほん]日[じつ]は晴[せい]天[てん]なり 複数文字のルビを振るときは *furigana[x][y] のように表記する 例. *furigana[紫陽花][あじさい]が咲いている #その他のコマンド その他のコマンドも基本的に *command[x][y][z]... のように表記する 引数は1個以上でコマンドごとに可変 引数内にさらにコマンドを書くこともできる *command[*command2[a]][y][z]... =end