示例#1
0
    def _productiondefinition(self):
        """Return defintion used for parsing."""
        types = self._prods  # rename!

        def toSeq(t, tokens):
            "Do not normalize function name!"
            return t[0], t[1]

        funcProds = Sequence(
            Prod(name='expression',
                 match=lambda t, v: t == types.FUNCTION,
                 toSeq=toSeq),
            Sequence(
                Choice(
                    Prod(
                        name='nested function',
                        match=lambda t, v: t == self._prods.FUNCTION,
                        toSeq=lambda t, tokens: (
                            ExpressionValue._functionName,
                            ExpressionValue(
                                cssutils.helper.pushtoken(t, tokens)),
                        ),
                    ),
                    Prod(
                        name='part',
                        match=lambda t, v: v != ')',
                        toSeq=lambda t, tokens: (t[0], t[1]),
                    ),
                ),
                minmax=lambda: (0, None),
            ),
            PreDef.funcEnd(stop=True),
        )
        return funcProds
示例#2
0
    def test_init(self):
        "Choice.__init__()"
        p1 = Prod('p1', lambda t, v: t == 1)
        p2 = Prod('p2', lambda t, v: t == 2)
        t0 = (0, 0, 0, 0)
        t1 = (1, 0, 0, 0)
        t2 = (2, 0, 0, 0)

        ch = Choice(p1, p2)
        self.assertRaisesMsg(ParseError,
                             'No match for (0, 0, 0, 0) in Choice(p1, p2)',
                             ch.nextProd, t0)
        self.assertEqual(p1, ch.nextProd(t1))
        self.assertRaisesMsg(Exhausted, 'Extra token', ch.nextProd, t1)

        ch = Choice(p1, p2)
        self.assertEqual(p2, ch.nextProd(t2))
        self.assertRaisesMsg(Exhausted, 'Extra token', ch.nextProd, t2)

        ch = Choice(p2, p1)
        self.assertRaisesMsg(ParseError,
                             'No match for (0, 0, 0, 0) in Choice(p2, p1)',
                             ch.nextProd, t0)
        self.assertEqual(p1, ch.nextProd(t1))
        self.assertRaisesMsg(Exhausted, 'Extra token', ch.nextProd, t1)

        ch = Choice(p2, p1)
        self.assertEqual(p2, ch.nextProd(t2))
        self.assertRaisesMsg(Exhausted, 'Extra token', ch.nextProd, t2)
示例#3
0
    def test_initToStore(self):
        "Prod.__init__(...toStore=...)"
        p = Prod('all', lambda t, v: True, toStore='key')

        # save as key
        s = {}
        p.toStore(s, 1)
        self.assertEqual(s['key'], 1)

        # append to key
        s = {'key': []}
        p.toStore(s, 1)
        p.toStore(s, 2)
        self.assertEqual(s['key'], [1, 2])

        # callback
        def doubleToStore(key):
            def toStore(store, item):
                store[key] = item * 2

            return toStore

        p = Prod('all', lambda t, v: True, toStore=doubleToStore('key'))
        s = {'key': []}
        p.toStore(s, 1)
        self.assertEqual(s['key'], 2)
示例#4
0
    def test_init(self):
        "Sequence.__init__()"
        p1 = Prod('p1', lambda t, v: t == 1)
        p2 = Prod('p2', lambda t, v: t == 2)
        seq = Sequence(p1, p2)

        self.assertEqual(1, seq._min)
        self.assertEqual(1, seq._max)
