我怎样才能获得令牌而不是字符串?

时间:2015-04-09 20:55:08

标签: python pyparsing

我有以下语法:

kv = Word(alphanums + '_') | QuotedString('"', escQuote="\\") | QuotedString("'", escQuote="\\")
kv = kv.setResultsName('literal', listAllMatches=True)
cskv = kv + Optional(ZeroOrMore(Suppress(',') + kv))  # comma separated kv

并使用此示例:

>>> res=cskv.parseString('a,b,c,d,e')
>>> res
(['a', 'b', 'c', 'd', 'e'], {'literal': [('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4)]})
>>> res[0]
'a'
>>> type(res[0])
<type 'str'>

通知:

>>> type(res[0])
<type 'str'>

我真的希望它是ParseResults,而不是字符串,这样我就可以res[0].getName(),希望我能得到literal

第二个问题是如何获得某些令牌的索引?

假设我想知道literal d的索引,它应该返回3

在这个例子中它是微不足道的,因为我只有一种类型的令牌,但在我的问题中,我需要知道不同类型的令牌的相对位置,以便在处理时有所帮助。

任何实现这些目标的方法?

编辑:

我不知道为什么我的问题如此令人困惑,为什么人们会继续关注我的例子而不是我的问题。以下是更加明确的说明:

我使用pyparsing作为一个标记器来标记一个字符串来解释它,我遇到的问题是,我需要知道那个标记是什么,让我们说(这意味着它是一个不值得关注的例子) ):

variable = string

如果某种语言支持这一点,并且它知道字符串恰好是一个左值,那么它就是一个变量,如果它是正确的值它将是一个字符串(不要问我为什么是这样,它已经组成了)。

所以我期待这种语法:

expr = Word(alphanums+'_')('leftval') + '=' + Word(alphanums+'_')('rightval')

最后,该表达式应该被完全标记化:

In [3]: res = expr.parseString('variable = string')

In [4]: res
Out[4]: (['variable', '=', 'string'], {'rightval': [('string', 2)], 'leftval': [('variable', 0)]})

但这是我的问题:

In [5]: res[0]
Out[5]: 'variable'

In [6]: type(res[0])
Out[6]: str

现在res给了我一个字符串。我需要一个令牌工作器,包括令牌后面的信息,现在我丢失了令牌的名称,该名称应为leftval

有趣的是,__repr__的{​​{1}}已显示我需要的所有信息:

令牌名称,以及所有捕获的令牌本身以及令牌化结果res中的位置。

看到了吗?

这正是我的问题。不是如何用pyparsing处理逗号分隔值。

2 个答案:

答案 0 :(得分:0)

我不确定这是否能回答你的问题

from pyparsing import Word, alphas,alphanums,QuotedString,Optional,ZeroOrMore,Suppress

kv = Word(alphanums + '_') | QuotedString('"', escQuote="\\") | QuotedString("'", escQuote="\\")
kv = kv.setResultsName('literal', listAllMatches=True)
cskv = kv + Optional(ZeroOrMore(Suppress(',') + kv))  # comma separated kv
tokens = cskv.parseString("a,b,c,d,e")

#you can use asDict to get a dictionary mapping names to values
print tokens.asDict()

#or you can get it as xml and parse the xml
import re
xml_result = tokens.asXML()
for tok in tokens:
    needle = "\<([^\>]+)\>\s*%s\s*\<\/"%tok
    print tok, "=", re.search(needle,xml_result).groups()[0]

可能有更好的方法来做到这一点......我不确定......它也可能会破坏更复杂的语法......

根据您的评论尝试

import ast
parsed_values,meta_data = ast.literal_eval(repr(tokens))
print parsed_values # ['a', 'b', 'c', 'd', 'e']
print meta_data # {'literal': [('a', 0), ('b', 1), ('c', 2), ('d', 3), ('e', 4)]}

答案 1 :(得分:0)

根据pyparsing文档,存在 delimitedList 函数,它用于解析由特定分隔符分隔的多个字符组成的特定字符串。

我会引用它:

  

帮助器定义分隔符表达式列表 - 分隔符默认为“,”。默认情况下,列表元素和分隔符可以有插入的空格和注释,但这可以通过在构造函数中传递combine = True来覆盖。如果将combine设置为True,则匹配的标记将作为单个标记字符串返回,并包含分隔符;否则,匹配的标记将作为标记列表返回,并且分隔符被抑制。

现在你只需要使用它并使用它解析一个字符串来获取 ParseResult 对象:

csvExpr = delimitedList()

parsed = csvExpr.parseString("a,b,c,d,e")

print(type(parsed)) # output: <class 'pyparsing.ParseResults'>