问题描述:

Using pyparsing i try to parse some text with a compound expression like

a = pp.Word(pp.alphas).setResultsName('A')

b = pp.Word(pp.nums).setResultsName('B')

c = pp.Word(pp.alphas).setResultsName('C')

expr = a + b + c

and parseString fails with the Exception

ParseException: Expected W:(0123...) (at char 7), (line:1, col:8)

So far so good. However, to understand better what's going on, is it possible to ask pyparsing/parseString to tell me directly what character from the input string didn't match? (I can, of course, calculate this myself from the information in the Exception text.)

Additionally is it possible to see in which sub-expression (a,b or c) the exception was raised?

网友答案:

Pyparsing exceptions include a method markInputline() that will print the last line of the input string and a marker where the exception occurred:

import pyparsing as pp
a = pp.Word(pp.alphas).setResultsName('A')
b = pp.Word(pp.nums).setResultsName('B')
c = pp.Word(pp.alphas).setResultsName('C')
expr = a + b + c
try:
    expr.parseString("lskdjf lskdjf sdlkfj")
except ParseException as pe:
    print(pe.markInputline())

lskdjf >!<lskdjf sdlkfj

(You can specify a different marker if you don't like '>!<'.)

Here is another method I've used that makes use of the col and line attributes of the ParseException:

alphaword = pp.Word(pp.alphas).setName('alphaword')
numword = pp.Word(pp.nums).setName('numword')
expr = alphaword('A') + numword('B') + alphaword('C')
try:
    expr.parseString('sldkj slkdj sldkj')
except ParseException as pe:
    print(pe.line)
    print(' '*(pe.col-1) + '^')
    print(pe)

sldkj slkdj sldkj
      ^
Expected numword (at char 6), (line:1, col:7)

A couple of other points:

  • I've used setName() to give the expressions themselves names, so that the exception messages are a little more readable. Please note the distinction between setName and setResultsName.

  • I've used the call syntax for defining results names. In practice (or just out of laziness) I found the '.setResultsName' method call to really detract from the grammar definition portion of the code. So in place of expr.setResultsName('xyz'), you can just write expr('xyz').

相关阅读:
Top