示例#5
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods  # rename!

        _operator = Choice(
            Prod(
                name='Operator */',
                match=lambda t, v: v in '*/',
                toSeq=lambda t, tokens: (t[0], t[1]),
            ),
            Sequence(
                PreDef.S(),
                Choice(
                    Sequence(
                        Prod(
                            name='Operator */',
                            match=lambda t, v: v in '*/',
                            toSeq=lambda t, tokens: (t[0], t[1]),
                        ),
                        PreDef.S(optional=True),
                    ),
                    Sequence(
                        Prod(
                            name='Operator +-',
                            match=lambda t, v: v in '+-',
                            toSeq=lambda t, tokens: (t[0], t[1]),
                        ),
                        PreDef.S(),
                    ),
                    PreDef.funcEnd(stop=True, mayEnd=True),
                ),
            ),
        )

        _operant = lambda: Choice(  # noqa:E731
            _DimensionProd(self), _CalcValueProd(self), _CSSVariableProd(self))

        prods = Sequence(
            Prod(
                name='CALC',
                match=lambda t, v: t == types.FUNCTION and normalize(v) ==
                'calc(',
            ),
            PreDef.S(optional=True),
            _operant(),
            Sequence(_operator, _operant(), minmax=lambda: (0, None)),
            PreDef.funcEnd(stop=True),
        )

        # store: name of variable
        ok, seq, store, unused = ProdParser().parse(cssText,
                                                    'CSSCalc',
                                                    prods,
                                                    checkS=True)
        self.wellformed = ok
        if ok:
            self._setSeq(seq)
示例#6
0
    def test_init(self):
        "Prod.__init__(...)"
        p = Prod('min', lambda t, v: t == 1 and v == 2)

        self.assertEqual(str(p), 'min')
        self.assertEqual(p.toStore, None)
        self.assertEqual(p.optional, False)

        p = Prod('optional', lambda t, v: True, optional=True)
        self.assertEqual(p.optional, True)
示例#7
0
 def test_reset(self):
     "Sequence.reset()"
     p1 = Prod('p1', lambda t, v: t == 1)
     p2 = Prod('p2', lambda t, v: t == 2)
     seq = Sequence(p1, p2)
     t1 = (1, 0, 0, 0)
     t2 = (2, 0, 0, 0)
     self.assertEqual(p1, seq.nextProd(t1))
     self.assertEqual(p2, seq.nextProd(t2))
     self.assertRaises(Exhausted, seq.nextProd, t1)
     seq.reset()
     self.assertEqual(p1, seq.nextProd(t1))
示例#8
0
    def test_reset(self):
        "Choice.reset()"
        p1 = Prod('p1', lambda t, v: t == 1)
        p2 = Prod('p2', lambda t, v: t == 2)
        t1 = (1, 0, 0, 0)
        t2 = (2, 0, 0, 0)

        ch = Choice(p1, p2)
        self.assertEqual(p1, ch.nextProd(t1))
        self.assertRaises(Exhausted, ch.nextProd, t1)
        ch.reset()
        self.assertEqual(p2, ch.nextProd(t2))
示例#9
0
    def _setCssText(self, cssText):
        self._checkReadonly()
        types = self._prods  # rename!
        valueProd = Prod(
            name='value',
            match=lambda t, v: t in (types.NUMBER, types.PERCENTAGE),
            toSeq=lambda t, v: (CSSPrimitiveValue, CSSPrimitiveValue(v)),
            toStore='parts',
        )
        # COLOR PRODUCTION
        funccolor = Sequence(
            Prod(
                name='FUNC',
                match=lambda t, v: t == types.FUNCTION and cssutils.helper.
                normalize(v) in ('rgb(', 'rgba(', 'hsl(', 'hsla('),
                toSeq=lambda t, v: (t, v),  # cssutils.helper.normalize(v)),
                toStore='colorType',
            ),
            PreDef.unary(),
            valueProd,
            # 2 or 3 more values starting with Comma
            Sequence(PreDef.comma(),
                     PreDef.unary(),
                     valueProd,
                     minmax=lambda: (2, 3)),
            PreDef.funcEnd(),
        )
        colorprods = Choice(
            funccolor,
            PreDef.hexcolor('colorType'),
            Prod(
                name='named color',
                match=lambda t, v: t == types.IDENT,
                toStore='colorType',
            ),
        )
        # store: colorType, parts
        wellformed, seq, store, unusedtokens = ProdParser().parse(
            cssText, 'RGBColor', colorprods, keepS=True, store={'parts': []})

        if wellformed:
            self.wellformed = True
            if store['colorType'].type == self._prods.HASH:
                self._colorType = 'HEX'
            elif store['colorType'].type == self._prods.IDENT:
                self._colorType = 'Named Color'
            else:
                self._colorType = store['colorType'].value[:-1]
                # self._colorType = \
                # cssutils.helper.normalize(store['colorType'].value)[:-1]

            self._setSeq(seq)
