Python Pyparsing-从解析操作解析子语法

Python Pyparsing-从解析操作解析子语法,python,pyparsing,Python,Pyparsing,我有一个由“语句”列表组成的文件,每个“语句”都包含一个以逗号分隔的可变长度“列”列表,其中语句的结尾用分号表示: head( col1, col2 ); head2( col1, col2, col3 ); 我有一个完整文件的工作语法,但是如果其中一列中有语法错误,错误消息的信息就不是很丰富——它本质上说整个语句在开头部分不好 所以我想分别分析每一列,这样可以更详细地报告该列中的错误。以下内容将解析整个文件(两条语句),并打印解析操作中的每条语句和列列

我有一个由“语句”列表组成的文件,每个“语句”都包含一个以逗号分隔的可变长度“列”列表,其中语句的结尾用分号表示:

head(
    col1,
    col2
);
head2(
    col1,
    col2,
    col3
);
我有一个完整文件的工作语法,但是如果其中一列中有语法错误,错误消息的信息就不是很丰富——它本质上说整个语句在开头部分不好

所以我想分别分析每一列,这样可以更详细地报告该列中的错误。以下内容将解析整个文件(两条语句),并打印解析操作中的每条语句和列列表:

from pyparsing import Group, Literal, ParseException
from pyparsing import SkipTo, Suppress, commaSeparatedList
from pyparsing import Word, ZeroOrMore, alphas, alphanums

def parse_stmt(strng, loc, toks):
    print("++",toks,"++",loc,"++")

def parse_col(strng, loc, toks):
    # cols = commaSeparatedList(toks)
    print("==",toks,"===",loc,"==")

specs = '$_-'
name = Word(alphas+specs, alphanums+specs)
term = Literal(')') + Literal(';')
init = name
statement = Group(init.setParseAction(parse_stmt) + Suppress(Literal('(')) + \
            SkipTo(term).setParseAction(parse_col) + Suppress(term))
script = ZeroOrMore(statement)

ss = '\
abc(d 45, e, f g h); \
s2("much" "stuff", 34 48); \
'

print(ss)
try:
    print(script.parseString(ss))
except ParseException as err:
    print(" "*(err.column-1) + "^")
    print(err)
导致:

abc(d 45, e, f g h); s2("much" "stuff", 34 48); 
++ ['abc'] ++ 0 ++
== ['d 45, e, f g h'] === 4 ==
++ ['s2'] ++ 21 ++
== ['"much" "stuff", 34 48'] === 24 ==
[['abc', 'd 45, e, f g h'], ['s2', '"much" "stuff", 34 48']]
但是,当我试图通过取消注释
cols=commaSeparatedList(toks)
来解析列列表时,一切都崩溃了:

abc(d 45, e, f g h); s2("much" "stuff", 34 48); 
++ ['abc'] ++ 0 ++
Traceback (most recent call last):
  File "pt.py", line 27, in <module>
    print(script.parseString(ss))
  File "pyparsing.py", line 1115, in parseString
    loc, tokens = self._parse( instring, 0 )
  File "pyparsing.py", line 989, in _parseNoCache
    loc,tokens = self.parseImpl( instring, preloc, doActions )
  File "pyparsing.py", line 2732, in parseImpl
    loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False )
  File "pyparsing.py", line 989, in _parseNoCache
    loc,tokens = self.parseImpl( instring, preloc, doActions )
  File "pyparsing.py", line 2624, in parseImpl
    return self.expr._parse( instring, loc, doActions, callPreParse=False )
  File "pyparsing.py", line 989, in _parseNoCache
    loc,tokens = self.parseImpl( instring, preloc, doActions )
  File "pyparsing.py", line 2378, in parseImpl
    loc, exprtokens = e._parse( instring, loc, doActions )
  File "pyparsing.py", line 1015, in _parseNoCache
    tokens = fn( instring, tokensStart, retTokens )
  File "pyparsing.py", line 779, in wrapper
    ret = func(*args[limit[0]:])
TypeError: parse_col() missing 3 required positional arguments: 'strng', 'loc', and 'toks'
abc(d45,e,fgh);s2(“很多”东西”,34 48);
++['abc']++0++
回溯(最近一次呼叫最后一次):
文件“pt.py”,第27行,在
打印(script.parseString(ss))
文件“pyparsing.py”,第1115行,parseString格式
loc,标记=self.\u解析(instring,0)
parseNoCache中第989行的文件“pyparsing.py”
loc,tokens=self.parseImpl(指令、预指令、动作)
parseImpl中的文件“pyparsing.py”,第2732行
loc,tokens=self.expr.\u parse(instring,loc,doActions,callPreParse=False)
parseNoCache中第989行的文件“pyparsing.py”
loc,tokens=self.parseImpl(指令、预指令、动作)
parseImpl中的文件“pyparsing.py”,第2624行
返回self.expr.\u parse(instring、loc、doActions、callPreParse=False)
parseNoCache中第989行的文件“pyparsing.py”
loc,tokens=self.parseImpl(指令、预指令、动作)
parseImpl中第2378行的文件“pyparsing.py”
loc,exprtokens=e.(指令,loc,动作)
文件“pyparsing.py”,第1015行,在_parseNoCache中
令牌=fn(instring、令牌start、retTokens)
包装器中第779行的文件“pyparsing.py”
ret=func(*参数[限制[0]:])
TypeError:parse_col()缺少3个必需的位置参数:“strng”、“loc”和“toks”
我的问题不涉及多线程或递归,但它确实表明对pyparsing的可重入调用存在问题,可能与

有没有一种简单的方法可以从一个动作调用pyparsing例程,一种比这个问题的答案更简单的方法

cols = commaSeparatedList(toks)


几乎可以修复它,至少对于您给出的数据示例而言。然而,“很多”东西似乎破坏了csl解析器,可能是因为它希望在“很多”的结尾后有一个逗号。

Ahh,感谢你指出我愚蠢的语法错误-
cols=commaSeparatedList(toks[0])
至少让我重新开始,而parseString使它变得有意义。别忘了parseString()方法-您要使用的是commaSeparatedList.parseString(toks[0])
cols = commaSeparatedList.parseString(toks[0])