私は pyparsing を使って pig という言語を解析しています。入力テキストに「\t」が含まれているときに関数「lineno」を使用すると、予期しない結果が見つかりました。
質問しやすいように、問題に対処するためにコードを単純化しました。
#/usr/bin/env python
from pyparsing import *
ident = Word(alphas)
statement1 = ident + Literal('=')+ Keyword('GENERATE', caseless = True) + SkipTo(Literal(';'),ignore = nestedExpr())+ Literal(';').suppress()
statement2 = Keyword('STORE',caseless = True) + ident + Literal(';').suppress()
statement = statement1|statement2
text = """
fact = GENERATE
('Exp' :(a
)
) ;
STORE fact ;
"""
all_statements = statement.scanString(text)
for tokens,startloc,endloc in all_statements:
print 'startloc:' + str(startloc) , 'lineno:' + str(lineno(startloc,text))
print 'endloc:' + str(endloc), 'lineno:' + str(lineno(endloc,text))
print tokens
入力テキストでは、3 行目の先頭に 3 つ以上の '\t' があることに注意してください。これを実行すると、出力は次のようになります。
startloc:1 lineno:2
endloc:66 lineno:10
['fact', '=', 'GENERATE', "('Exp' :(a\n )\n) "]
startloc:68 lineno:10
endloc:80 lineno:10
['STORE', 'fact']
全部で 9 行あるので、これは間違っているはずです。最初のステートメントは 2 行目から 10 行目までです。これらの '\t' を削除すると、入力テキストは :
text = """
fact = GENERATE
('Exp' :(a
)
) ;
STORE fact ;
"""
もう一度実行すると、結果は次のようになります。
startloc:1 lineno:2
endloc:34 lineno:5
['fact', '=', 'GENERATE', "('Exp' :(a\n)\n) "]
startloc:36 lineno:7
endloc:48 lineno:7
['STORE', 'fact']
そして、この結果は正しいようです。最初のステートメントは 2 行目から 5 行目までであり、2 番目のステートメントは 7 行目から 7 行目までです。これは私が期待したものです。
したがって、lineno() 関数または scanString に問題がある可能性があります。または、私のコードに何か問題があるのでしょうか?