示例#10
0
    def _productiondefinition(self):
        """Return definition used for parsing."""
        types = self._prods  # rename!

        value = Sequence(
            PreDef.unary(),
            Prod(
                name='PrimitiveValue',
                match=lambda t, v: t in (
                    types.DIMENSION,
                    types.HASH,
                    types.IDENT,
                    types.NUMBER,
                    types.PERCENTAGE,
                    types.STRING,
                ),
                toSeq=lambda t, tokens: (t[0], CSSPrimitiveValue(t[1])),
            ),
        )
        valueOrFunc = Choice(
            value,
            # FUNC is actually not in spec but used in e.g. Prince
            PreDef.function(toSeq=lambda t, tokens: (
                'FUNCTION',
                CSSFunction(cssutils.helper.pushtoken(t, tokens)),
            )),
        )
        funcProds = Sequence(
            Prod(
                name='FUNC',
                match=lambda t, v: t == types.FUNCTION,
                toSeq=lambda t, tokens:
                (t[0], cssutils.helper.normalize(t[1])),
            ),
            Choice(
                Sequence(
                    valueOrFunc,
                    # more values starting with Comma
                    # should use store where colorType is saved to
                    # define min and may, closure?
                    Sequence(PreDef.comma(),
                             valueOrFunc,
                             minmax=lambda: (0, None)),
                    PreDef.funcEnd(stop=True),
                ),
                PreDef.funcEnd(stop=True),
            ),
        )
        return funcProds
示例#11
0
 def test_matches(self):
     "Prod.matches(token)"
     p1 = Prod('p1', lambda t, v: t == 1 and v == 2)
     p2 = Prod('p2', lambda t, v: t == 1 and v == 2, optional=True)
     self.assertEqual(p1.matches([1, 2, 0, 0]), True)
     self.assertEqual(p2.matches([1, 2, 0, 0]), True)
     self.assertEqual(p1.matches([0, 0, 0, 0]), False)
     self.assertEqual(p2.matches([0, 0, 0, 0]), False)
示例#12
0
    def _productions(self):
        """Return definition used for parsing."""
        types = self._prods  # rename!

        itemProd = Choice(
            _ColorProd(self),
            _DimensionProd(self),
            _URIProd(self),
            _ValueProd(self),
            _CalcValueProd(self),
            _CSSVariableProd(self),
            _CSSFunctionProd(self),
        )
        funcProds = Sequence(
            Prod(
                name='FUNCTION',
                match=lambda t, v: t == types.FUNCTION,
                toSeq=lambda t, tokens: (t[0], normalize(t[1])),
            ),
            Choice(
                Sequence(
                    itemProd,
                    Sequence(PreDef.comma(optional=True),
                             itemProd,
                             minmax=lambda: (0, None)),
                    PreDef.funcEnd(stop=True),
                ),
                PreDef.funcEnd(stop=True),
            ),
        )
        return funcProds
示例#13
0
def _MSValueProd(parent, nextSor=False):
    return Prod(
        name=MSValue._functionName,
        match=lambda t, v: (  # t == self._prods.FUNCTION and (
            normalize(v) in (
                'expression(',
                'alpha(',
                'blur(',
                'chroma(',
                'dropshadow(',
                'fliph(',
                'flipv(',
                'glow(',
                'gray(',
                'invert(',
                'mask(',
                'shadow(',
                'wave(',
                'xray(',
            ) or v.startswith('progid:DXImageTransform.Microsoft.')),
        nextSor=nextSor,
        toSeq=lambda t, tokens: (
            MSValue._functionName,
            MSValue(pushtoken(t, tokens), parent=parent),
        ),
    )
