2016-01-28 74 views
2

我正在尝试为某些文本编写解析器。我究竟做错了什么? 考虑以下pyparsing代码使用pyparsing的自定义分隔符

from pyparsing import CaselessLiteral,StringEnd,Suppress,alphanums,alphas,alphas, 
Word,ParseException,ParseResults,nums,Group,ZeroOrMore,ParseElement,restOfline,Combine,Optional,Literal,LineEnd 
ParseElement.enablePackrat() 
import lxml.etree 

#define common syntax 
delimiter=Supress("->")|Suppress(">") 
line_ending=";" 
cust_seperator="_" 
cust_code=Word(alphanums) 
description=Word(alphanums+"~#[email protected]£$%^&*()'-+/{}[]=. ") 
limit_state=CaselessLiteral("REACHED")|CaselessLiteral("NOT_REACHED")|CaselessLiteral("RETIRED") 


#define grammar for user comment 
StringStart=CaselessLiteral("COMMENT") 
comment_text=Word(alphanums+"#[email protected]£$%^&*()<>'/{}[]=. ") 
usercomment_syntax=(StringStart+delimiter+comment_text+line_ending).setResultsNmae('user_comment') 

#define grammar for upperlimit 
StringStart=CaselessLiteral("CUSTOMER_LIMIT_REACHED") 
cust_code_prefix=Word(alphanums,max=6) 
customer_identifier=Combine(cust_code_prefix+Optional(cust_seperator)+cust_code+Optional(description)) 
customerupperlimit=(StringStart+delimiter+customer_identifier+delimiter+limit_state+line_ending).setResultsNmae('customer_upper_limit') 

所以考虑以下

COMMENT->欢迎银行之一;

这通过和令牌是[ 'COMMENT', '欢迎来到银行一个', ';']

CUSTOMER_LIMIT_REACHED->1234_A0001 [Harry mop]->NOT_REACHED; 

这通过和令牌是

['CUSTOMER_LIMIT_REACHED','1234_A0001 [Harry mop]','NOT_REACHED',';']

但是当一个>在“错误”的地方会发生什么?

CUSTOMER_LIMIT_REACHED->1234_A0001 [Sally >12 top]->NOT_REACHED; 

这似乎并不为我工作的描述中的外观>导致错误。因此,重新定义的描述,像这样

描述=字(alphanums +“!〜#@£$%^ & *() - +/{} [] =>“)

应该工作,但它打破了评论语法。 我只是想有分隔符 - >被视为一个

关于它的思考,我不认为

delimiter=Suppress("->")| Suppress(">") 

是正确的,我肯定只需要

delimiter=Suppress("->") 

谢谢,@保罗。我已经尝试了你的建议。

description = Combine(OneOrMore(Word(alphanums+"~#[email protected]£$%^&*()'+/{}[]=. >") + ('-' + ~FollowedBy('>')))) 

如果我打字一些错误,但打破了连字符,我不知道已被证明是有点棘手

CUSTOMER_LIMIT_REACHED->1234_A0001 [Harry-mop]->NOT_REACHED; 

现在失败了,如果我是对的,我相信

  • (' - '+〜FollowedBy('>') 会在单词之后出现一个连字符( - ),因为它必须,所以

    CUSTOMER_LIMIT_REACHED-> 1234_A0001 [Harry-mop] - > NOT_REACHED; 失败,但是 CUSTOMER_LIMIT_REACHED-> 1234_A0001 [Harry-mop] - > NOT_REACHED; 通行证。

我调整了答案后只是一个小一些试验

description = Combine(OneOrMore(Word(alphanums+"~#[email protected]£$%^&*()'+/{}[]=. >") + Optional('-' + ~FollowedBy('>')))) 

谢谢你让我在正确的道路上

回答

1

是的,问题是

​​

如果您在这组允许的字符中添加'>'description,pyparsing将无法区分作为描述的一部分的' - >'与作为分隔符的' - >'(因为' - '和'>'都包含在允许字符集中) 。

您需要实施负向预测,以便单独使用' - '或'>'作为描述的可接受内容。但是,在Word的标记构建中,没有办法做到这一点。你需要把' - '(作为' - >'中的主角)作为一个单独的东西来分解。

description = (OneOrMore(Word(alphanums+"~#[email protected]£$%^&*()'+/{}[]=. >") + 
        ('-' + ~FollowedBy('>')))) 

裹在这整个事情的一个结合,从而pyparsing不会给单独字符串此描述的单独位:

description = Combine(OneOrMore(Word(alphanums+"~#[email protected]£$%^&*()'+/{}[]=. >") + 
        ('-' + ~FollowedBy('>')))) 

在这一点上,delimiter = Suppress('->')应该是足够的。