使用pyparsing

时间:2016-01-28 22:42:07

标签: python-2.7 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+"~#!@£$%^&*()'-+/{}[]=. ")
limit_state=CaselessLiteral("REACHED")|CaselessLiteral("NOT_REACHED")|CaselessLiteral("RETIRED")


#define grammar for user comment
StringStart=CaselessLiteral("COMMENT")
comment_text=Word(alphanums+"#!@£$%^&*()<>'/{}[]=. ")
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')

请考虑以下

  

评论 - &gt;欢迎来到银行;

这传递并且令牌是['评论','欢迎银行一',';']

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

这传递并且令牌是

  

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

但是当&gt;是在“错误”的地方?

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

这对我来说似乎不适用于&gt;在描述中导致错误。所以重新定义这样的描述

  

description = Word(alphanums +“〜#!@£$%^&amp; *()' - + / {} [] =。&gt;”)

应该有效,但它会破坏注释语法。 我只想要分隔符 - &gt;被视为一个

考虑一下我不认为

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

肯定我只需要

delimiter=Suppress("->")

谢谢,@保罗。我试过你的建议。

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

我不知道我输错了什么,但打破连字符证明有点棘手

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

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

  
      
  • (' - '+〜FollowedBy('&gt;')   期望在单词之后出现连字符( - ),因为它必须如此,所以

         

    CUSTOMER_LIMIT_REACHED-&gt; 1234_A0001 [Harry-mop] - &gt; NOT_REACHED;   但失败了   CUSTOMER_LIMIT_REACHED-&gt; 1234_A0001 [Harry-mop] - &gt; NOT_REACHED;   通行证。

  •   

经过一些实验后我稍微调整了答案

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

感谢让我走上正确的道路

1 个答案:

答案 0 :(得分:1)

是的,问题在于

description=Word(alphanums+"~#!@£$%^&*()'-+/{}[]=. ")

如果您添加&#39;&gt;&#39;对于description中的这组允许字符,pyparsing将无法区分&#39; - &gt;&#39;这是描述与&#39; - &gt;&#39;的一部分。这是分隔符(因为&#39; - &#39;&#39;&gt;&#39;包含在允许的字符集中)。

你需要实施一个消极的前瞻,以便&#39; - &#39;或者&#39;&gt;&#39;单独将是可接受的描述内容。但是,在Word的令牌构建中,没有办法做到这一点。你需要突破&#39; - &#39; (作为&#39; - &gt;&#39;)中的主角作为一个单独的东西。

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

将整个事物包含在一个Combine中,以便pyparsing不会为此描述的单独位提供单独的字符串:

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

此时,delimiter = Suppress('->')就足够了。