示例#14
0
    def test_matches(self):
        "Choice.matches()"
        p1 = Prod('p1', lambda t, v: t == 1)
        p2 = Prod('p2', lambda t, v: t == 2, optional=True)

        t1 = (1, 0, 0, 0)
        t2 = (2, 0, 0, 0)
        t3 = (3, 0, 0, 0)

        c = Choice(p1, p2)
        self.assertEqual(True, c.matches(t1))
        self.assertEqual(True, c.matches(t2))
        self.assertEqual(False, c.matches(t3))

        c = Choice(Sequence(p1), Sequence(p2))
        self.assertEqual(True, c.matches(t1))
        self.assertEqual(True, c.matches(t2))
        self.assertEqual(False, c.matches(t3))
示例#15
0
def _ValueProd(parent, nextSor=False, toStore=None):
    return Prod(
        name='Value',
        match=lambda t, v: t in ('IDENT', 'STRING', 'UNICODE-RANGE'),
        nextSor=nextSor,
        toStore=toStore,
        toSeq=lambda t, tokens:
        ('Value', Value(pushtoken(t, tokens), parent=parent)),
    )
示例#16
0
    def test_initminmax(self):
        "Sequence.__init__(...minmax=...)"
        p1 = Prod('p1', lambda t, v: t == 1)
        p2 = Prod('p2', lambda t, v: t == 2)

        s = Sequence(p1, p2, minmax=lambda: (2, 3))
        self.assertEqual(2, s._min)
        self.assertEqual(3, s._max)

        s = Sequence(p1, p2, minmax=lambda: (0, None))
        self.assertEqual(0, s._min)

        try:
            # py2.6/3
            m = sys.maxsize
        except AttributeError:
            # py<1.6
            m = sys.maxsize
        self.assertEqual(m, s._max)
示例#17
0
    def test_optional(self):
        "Sequence.optional"
        p1 = Prod('p1', lambda t, v: t == 1)

        s = Sequence(p1, minmax=lambda: (1, 3))
        self.assertEqual(False, s.optional)
        s = Sequence(p1, minmax=lambda: (0, 3))
        self.assertEqual(True, s.optional)
        s = Sequence(p1, minmax=lambda: (0, None))
        self.assertEqual(True, s.optional)
示例#18
0
def _URIProd(parent, nextSor=False, toStore=None):
    return Prod(
        name='URIValue',
        match=lambda t, v: t == 'URI',
        toStore=toStore,
        nextSor=nextSor,
        toSeq=lambda t, tokens: (
            'URIValue',
            URIValue(pushtoken(t, tokens), parent=parent),
        ),
    )
示例#19
0
def _DimensionProd(parent, nextSor=False, toStore=None):
    return Prod(
        name='Dimension',
        match=lambda t, v: t in ('DIMENSION', 'NUMBER', 'PERCENTAGE'),
        nextSor=nextSor,
        toStore=toStore,
        toSeq=lambda t, tokens: (
            'DIMENSION',
            DimensionValue(pushtoken(t, tokens), parent=parent),
        ),
    )
示例#20
0
    def _productions(self):
        """Return definition used for parsing."""
        types = self._prods  # rename!

        func = Prod(
            name='MSValue-Sub',
            match=lambda t, v: t == self._prods.FUNCTION,
            toSeq=lambda t, tokens: (
                MSValue._functionName,
                MSValue(pushtoken(t, tokens), parent=self),
            ),
        )

        funcProds = Sequence(
            Prod(
                name='FUNCTION',
                match=lambda t, v: t == types.FUNCTION,
                toSeq=lambda t, tokens: (t[0], t[1]),
            ),
            Sequence(
                Choice(
                    _ColorProd(self),
                    _DimensionProd(self),
                    _URIProd(self),
                    _ValueProd(self),
                    _MSValueProd(self),
                    # _CalcValueProd(self),
                    _CSSVariableProd(self),
                    func,
                    # _CSSFunctionProd(self),
                    Prod(
                        name='MSValuePart',
                        match=lambda t, v: v != ')',
                        toSeq=lambda t, tokens: (t[0], t[1]),
                    ),
                ),
                minmax=lambda: (0, None),
            ),
            PreDef.funcEnd(stop=True),
        )
        return funcProds
