範囲を生成するようなあれ(パース編)
きのうのつづきで範囲構文を解析することにする。
パーサはさくっと構文解析ライブラリにまかせる。
python パーサ
で検索しただけだけど、BNF っぽく書けることで雑に採用。
もっとも BNF がこれでいいのかは自信がないが、doctest が通ってるしいいことにしよう。
$ sudo easy_install pip $ sudo pip install lark-parser
チュートリアルを眺めつつ、こんなかんじで書けた。
#!/usr/bin/env python # coding: utf-8 ''' >>> list(parse("1")) [1] >>> list(parse("1,2")) [1, 2] >>> list(parse("1,2,5-7")) [1, 2, 5, 6, 7] >>> list(parse("1,2,5-7,9-10,13")) [1, 2, 5, 6, 7, 9, 10, 13] ''' import itertools from lark import Lark, Transformer, v_args @v_args(inline=True) class RangeSyntax(Transformer): concat = itertools.chain def constant(self, x): return itertools.repeat(int(x), 1) def range(self, start, end): return xrange(int(start), int(end) + 1) parser = Lark(''' ?expr : expr "," expr -> concat | NUMBER "-" NUMBER -> range | NUMBER -> constant %import common.NUMBER %import common.WS %ignore WS ''', start='expr', parser='lalr', transformer=RangeSyntax()) parse = parser.parse if __name__ == '__main__': import doctest doctest.testmod()