Pythonの構文木を見る
ワンライナーから不要な空白文字を取り除くスクリプトを作ったのですが、「取り除いてパースに成功するなら取り除いてOK」とやってしまったので文字列の中の空白まで取り除かれてしまいました。そこできちんと構文木を眺めてみることにしました。love unstable: Pythonの構文木を見るを参考に。
import parser, symbol, pprint, token
def change(ast):
if type(ast) is list:
return map(change, ast)
else:
leaf = symbol.sym_name.get(ast, ast)
return token.tok_name.get(leaf, leaf)
parse = lambda s: change(parser.ast2list(parser.expr(s)))
pprint.pprint(parse("('1 1' * 2) + (3 - 4)"))
これで出力は
['eval_input',
['testlist',
['test',
['and_test',
['not_test',
['comparison',
['expr',
['xor_expr',
['and_expr',
['shift_expr',
['arith_expr',
['term',
['factor',
['power',
['atom',
['LPAR', '('],
['testlist_gexp',
['test',
['and_test',
['not_test',
['comparison',
['expr',
['xor_expr',
['and_expr',
['shift_expr',
['arith_expr',
['term',
['factor',
['power',
['atom',
['STRING', "'1 1'"]]]],
['STAR', '*'],
['factor',
['power',
['atom',
['NUMBER', '2']]]]]]]]]]]]]]],
['RPAR', ')']]]],
['STAR', '*'],
['factor', ['power', ['atom', ['NAME', 'x']]]]],
['PLUS', '+'],
['term',
['factor',
['power',
['atom',
['LPAR', '('],
['testlist_gexp',
['test',
['and_test',
['not_test',
['comparison',
['expr',
['xor_expr',
['and_expr',
['shift_expr',
['arith_expr',
['term',
['factor',
['power',
['atom',
['NUMBER', '3']]]]],
['MINUS', '-'],
['term',
['factor',
['power',
['atom',
['NUMBER', '4']]]]]]]]]]]]]]],
['RPAR', ')']]]]]]]]]]]]]]],
['NEWLINE', ''],
['ENDMARKER', '']]
当たり前ですが、文字列の中の空白は残って、トークンの間の空白は消えていますね。後はNAME、NUMBERなどが隣接するときには空白を挟み、RPAR(括弧)などは空白を挟まないでトークンを結合してやれば目的は果たせるでしょうかね…?