示例#21
0
def _CalcValueProd(parent, nextSor=False, toStore=None):
    return Prod(
        name=CSSCalc._functionName,
        match=lambda t, v: t == PreDef.types.FUNCTION and normalize(v) ==
        'calc(',
        toStore=toStore,
        toSeq=lambda t, tokens: (
            CSSCalc._functionName,
            CSSCalc(pushtoken(t, tokens), parent=parent),
        ),
        nextSor=nextSor,
    )
示例#22
0
def _ColorProd(parent, nextSor=False, toStore=None):
    return Prod(
        name='ColorValue',
        match=lambda t, v: (t == 'HASH' and reHexcolor.match(v)) or
        (t == 'FUNCTION' and normalize(v) in
         ('rgb(', 'rgba(', 'hsl(', 'hsla(')) or
        (t == 'IDENT' and normalize(v) in list(ColorValue.COLORS.keys())),
        nextSor=nextSor,
        toStore=toStore,
        toSeq=lambda t, tokens: (
            'ColorValue',
            ColorValue(pushtoken(t, tokens), parent=parent),
        ),
    )
示例#23
0
    def test_nested(self):
        "Choice with nested Sequence"
        p1 = Prod('p1', lambda t, v: t == 1)
        p2 = Prod('p2', lambda t, v: t == 2)
        s1 = Sequence(p1, p1)
        s2 = Sequence(p2, p2)
        t0 = (0, 0, 0, 0)
        t1 = (1, 0, 0, 0)
        t2 = (2, 0, 0, 0)

        ch = Choice(s1, s2)
        self.assertRaisesMsg(
            ParseError,
            'No match for (0, 0, 0, 0) in Choice(Sequence(p1, p1), Sequence(p2, p2))',
            ch.nextProd,
            t0,
        )
        self.assertEqual(s1, ch.nextProd(t1))
        self.assertRaisesMsg(Exhausted, 'Extra token', ch.nextProd, t1)

        ch = Choice(s1, s2)
        self.assertEqual(s2, ch.nextProd(t2))
        self.assertRaisesMsg(Exhausted, 'Extra token', ch.nextProd, t1)
示例#24
0
    def test_initToSeq(self):
        "Prod.__init__(...toSeq=...)"
        # simply saves
        p = Prod('all', lambda t, tokens: True, toSeq=None)
        self.assertEqual(p.toSeq([1, 2], None), (1, 2))  # simply saves
        self.assertEqual(p.toSeq(['s1', 's2'], None),
                         ('s1', 's2'))  # simply saves

        # saves callback(val)
        p = Prod('all',
                 lambda t, v: True,
                 toSeq=lambda t, tokens: (1 == t[0], 3 == t[1]))
        self.assertEqual(p.toSeq([1, 3], None), (True, True))
        self.assertEqual(p.toSeq([2, 4], None), (False, False))
示例#25
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods  # rename!

        funcProds = Sequence(
            Prod(name='var', match=lambda t, v: t == types.FUNCTION),
            PreDef.ident(toStore='ident'),
            PreDef.funcEnd(stop=True),
        )

        # store: name of variable
        store = {'ident': None}
        wellformed, seq, store, unusedtokens = ProdParser().parse(
            cssText, 'CSSVariable', funcProds, keepS=True)
        if wellformed:
            self._name = store['ident'].value
            self._setSeq(seq)
            self.wellformed = True
