def test_grammar_optional(self): grammar = Grammar(Sequence(Optional('WORD'), Optional('WORD'), Optional('NUMBER'))) datas = [ ( [], [[], [], []] ), ( [('WORD', 'a')], [['a'], [], []] ), ( [('NUMBER', 'c')], [[], [], ['c']] ), ( [('WORD', 'a'), ('NUMBER', 'c')], [['a'], [], ['c']] ), ( [('WORD', 'a'), ('WORD', 'b'), ('NUMBER', 'c')], [['a'], ['b'], ['c']] ) ] 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): return Sequence( 'WORD', Optional('WORD'), 'ESCAPED_STRING', 'WORD', Optional(choice(DelimitedList('ESCAPED_STRING'), ZeroOrMore('NUMBER'))), '.')
def test_grammar_delimited_list_mismatch(self): grammar = Grammar(Sequence(DelimitedList('WORD'), Optional('.'))) datas = [([('WORD', 'foo', 1), (',', ',', 2)], 2), ([('WORD', 'foo', 1), (',', ',', 2), ('WORD', 'foo', 3), (',', ',', 4), ('.', '.', 5)], 4)] self.parse_and_assert_mismatch(grammar, datas)
def test_grammar_delimited_list(self): grammar = Grammar(Sequence(DelimitedList('WORD'), Optional('.'))) datas = [([('WORD', 'foo')], [['foo'], []]), ([('WORD', 'foo'), (',', ','), ('WORD', 'bar')], [['foo', 'bar'], []]), ([('WORD', 'foo'), (',', ','), ('WORD', 'bar'), ('.', '.')], [['foo', 'bar'], ['.']])] self.parse_and_assert_tree(grammar, datas)
def test_grammar_tag(self): grammar = Grammar( Tag( 'a', Tag('b', choice(Tag('c', 'WORD'), Tag('d', Optional('NUMBER')))))) datas = [([('WORD', 'bar')], ('a', ('b', ('c', 'bar')))), ([('NUMBER', '1')], ('a', ('b', ('d', ['1'])))), ([], ('a', ('b', ('d', []))))] self.parse_and_assert_tree(grammar, datas)
def test_grammar_choice_dict_init(self): datas = [(('WORD', 'WORD'), "First token kind must be unique, but WORD isn't."), (('WORD', Sequence('WORD')), "First token kind must be unique, but WORD isn't."), ((Sequence(Sequence(Optional('WORD'))), ), "Unsupported pattern type <class 'textparser.Optional'>.")] for grammar, message in datas: with self.assertRaises(textparser.Error) as cm: ChoiceDict(*grammar) self.assertEqual(str(cm.exception), message)
def grammar(self): version = Sequence('VERSION', 'STRING') ns = Sequence('NS_', ':', AnyUntil(Sequence(Any(), ':'))) bs = Sequence('BS_', ':') nodes = Sequence('BU_', ':', ZeroOrMore('WORD')) signal = Sequence('SG_', choice(Sequence('WORD', 'WORD'), Sequence('WORD')), ':', 'NUMBER', '|', 'NUMBER', '@', 'NUMBER', '+/-', '(', 'NUMBER', ',', 'NUMBER', ')', '[', 'NUMBER', '|', 'NUMBER', ']', 'STRING', DelimitedList('WORD')) message = Sequence('BO_', 'NUMBER', 'WORD', ':', 'NUMBER', 'WORD', ZeroOrMore(signal)) environment_variable = Sequence('EV_', 'WORD', ':', 'NUMBER', '[', 'NUMBER', '|', 'NUMBER', ']', 'STRING', 'NUMBER', 'NUMBER', 'WORD', 'WORD', ';') comment = Sequence( 'CM_', choice(Sequence('SG_', 'NUMBER', 'WORD', 'STRING'), Sequence('BO_', 'NUMBER', 'STRING'), Sequence('EV_', 'WORD', 'STRING'), Sequence('BU_', 'WORD', 'STRING'), 'STRING'), ';') attribute_definition = Sequence( 'BA_DEF_', Optional(choice('SG_', 'BO_', 'EV_', 'BU_')), 'STRING', 'WORD', Optional(choice(DelimitedList('STRING'), ZeroOrMore('NUMBER'))), ';') attribute_definition_default = Sequence('BA_DEF_DEF_', 'STRING', choice('NUMBER', 'STRING'), ';') attribute = Sequence( 'BA_', 'STRING', ZeroOrMore( choice(Sequence('BO_', 'NUMBER'), Sequence('SG_', 'NUMBER', 'WORD'), Sequence('BU_', 'WORD'), Sequence('EV_', 'WORD'))), choice('NUMBER', 'STRING'), ';') attribute_definition_rel = Sequence( 'BA_DEF_REL_', Optional('BU_SG_REL_'), 'STRING', 'WORD', Optional(choice(DelimitedList('STRING'), OneOrMore('NUMBER'))), ';') attribute_definition_default_rel = Sequence('BA_DEF_DEF_REL_', 'STRING', choice('NUMBER', 'STRING'), ';') attribute_rel = Sequence('BA_REL_', 'STRING', 'BU_SG_REL_', 'WORD', 'SG_', 'NUMBER', 'WORD', choice('NUMBER', 'STRING'), ';') choice_ = Sequence('VAL_', Optional('NUMBER'), 'WORD', ZeroOrMore(Sequence('NUMBER', 'STRING')), ';') value_table = Sequence('VAL_TABLE_', 'WORD', ZeroOrMore(Sequence('NUMBER', 'STRING')), ';') signal_type = Sequence('SIG_VALTYPE_', 'NUMBER', 'WORD', ':', 'NUMBER', ';') signal_multiplexer_values = Sequence( 'SG_MUL_VAL_', 'NUMBER', 'WORD', 'WORD', DelimitedList(Sequence('NUMBER', 'NUMBER')), ';') message_add_sender = Sequence('BO_TX_BU_', 'NUMBER', ':', DelimitedList('WORD'), ';') signal_group = Sequence('SIG_GROUP_', 'NUMBER', 'WORD', 'NUMBER', ':', Optional(OneOrMore('WORD')), ';') return OneOrMoreDict( choice(message, comment, attribute_definition, value_table, choice_, attribute, attribute_rel, attribute_definition_rel, attribute_definition_default, attribute_definition_default_rel, signal_group, signal_type, signal_multiplexer_values, message_add_sender, environment_variable, nodes, ns, bs, version))
def grammar(self): word = choice('WORD', *list(self.KEYWORDS)) version = Sequence('FormatVersion', '=', 'NUMBER', 'COMMENT') title = Sequence('Title', '=', 'STRING') unique_variables = Sequence('UniqueVariables', '=', word) float_decimal_places = Sequence('FloatDecimalPlaces', '=', 'NUMBER') bit_rate_switch = Sequence('BRS', '=', word) enum_value = Sequence('NUMBER', '=', 'STRING') enum = Sequence('Enum', '=', word, '(', Optional(DelimitedList(enum_value)), ')', Optional('COMMENT')) sig_unit = '/u:' sig_factor = Sequence('/f:', 'NUMBER') sig_offset = Sequence('/o:', 'NUMBER') sig_min = Sequence('/min:', 'NUMBER') sig_max = Sequence('/max:', 'NUMBER') sig_default = Sequence('/d:', choice('NUMBER', 'WORD')) sig_long_name = Sequence('/ln:', 'STRING') sig_enum = Sequence('/e:', word) sig_places = Sequence('/p:', 'NUMBER') signal = Sequence( 'Sig', '=', Any(), word, Optional('NUMBER'), Optional(choice('-h', '-b')), Optional('-m'), ZeroOrMore( choice(sig_unit, sig_factor, sig_offset, sig_min, sig_max, sig_default, sig_long_name, sig_enum, sig_places)), Optional('COMMENT')) variable = Sequence( 'Var', '=', Any(), word, 'NUMBER', ',', 'NUMBER', ZeroOrMore(choice('-v', '-m', '-s')), ZeroOrMore( choice(sig_unit, sig_factor, sig_offset, sig_min, sig_max, sig_default, sig_long_name, sig_enum, sig_places)), Optional('COMMENT')) symbol = Sequence( '[', Any(), ']', ZeroOrMoreDict( choice( Sequence('ID', '=', 'NUMBER', word, Optional(Sequence('NUMBER', word)), Optional('COMMENT')), Sequence('Len', '=', 'NUMBER'), Sequence('Mux', '=', Any(), 'NUMBER', ',', 'NUMBER', 'NUMBER', Optional('-t')), Sequence('CycleTime', '=', 'NUMBER'), Sequence('Timeout', '=', 'NUMBER'), Sequence('MinInterval', '=', 'NUMBER'), Sequence('Color', '=', 'NUMBER', 'WORD'), variable, Sequence('Sig', '=', Any(), 'NUMBER')))) enums = Sequence('{ENUMS}', ZeroOrMore(choice(enum, 'COMMENT'))) signals = Sequence('{SIGNALS}', ZeroOrMore(choice(signal, 'COMMENT'))) send = Sequence('{SEND}', ZeroOrMore(choice(symbol, 'COMMENT'))) receive = Sequence('{RECEIVE}', ZeroOrMore(choice(symbol, 'COMMENT'))) sendreceive = Sequence('{SENDRECEIVE}', ZeroOrMore(choice(symbol, 'COMMENT'))) section = choice(enums, signals, send, receive, sendreceive) grammar = Sequence( Optional('COMMENT'), version, ZeroOrMore( choice(unique_variables, float_decimal_places, title, bit_rate_switch)), ZeroOrMore(section)) return grammar
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): nls = OneOrMore('NL') any_until_keyword = AnyUntil(Sequence('NL', choice(*KEYWORDS))) any_until_nl = AnyUntil(choice('NL', '__EOF__')) sub_parameter = Tag('SubParameter', Sequence(nls, 'WORD', 'WS', 'WORD')) sub_parameter_typ_min_max = Tag( 'SubParameterTypMinMax', Sequence(nls, 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD')) numerical_sub_parameter = Tag( 'NumericalSubParameter', Sequence(nls, 'WORD', Optional('WS'), 'EQ', Optional('WS'), 'WORD')) ibis_ver = Sequence(Optional(nls), '__SOF__', Optional(nls), '[ibis ver]', 'WS', 'WORD') comment_char = Sequence('[comment char]') file_name = Sequence('[file name]', 'WS', 'WORD') file_rev = Sequence('[file rev]', 'WS', 'WORD') date = Sequence('[date]', any_until_nl) source = Sequence('[source]', any_until_keyword) notes = Sequence('[notes]', any_until_keyword) disclaimer = Sequence('[disclaimer]', any_until_keyword) copyright_ = Sequence('[copyright]', any_until_keyword) component = Sequence('[component]', any_until_nl, ZeroOrMore(Sequence(nls, 'WORD', 'WS', 'WORD'))) manufacturer = Sequence('[manufacturer]', any_until_nl) package = Sequence( '[package]', ZeroOrMore( Sequence(nls, 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD'))) pin = Sequence( '[pin]', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', ZeroOrMore( choice( Tag( 'All', Sequence(nls, Optional('WS'), 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD')), Tag( 'Triple', Sequence(nls, Optional('WS'), 'WORD', 'WS', 'WORD', 'WS', 'WORD'))))) diff_pin = Sequence( '[diff pin]', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', ZeroOrMore( Sequence(nls, 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD'))) series_switch_groups = Sequence( '[series switch groups]', ZeroOrMore(Sequence(nls, any_until_nl))) model_selector = Sequence( '[model selector]', 'WS', 'WORD', ZeroOrMore(Sequence(nls, 'WORD', any_until_nl))) model = Sequence( '[model]', 'WS', 'WORD', ZeroOrMore( choice( Tag( 'Quad', Sequence(nls, 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD')), sub_parameter, numerical_sub_parameter))) add_submodel = Sequence( '[add submodel]', ZeroOrMore(Sequence(nls, 'WORD', 'WS', 'WORD'))) temperature_range = Sequence('[temperature range]', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD') voltage_range = Sequence('[voltage range]', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD') pullup_reference = Sequence('[pullup reference]', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD') pulldown_reference = Sequence('[pulldown reference]', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD') quad_table = ZeroOrMore( Sequence(nls, Optional('WS'), 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD')) gnd_clamp = Sequence('[gnd clamp]', quad_table) power_clamp = Sequence('[power clamp]', quad_table) pullup = Sequence('[pullup]', quad_table) pulldown = Sequence('[pulldown]', quad_table) ramp = Sequence( '[ramp]', ZeroOrMore( choice(numerical_sub_parameter, sub_parameter_typ_min_max))) waveform = ZeroOrMore( choice( Tag( 'TableEntry', Sequence(nls, Optional('WS'), 'WORD', 'WS', 'WORD', 'WS', 'WORD', 'WS', 'WORD')), numerical_sub_parameter)) falling_waveform = Sequence('[falling waveform]', waveform) rising_waveform = Sequence('[rising waveform]', waveform) submodel = Sequence('[submodel]', 'WS', 'WORD', OneOrMore(sub_parameter)) submodel_spec = Sequence('[submodel spec]', OneOrMore(sub_parameter_typ_min_max)) unknown_keyword = Sequence('KEYWORD', any_until_keyword) end = Sequence('[end]') ibis_file = Sequence( ibis_ver, ZeroOrMore( Sequence( nls, choice(comment_char, file_name, file_rev, date, source, notes, disclaimer, copyright_, component, manufacturer, package, pin, diff_pin, series_switch_groups, model_selector, model, add_submodel, temperature_range, voltage_range, pullup_reference, pulldown_reference, gnd_clamp, power_clamp, pullup, pulldown, ramp, falling_waveform, rising_waveform, submodel, submodel_spec, unknown_keyword, end)))) return ibis_file
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
def grammar(self): version = Sequence('FormatVersion', '=', 'NUMBER') title = Sequence('Title', '=', 'STRING') enum_value = Sequence('NUMBER', '=', 'STRING') enum = Sequence('Enum', '=', 'WORD', '(', DelimitedList(enum_value), ')') sig_unit = Sequence('/u:', 'WORD') sig_factor = Sequence('/f:', 'NUMBER') sig_offset = Sequence('/o:', 'NUMBER') sig_min = Sequence('/min:', 'NUMBER') sig_max = Sequence('/max:', 'NUMBER') sig_default = Sequence('/d:', 'NUMBER') sig_long_name = Sequence('/ln:', 'STRING') sig_enum = Sequence('/e:', 'WORD') signal = Sequence('Sig', '=', 'WORD', 'WORD', Optional('NUMBER'), Optional('-m'), Optional(sig_unit), Optional(sig_factor), Optional(sig_offset), Optional(sig_min), Optional(sig_max), Optional(sig_default), Optional(sig_long_name), Optional(sig_enum)) symbol = Sequence( '[', 'WORD', ']', Optional( Sequence('ID', '=', 'NUMBER', 'WORD', Optional(Sequence('NUMBER', 'WORD')))), Sequence('Len', '=', 'NUMBER'), Optional( Sequence('Mux', '=', 'WORD', 'NUMBER', ',', 'NUMBER', 'NUMBER')), Optional(Sequence('CycleTime', '=', 'NUMBER')), Optional(Sequence('Timeout', '=', 'NUMBER')), Optional(Sequence('MinInterval', '=', 'NUMBER')), ZeroOrMore(Sequence('Sig', '=', 'WORD', 'NUMBER'))) enums = Sequence('{ENUMS}', ZeroOrMore(enum)) signals = Sequence('{SIGNALS}', ZeroOrMore(signal)) send = Sequence('{SEND}', ZeroOrMore(symbol)) receive = Sequence('{RECEIVE}', ZeroOrMore(symbol)) sendreceive = Sequence('{SENDRECEIVE}', ZeroOrMore(symbol)) section = choice(enums, signals, send, receive, sendreceive) grammar = Sequence(version, title, OneOrMore(section)) return grammar