2

我在继承定义时努力工作setParseAction(我不知道如何用英语表达,所以举个例子):

from __future__ import division
from decimal import Decimal

from pyparsing import Word, alphas, ParseException, Literal, CaselessLiteral \
        , Combine, Optional, nums, Or, Forward, ZeroOrMore, StringEnd, alphanums, Suppress \
        , sglQuotedString, dblQuotedString, Group \
        , restOfLine, Regex, stringEnd


class ASTNode(object):
    def __init__(self, tokens):
        self.tokens = tokens
        self.assignFields()

    def __str__(self):
        return self.__class__.__name__ + ':' + str(self.__dict__)
    __repr__ = __str__


class ConstantNode(ASTNode):
    def assignFields(self):
        #print "  ", self.tokens
        self.setValue(self.tokens[0])

    def transform(self, value):
        return value

    def setValue(self, value):
        self.constant = self.transform(value)
        del self.tokens


class StringNode(ConstantNode):
    pass


class BoolNode(ConstantNode):
    def transform(self, value):
        return bool(value)


class IntNode(ConstantNode):
    def transform(self, value):
        return int(value)


class FloatNode(ConstantNode):
    def transform(self, value):
        print value
        return Decimal(value)


class AssignmentNode(ASTNode):
    def assignFields(self):
        #print self.tokens
        self.lhs, self.rhs = self.tokens
        del self.tokens


LPAR, RPAR, LBRACK, RBRACK, LBRACE, RBRACE, SEMI, COMMA = map(Suppress, "()[]{};,")

PLUS = Literal("+")
MINUS = Literal("-")
MULT = Literal("*")
DIV = Literal("/")

ASSIGN = Literal("=")
POINT = Literal('.')

TRUE = Literal('True')
FALSE = Literal('False')

SEP = Literal(':').suppress()

NAME = Word(alphas + '_?', alphanums + '_?')
TYPE = SEP + NAME
COMMENT = "#" + restOfLine

BOOLEANS = TRUE | FALSE
BOOLEANS.setParseAction(BoolNode)

EXPR = Forward()

ADDOP = PLUS | MINUS
MULTOP = MULT | DIV
PLUSORMINUS = PLUS | MINUS

#Strings
STR = dblQuotedString.setParseAction(ConstantNode) | sglQuotedString.setParseAction(ConstantNode)

STRINGS = STR

#Numbers
NUMBER = Word(nums)
INTEGER = Combine(Optional(PLUSORMINUS) + NUMBER)
FLOATNUMBER = Combine(INTEGER.copy() +
                       Optional(POINT + Optional(NUMBER)) +
                       Optional(INTEGER.copy())
                )

MONEY = Combine(FLOATNUMBER.copy() + Word("$").suppress())
TYPED_FLOATNUMBER = Combine(FLOATNUMBER + Word(alphas))

INTEGER.setParseAction(IntNode)
FLOATNUMBER.setParseAction(FloatNode)

NUMBERS = MONEY | TYPED_FLOATNUMBER | FLOATNUMBER


TEST_GRAMMAR = """
#Single values
True
False
1 #Int32
1.0 #Float
1$ #MONEY
25.3mt #Typed number"""

一切都解析,但不调用布尔和整数节点,只调用浮点数。

['True']
['False']
1
[FloatNode:{'constant': Decimal('1')}]
1.0
[FloatNode:{'constant': Decimal('1.0')}]
['1']
['25.3mt']
[ConstantNode:{'constant': "'hello world'"}]
[ConstantNode:{'constant': '"hello world"'}]
['2002-08-10']
['100000']
['2002-08-10-100000']
1
[AssignmentNode:{'rhs': FloatNode:{'constant': Decimal('1')}, 'lhs': 'x'}]
1.0
[AssignmentNode:{'rhs': FloatNode:{'constant': Decimal('1.0')}, 'lhs': 'x'}]
[AssignmentNode:{'rhs': '1', 'lhs': 'x'}]
[AssignmentNode:{'rhs': '12.2mt', 'lhs': 'x'}]

我知道 setParseAction 与部分语法的定义有关。但是,我发现如果 chain 之类FLOATNUMBER的因为是基于INTEGER.

4

1 回答 1

0

您遗漏了执行实际解析的代码,因此我添加了以下代码:

for line in TEST_GRAMMAR.splitlines():
    if not line or line[0] == '#': continue
    print (BOOLEANS^INTEGER^NUMBERS).parseString(line)

给出这个输出:

[BoolNode:{'constant': True}]
[BoolNode:{'constant': False}]
[IntNode:{'constant': 1}]
1.0
[FloatNode:{'constant': Decimal('1.0')}]
['1']
['25.3mt']

我还必须修复 BoolNode 中的一个小错误:

class BoolNode(ConstantNode):
    def transform(self, value):
        return value.lower()=='true' #bool(value)

transform中,value 将是字符串 "True" 或 "False" 之一,但这bool两个字符串的值都是 True - 只有空字符串 "" 将返回 False 布尔值。

您遇到的问题之一是您对 FLOAT 的定义也将匹配 INTEGER,因此您可能会考虑重新定义 FLOAT 以要求前导、尾随或嵌入的小数点。我通过使用 '^' 而不是 '|' 解决了这个问题 作为“或”运算符。'^' 将测试所有给定的备选方案并选择最长的匹配项,'|' 将短路并选择第一个匹配项。

于 2012-12-31T06:06:26.137 回答