def build(self): ''' Construct the parser. ''' # Avoid dependency loops from lepl.matchers.derived import Drop, Eos, AnyBut, Upper from lepl.matchers.core import Any, Lookahead, Literal, Delayed from lepl.matchers.error import make_error from lepl.matchers.variables import TraceVariables from lepl.support.node import node_throw with TraceVariables(False): # these two definitions enforce the conditions above, providing only # special characters appear as literals in the grammar escaped = Drop(self.alphabet.escape) & self.alphabet.escaped raw = ~Lookahead(self.alphabet.escape) & \ AnyBut(self.alphabet.illegal) close = Drop(')') extend = (Drop('(*') & Upper()[1:,...] & close) >> self.extend single = escaped | raw | extend any_ = Literal('.') >> self.dot letter = single >> self.dup pair = single & Drop('-') & single > self.tup interval = pair | letter brackets = Drop('[') & interval[1:] & Drop(']') inverted = Drop('[^') & interval[1:] & Drop(']') >= self.invert char = inverted | brackets | letter | any_ | extend > self.char item = Delayed() open = Drop('(?:') range = Drop(self.alphabet.escape) & self.alphabet.range seq = (char | item | range)[0:] > self.sequence group = open & seq & close alts = open & seq[2:, Drop('|')] & close > self.choice star = (alts | group | char) & Drop('*') > self.star plus = (alts | group | char) & Drop('+') > self.plus opt = (alts | group | char) & Drop('?') > self.option bad_grp = (Drop('(') & ~Lookahead('?:') & seq & close) \ ** make_error( "Lepl's own regular expressions do not currently " "support matched groups.\n" "Use '(?:...)' to group expressions without " "matching.") item += alts | group | star | plus | opt | bad_grp expr = ((char | item)[:] & Drop(Eos())) >> node_throw # Empty config here avoids loops if the default config includes # references to alphabets expr.config.clear() return expr.parse_string
def build(self): ''' Construct the parser. ''' # Avoid dependency loops from lepl.matchers.derived import Drop, Eos, AnyBut, Upper from lepl.matchers.core import Any, Lookahead, Literal, Delayed from lepl.matchers.error import make_error from lepl.matchers.variables import TraceVariables from lepl.support.node import node_throw with TraceVariables(False): # these two definitions enforce the conditions above, providing only # special characters appear as literals in the grammar escaped = Drop(self.alphabet.escape) & self.alphabet.escaped raw = ~Lookahead(self.alphabet.escape) & \ AnyBut(self.alphabet.illegal) close = Drop(')') extend = (Drop('(*') & Upper()[1:, ...] & close) >> self.extend single = escaped | raw | extend any_ = Literal('.') >> self.dot letter = single >> self.dup pair = single & Drop('-') & single > self.tup interval = pair | letter brackets = Drop('[') & interval[1:] & Drop(']') inverted = Drop('[^') & interval[1:] & Drop(']') >= self.invert char = inverted | brackets | letter | any_ | extend > self.char item = Delayed() open = Drop('(?:') range = Drop(self.alphabet.escape) & self.alphabet.range seq = (char | item | range)[0:] > self.sequence group = open & seq & close alts = open & seq[2:, Drop('|')] & close > self.choice star = (alts | group | char) & Drop('*') > self.star plus = (alts | group | char) & Drop('+') > self.plus opt = (alts | group | char) & Drop('?') > self.option bad_grp = (Drop('(') & ~Lookahead('?:') & seq & close) \ ** make_error( "Lepl's own regular expressions do not currently " "support matched groups.\n" "Use '(?:...)' to group expressions without " "matching.") item += alts | group | star | plus | opt | bad_grp expr = ((char | item)[:] & Drop(Eos())) >> node_throw # Empty config here avoids loops if the default config includes # references to alphabets expr.config.clear() return expr.parse_string
def test_bad_format(self): ''' Test a message with bad formatting. ''' try: parser = (Literal('abc') > 'name')**make_error('msg {0}') parser.config.no_full_first_match() list(parser.match('abc')) assert False, 'expected error' except IndexError: pass
def test_formatted(self): ''' Test a message with formatting. ''' parser = (Literal('abc') > 'name')**make_error('msg {stream_in}') parser.config.no_full_first_match() node = parser.parse('abc')[0] assert isinstance(node, Error) assert node[0] == 'msg abc', node[0] assert str(node).startswith('msg abc ('), str(node) assert isinstance(node, Exception), type(node)
def test_bad_format(self): ''' Test a message with bad formatting. ''' try: parser = (Literal('abc') > 'name') ** make_error('msg {0}') parser.config.no_full_first_match() list(parser.match('abc')) assert False, 'expected error' except IndexError: pass
def test_formatted(self): ''' Test a message with formatting. ''' parser = (Literal('abc') > 'name') ** make_error('msg {stream_in}') parser.config.no_full_first_match() node = parser.parse('abc')[0] assert isinstance(node, Error) assert node[0] == 'msg abc', node[0] assert str(node).startswith('msg abc ('), str(node) assert isinstance(node, Exception), type(node)
def test_fmtted(self): ''' Test a message with fmtting. ''' parser = (Literal('abc') > 'name')**make_error('msg {in_rest}') parser.config.no_full_first_match() node = parser.parse('abc')[0] assert isinstance(node, Error) assert node[0] == "msg 'abc'", node[0] assert str(node).startswith("msg 'abc' ("), str(node) assert isinstance(node, Exception), type(node)
def test_fmtted(self): ''' Test a message with fmtting. ''' parser = (Literal('abc') > 'name') ** make_error('msg {in_rest}') parser.config.no_full_first_match() node = parser.parse('abc')[0] assert isinstance(node, Error) assert node[0] == "msg 'abc'", node[0] assert str(node).startswith("msg 'abc' ("), str(node) assert isinstance(node, Exception), type(node)
def test_list(self): ''' Code has an exception for handling lists. ''' #basicConfig(level=DEBUG) with TraceVariables(): parser = (Literal([1, 2, 3]) > 'name')**make_error('msg {in_str}') parser.config.no_full_first_match() node = parser.parse([1, 2, 3])[0] assert isinstance(node, Error) assert node[0] == 'msg 1', node[0] assert str(node).startswith('msg 1 ('), str(node) assert isinstance(node, Exception), type(node)
def test_list(self): ''' Code has an exception for handling lists. ''' #basicConfig(level=DEBUG) with TraceVariables(): parser = (Literal([1, 2, 3]) > 'name') ** make_error('msg {stream_in}') parser.config.no_full_first_match() node = parser.parse([1, 2, 3])[0] assert isinstance(node, Error) assert node[0] == 'msg [1, 2, 3]', node[0] assert str(node).startswith('msg [1, 2, 3] ('), str(node) assert isinstance(node, Exception), type(node)