# -*- coding: utf-8 -*- 'Tests for issue #8: prevent definitions of non-halting parsers.' from funcparserlib.parser import (a, many, fwd, maybe, pure, oneplus, GrammarError, makes_progress, non_halting) from funcparserlib.contrib.common import const from nose.tools import ok_, assert_raises x = a('x') p1 = maybe(x) p3 = maybe(x) + x p4 = many(p3) p5 = x | many(x) p8 = x >> const(True) p9 = pure(True) def test_makes_progress(): ok_(not makes_progress(p1)) ok_(not makes_progress(p4)) ok_(not makes_progress(p5)) ok_(not makes_progress(p9)) ok_(makes_progress(p3)) ok_(makes_progress(p8)) def test_non_halting_many(): assert_raises(GrammarError, lambda: many(many(x)).parse('')) assert_raises(GrammarError, lambda: oneplus(many(x)).parse('')) assert_raises(GrammarError, lambda: many(p1).parse(''))
def sub(m): if m.group('standard') is not None: return std[m.group('standard')] else: return unichr(int(m.group('unicode'), 16)) return re_esc.sub(sub, s) def make_string(n): return unescape(n[1:-1]) # JSON Grammar null = n('null') >> const(None) true = n('true') >> const(True) false = n('false') >> const(False) number = sometok('number') >> make_number string = sometok('string') >> make_string value = fwd() member = string + op_(':') + value >> tuple object = (op_('{') + maybe(member + many(op_(',') + member)) + op_('}') >> make_object) array = ( op_('[') + maybe(value + many(op_(',') + value)) + op_(']') >> make_array) value.define(null | true | false | object | array | number | string) json_text = object | array json_file = json_text + skip(eof) name_parser_vars(locals())
std = { '"': '"', '\\': '\\', '/': '/', 'b': '\b', 'f': '\f', 'n': '\n', 'r': '\r', 't': '\t', } def sub(m): if m.group('standard') is not None: return std[m.group('standard')] else: return unichr(int(m.group('unicode'), 16)) return re_esc.sub(sub, s) def make_string(n): return unescape(n[1:-1]) # JSON Grammar null = n('null') >> const(None) true = n('true') >> const(True) false = n('false') >> const(False) number = sometok('number') >> make_number string = sometok('string') >> make_string value = fwd() member = string + op_(':') + value >> tuple object = ( op_('{') + maybe(member + many(op_(',') + member)) + op_('}') >> make_object) array = ( op_('[') + maybe(value + many(op_(',') + value)) + op_(']')
except ZeroDivisionError: return None return ret res = reduce(F, args, z) return res eval = unarg(eval_expr) number = sometok('number') >> make_number name = sometok('name') >> make_name string = sometok('string') >> make_string func = sometok('func') >> make_func value = number | name | string makeop = lambda s, f: op(s) >> const(f) add = makeop('+', (ets.add, operator.add)) sub = makeop('-', (ets.sub, operator.sub)) mul = makeop('*', (ets.mul, operator.mul)) div = makeop('/', (ets.div, operator.div)) mul_op = mul | div add_op = add | sub args = fwd() factor = fwd() primary = value call = func + op_('(') + args + op_(')') >> exec_func term = factor + many(mul_op + factor ) >> eval expr = term + many(add_op + term ) >> eval
# -*- coding: utf-8 -*- 'Tests for issue #8: prevent definitions of non-halting parsers.' from funcparserlib.parser import ( a, many, fwd, maybe, pure, oneplus, GrammarError, makes_progress, non_halting) from funcparserlib.contrib.common import const from nose.tools import ok_, assert_raises x = a('x') p1 = maybe(x) p3 = maybe(x) + x p4 = many(p3) p5 = x | many(x) p8 = x >> const(True) p9 = pure(True) def test_makes_progress(): ok_(not makes_progress(p1)) ok_(not makes_progress(p4)) ok_(not makes_progress(p5)) ok_(not makes_progress(p9)) ok_(makes_progress(p3)) ok_(makes_progress(p8)) def test_non_halting_many(): assert_raises(GrammarError, lambda: many(many(x)).parse('')) assert_raises(GrammarError, lambda: oneplus(many(x)).parse('')) assert_raises(GrammarError, lambda: many(p1).parse('')) assert_raises(GrammarError, lambda: many(p5).parse(''))