示例#26
0
    def _setCssText(self, cssText):
        self._checkReadonly()

        types = self._prods  # rename!
        prods = Sequence(
            Prod(
                name='var',
                match=lambda t, v: t == types.FUNCTION and normalize(v) ==
                'var(',
            ),
            PreDef.ident(toStore='ident'),
            Sequence(
                PreDef.comma(),
                Choice(
                    _ColorProd(self, toStore='fallback'),
                    _DimensionProd(self, toStore='fallback'),
                    _URIProd(self, toStore='fallback'),
                    _ValueProd(self, toStore='fallback'),
                    _CalcValueProd(self, toStore='fallback'),
                    _CSSVariableProd(self, toStore='fallback'),
                    _CSSFunctionProd(self, toStore='fallback'),
                ),
                minmax=lambda: (0, 1),
            ),
            PreDef.funcEnd(stop=True),
        )

        # store: name of variable
        store = {'ident': None, 'fallback': None}
        ok, seq, store, unused = ProdParser().parse(cssText, 'CSSVariable',
                                                    prods)
        self.wellformed = ok

        if ok:
            self._name = store['ident'].value
            try:
                self._fallback = store['fallback'].value
            except KeyError:
                self._fallback = None

            self._setSeq(seq)
示例#27
0
 def test_initMatch(self):
     "Prod.__init__(...match=...)"
     p = Prod('min', lambda t, v: t == 1 and v == 2)
     self.assertEqual(p.match(1, 2), True)
     self.assertEqual(p.match(2, 2), False)
     self.assertEqual(p.match(1, 1), False)
示例#28
0
    def _setCssText(self, cssText):  # noqa: C901
        self._checkReadonly()
        types = self._prods  # rename!

        component = Choice(
            PreDef.unary(toSeq=lambda t, tokens: (
                t[0],
                DimensionValue(pushtoken(t, tokens), parent=self),
            )),
            PreDef.number(toSeq=lambda t, tokens: (
                t[0],
                DimensionValue(pushtoken(t, tokens), parent=self),
            )),
            PreDef.percentage(toSeq=lambda t, tokens: (
                t[0],
                DimensionValue(pushtoken(t, tokens), parent=self),
            )),
        )
        noalp = Sequence(
            Prod(
                name='FUNCTION',
                match=lambda t, v: t == types.FUNCTION and v in
                ('rgb(', 'hsl('),
                toSeq=lambda t, tokens: (t[0], normalize(t[1])),
            ),
            component,
            Sequence(PreDef.comma(optional=True),
                     component,
                     minmax=lambda: (2, 2)),
            PreDef.funcEnd(stop=True),
        )
        witha = Sequence(
            Prod(
                name='FUNCTION',
                match=lambda t, v: t == types.FUNCTION and v in
                ('rgba(', 'hsla('),
                toSeq=lambda t, tokens: (t[0], normalize(t[1])),
            ),
            component,
            Sequence(PreDef.comma(optional=True),
                     component,
                     minmax=lambda: (3, 3)),
            PreDef.funcEnd(stop=True),
        )
        namedcolor = Prod(
            name='Named Color',
            match=lambda t, v: t == 'IDENT' and
            (normalize(v) in list(self.COLORS.keys())),
            stop=True,
        )

        prods = Choice(PreDef.hexcolor(stop=True), namedcolor, noalp, witha)

        ok, seq, store, unused = ProdParser().parse(cssText, self.type, prods)
        self.wellformed = ok
        if ok:
            t, v = seq[0].type, seq[0].value
            if 'IDENT' == t:
                rgba = self.COLORS[normalize(v)]
            if 'HASH' == t:
                if len(v) == 4:
                    # HASH #rgb
                    rgba = (
                        int(2 * v[1], 16),
                        int(2 * v[2], 16),
                        int(2 * v[3], 16),
                        1.0,
                    )
                else:
                    # HASH #rrggbb
                    rgba = (int(v[1:3], 16), int(v[3:5], 16), int(v[5:7],
                                                                  16), 1.0)

            elif 'FUNCTION' == t:
                functiontype, raw, check = None, [], ''
                HSL = False

                for item in seq:
                    try:
                        type_ = item.value.type
                    except AttributeError:
                        # type of function, e.g. rgb(
                        if item.type == 'FUNCTION':
                            functiontype = item.value
                            HSL = functiontype in ('hsl(', 'hsla(')
                        continue

                    # save components
                    if type_ == Value.NUMBER:
                        raw.append(item.value.value)
                        check += 'N'
                    elif type_ == Value.PERCENTAGE:
                        if HSL:
                            # save as percentage fraction
                            raw.append(item.value.value / 100.0)
                        else:
                            # save as real value of percentage of 255
                            raw.append(int(255 * item.value.value / 100))
                        check += 'P'

                if HSL:
                    # convert to rgb
                    # h is 360 based (circle)
                    h, s, l_ = raw[0] / 360.0, raw[1], raw[2]
                    # ORDER h l s !!!
                    r, g, b = colorsys.hls_to_rgb(h, l_, s)
                    # back to 255 based
                    rgba = [
                        int(round(r * 255)),
                        int(round(g * 255)),
                        int(round(b * 255)),
                    ]

                    if len(raw) > 3:
                        rgba.append(raw[3])

                else:
                    # rgb, rgba
                    rgba = raw

                if len(rgba) < 4:
                    rgba.append(1.0)

                # validate
                checks = {
                    'rgb(': ('NNN', 'PPP'),
                    'rgba(': ('NNNN', 'PPPN'),
                    'hsl(': ('NPP', ),
                    'hsla(': ('NPPN', ),
                }
                if check not in checks[functiontype]:
                    self._log.error('ColorValue has invalid %s) parameters: '
                                    '%s (N=Number, P=Percentage)' %
                                    (functiontype, check))

            self._colorType = t
            self._red, self._green, self._blue, self._alpha = tuple(rgba)
            self._setSeq(seq)
