def test_grammar_choice_dict(self): number = Forward() number <<= Sequence('NUMBER') grammar = Grammar(ChoiceDict(number, Tag('foo', Sequence('WORD')), ChoiceDict('BAR'), 'FIE')) datas = [ ( [('WORD', 'm')], ('foo', ['m']) ), ( [('NUMBER', '5')], ['5'] ), ( [('BAR', 'foo')], 'foo' ), ( [('FIE', 'fum')], 'fum' ) ] self.parse_and_assert_tree(grammar, datas)
def test_grammar_forward_text(self): foo = Forward() foo <<= 'FOO' grammar = Grammar(foo) datas = [([('FOO', 'foo')], 'foo')] self.parse_and_assert_tree(grammar, datas)
def test_grammar_forward(self): foo = Forward() foo <<= Sequence('FOO') grammar = Grammar(foo) datas = [([('FOO', 'foo')], ['foo'])] self.parse_and_assert_tree(grammar, datas)
def grammar(self): value = Forward() list_ = Sequence('[', Optional(DelimitedList(value)), ']') pair = Sequence('ESCAPED_STRING', ':', value) dict_ = Sequence('{', Optional(DelimitedList(pair)), '}') value <<= choice(list_, dict_, 'ESCAPED_STRING', 'NUMBER', 'TRUE', 'FALSE', 'NULL') return value
def grammar(self): ident = choice('IDENT', *self.KEYWORDS) full_ident = DelimitedList(ident, '.') empty_statement = ';' message_type = Sequence(Optional('.'), full_ident) constant = choice(Tag('bool', choice('true', 'false')), Tag('ident', full_ident), Tag('string', 'STRING'), Tag('integer', 'INT')) option_name = Sequence(choice(ident, Sequence('(', full_ident, ')')), ZeroOrMore(Sequence('.', ident))) options = Optional( Sequence('[', DelimitedList(Sequence(option_name, '=', constant)), ']')) # Import. import_ = Sequence('import', Optional(choice('weak', 'public')), 'STRING') # Package. package = Sequence('package', full_ident, ';') # Option. option = Sequence('option', option_name, '=', constant, ';') # Enum. enum_field = Sequence(ident, '=', 'INT', options, ';') enum = Sequence('enum', ident, '{', ZeroOrMore(choice(enum_field, empty_statement)), '}') # Oneof. oneof_field = Sequence(message_type, ident, '=', 'INT', ';') oneof = Sequence('oneof', ident, '{', ZeroOrMore(choice(oneof_field, empty_statement)), '}') # Map. map_field = Sequence('map', '<', ident, ',', message_type, '>', ident, '=', 'INT', options, ';') # Reserved. field_number_range = Sequence( 'INT', Optional(Sequence('to', choice('INT', 'max')))) reserved = Sequence( 'reserved', choice(DelimitedList(field_number_range), DelimitedList('STRING'))) # Message. field = Sequence(Optional('repeated'), message_type, ident, '=', 'INT', options, ';') message = Forward() message <<= Sequence( 'message', ident, '{', ZeroOrMore( choice(Tag('field', field), enum, message, oneof, map_field, reserved, empty_statement)), '}') # Service. rpc_name = ident rpc = Sequence('rpc', rpc_name, '(', Optional('stream'), message_type, ')', 'returns', '(', Optional('stream'), message_type, ')', choice(Sequence('{', ZeroOrMore(option), '}'), ';')) service = Sequence('service', ident, '{', ZeroOrMore(choice(option, rpc, empty_statement)), '}') # Proto3-file. top_level_def = choice(message, enum, service) syntax = Sequence('syntax', '=', 'PROTO3', ';') proto = Sequence( syntax, ZeroOrMoreDict( choice(import_, package, option, top_level_def, empty_statement))) return proto
def grammar(self): message = Forward() rpc = Forward() ident = choice(*(list(self.keywords()) + ['IDENT'])) full_ident = DelimitedList(ident, delim='.') # Constant. constant = choice(full_ident, Sequence(Optional(choice('-', '+')), 'INT'), Sequence(Optional(choice('-', '+')), 'FLOAT'), 'ESCAPED_STRING', 'true', 'false') # Syntax. syntax = Sequence('syntax', '=', 'ESCAPED_STRING', ';') # Import statement. import_ = Sequence('import', Optional(choice('weak', 'public')), 'ESCAPED_STRING', ';') # Package. package = Sequence('package', full_ident, ';') # Option. option_name = Sequence(choice(ident, Sequence('(', full_ident, ')')), ZeroOrMore(Sequence('.', ident))) option = Sequence('option', option_name, '=', constant, ';') # Fields. type_ = choice(Sequence(Optional('.'), DelimitedList(ident, '.')), ident) field_number = 'INT' # Normal field. field_option = Sequence(option_name, '=', constant) field_options = DelimitedList(field_option) field = Sequence(Optional('repeated'), type_, ident, '=', field_number, Optional(Sequence('[', field_options, ']')), ';') # Oneof and oneof field. oneof_field = Sequence(type_, ident, '=', field_number, Optional(Sequence('[', field_options, ']')), ';') oneof = Sequence('oneof', ident, '{', ZeroOrMore(choice(oneof_field, ';')), '}') # Map field. key_type = choice('int32', 'int64', 'uint32', 'uint64', 'sint32', 'sint64', 'fixed32', 'fixed64', 'sfixed32', 'sfixed64', 'bool', 'string') map_field = Sequence('map', '<', key_type, ',', type_, '>', ident, '=', field_number, Optional(Sequence('[', field_options, ']')), ';') # Reserved. field_names = DelimitedList(ident) ranges = Sequence(DelimitedList('INT'), Optional(Sequence('to', choice('INT', 'max')))) reserved = Sequence('reserved', choice(ranges, field_names), ';') # Enum definition. enum_value_option = Sequence(option_name, '=', constant) enum_field = Sequence( ident, '=', 'INT', Optional(Sequence('[', DelimitedList(enum_value_option), ']')), ';') enum_body = Sequence('{', ZeroOrMore(choice(option, enum_field, ';')), '}') enum = Sequence('enum', ident, enum_body) # Message definition. message_body = Sequence( '{', ZeroOrMore( choice(field, enum, message, option, oneof, map_field, reserved, ';')), '}') message <<= Sequence('message', ident, message_body) # Service definition. service = Sequence('service', ident, '{', ZeroOrMore(choice(option, rpc, ';')), '}') rpc <<= Sequence( 'rpc', ident, '(', Optional('stream'), ident, ')', 'returns', '(', Optional('stream'), ident, ')', choice(Sequence('{', ZeroOrMore(choice(option, ';')), '}'), ';')) # Proto file. proto = Sequence( syntax, ZeroOrMore( choice(import_, package, option, message, enum, service, ';'))) return proto