示例#29
0
    def test_nextProd(self):
        "Sequence.nextProd()"
        p1 = Prod('p1', lambda t, v: t == 1, optional=True)
        p2 = Prod('p2', lambda t, v: t == 2)
        t1 = (1, 0, 0, 0)
        t2 = (2, 0, 0, 0)

        tests = {
            # seq: list of list of (token, prod or error msg)
            (
                p1, ): (
                [(t1, p1)],
                [(t2, 'Extra token')],  # as p1 optional
                [(t1, p1), (t1, 'Extra token')],
                [(t1, p1), (t2, 'Extra token')],
            ),
            (p2, ): (
                [(t2, p2)],
                [(t2, p2), (t2, 'Extra token')],
                [(t2, p2), (t1, 'Extra token')],
                [(t1, 'Missing token for production p2')],
            ),
            (p1, p2): (
                [(t1, p1), (t2, p2)],
                [(t1, p1), (t1, 'Missing token for production p2')],
            ),
        }
        for seqitems, results in list(tests.items()):
            for result in results:
                seq = Sequence(*seqitems)
                for t, p in result:
                    if isinstance(p, str):
                        self.assertRaisesMsg(ParseError, p, seq.nextProd, t)
                    else:
                        self.assertEqual(p, seq.nextProd(t))

        tests = {
            # seq: list of list of (token, prod or error msg)
            # as p1 optional!
            (p1, p1): (
                [(t1, p1)],
                [(t1, p1), (t1, p1)],
                [(t1, p1), (t1, p1)],
                [(t1, p1), (t1, p1), (t1, p1)],
                [(t1, p1), (t1, p1), (t1, p1), (t1, p1)],
                [(t1, p1), (t1, p1), (t1, p1), (t1, p1), (t1, 'Extra token')],
            ),
            (p1, ): (
                [(t1, p1)],
                [(t2, 'Extra token')],
                [(t1, p1), (t1, p1)],
                [(t1, p1), (t2, 'Extra token')],
                [(t1, p1), (t1, p1), (t1, 'Extra token')],
                [(t1, p1), (t1, p1), (t2, 'Extra token')],
            ),
            # as p2 NOT optional
            (
                p2, ): (
                [(t2, p2)],
                [(t1, 'Missing token for production p2')],
                [(t2, p2), (t2, p2)],
                [(t2, p2), (t1, 'No match for (1, 0, 0, 0) in Sequence(p2)')],
                [(t2, p2), (t2, p2), (t2, 'Extra token')],
                [(t2, p2), (t2, p2), (t1, 'Extra token')],
            ),
            (p1, p2): (
                [(t1, p1), (t1, 'Missing token for production p2')],
                [(t2, p2), (t2, p2)],
                [(t2, p2), (t1, p1), (t2, p2)],
                [(t1, p1), (t2, p2), (t2, p2)],
                [(t1, p1), (t2, p2), (t1, p1), (t2, p2)],
                [(t2, p2), (t2, p2), (t2, 'Extra token')],
                [(t2, p2), (t1, p1), (t2, p2), (t1, 'Extra token')],
                [(t2, p2), (t1, p1), (t2, p2), (t2, 'Extra token')],
                [(t1, p1), (t2, p2), (t2, p2), (t1, 'Extra token')],
                [(t1, p1), (t2, p2), (t2, p2), (t2, 'Extra token')],
                [(t1, p1), (t2, p2), (t1, p1), (t2, p2), (t1, 'Extra token')],
                [(t1, p1), (t2, p2), (t1, p1), (t2, p2), (t2, 'Extra token')],
            ),
        }
        for seqitems, results in list(tests.items()):
            for result in results:
                seq = Sequence(minmax=lambda: (1, 2), *seqitems)
                for t, p in result:
                    if isinstance(p, str):
                        self.assertRaisesMsg(ParseError, p, seq.nextProd, t)
                    else:
                        self.assertEqual(p, seq.nextProd(t))
示例#30
0
    def test_combi(self):
        "ProdParser.parse() 2"
        p1 = Prod('p1', lambda t, v: v == '1')
        p2 = Prod('p2', lambda t, v: v == '2')
        p3 = Prod('p3', lambda t, v: v == '3')

        tests = {
            '1 2': True,
            '1 2 1 2': True,
            '3': True,
            # '': 'No match in Choice(Sequence(p1, p2), p3)',
            '1': 'Missing token for production p2',
            '1 2 1': 'Missing token for production p2',
            '1 2 1 2 x': "No match: ('IDENT', 'x', 1, 9)",
            '1 2 1 2 1': "No match: ('NUMBER', '1', 1, 9)",
            '3 x': "No match: ('IDENT', 'x', 1, 3)",
            '3 3': "No match: ('NUMBER', '3', 1, 3)",
        }
        for text, exp in list(tests.items()):
            prods = Choice(Sequence(p1, p2, minmax=lambda: (1, 2)), p3)
            if exp is True:
                wellformed, seq, store, unused = ProdParser().parse(
                    text, 'T', prods)
                self.assertEqual(wellformed, exp)
            else:
                self.assertRaisesMsg(
                    xml.dom.SyntaxErr,
                    'T: %s' % exp,
                    ProdParser().parse,
                    text,
                    'T',
                    prods,
                )

        tests = {
            '1 3':
            True,
            '1 1 3':
            True,
            '2 3':
            True,
            '1':
            'Missing token for production p3',
            '1 1':
            'Missing token for production p3',
            '1 3 3':
            "No match: ('NUMBER', '3', 1, 5)",
            '1 1 3 3':
            "No match: ('NUMBER', '3', 1, 7)",
            '2 3 3':
            "No match: ('NUMBER', '3', 1, 5)",
            '2':
            'Missing token for production p3',
            '3':
            "Missing token for production Choice(Sequence(p1), p2): "
            "('NUMBER', '3', 1, 1)",
        }
        for text, exp in list(tests.items()):
            prods = Sequence(Choice(Sequence(p1, minmax=lambda: (1, 2)), p2),
                             p3)
            if exp is True:
                wellformed, seq, store, unused = ProdParser().parse(
                    text, 'T', prods)
                self.assertEqual(wellformed, exp)
            else:
                self.assertRaisesMsg(
                    xml.dom.SyntaxErr,
                    'T: %s' % exp,
                    ProdParser().parse,
                    text,
                    'T',
                    prods,
                )