import re
from copy import copy
-from pyparsing import Keyword, Literal, Word, OneOrMore, Combine, Regex, Forward, Optional, Group, Suppress, delimitedList, cStyleComment, nums, alphanums, empty, srange, dblQuotedString
+from pyparsing import Keyword, Literal, Word, OneOrMore, ZeroOrMore, Combine, Regex, Forward, Optional, Group, Suppress, delimitedList, cStyleComment, nums, alphanums, empty, srange, dblQuotedString
__all__ = ['parse_asn1', 'AnnotatedToken']
-def parse_asn1(asn1_payload):
- """ Parse a string containing an ASN.1 module definition
- and return a syntax tree in the form of a list of
+def parse_asn1(asn1_definition):
+ """ Parse a string containing one or more ASN.1 module definitions.
+ Returns a list of module syntax trees represented as nested lists of
AnnotatedToken objects.
"""
grammar = _build_asn1_grammar()
- parse_result = grammar.parseString(asn1_payload)
+ parse_result = grammar.parseString(asn1_definition)
parse_tree = parse_result.asList()
return parse_tree
SIZE = Keyword('SIZE')
OF = Keyword('OF')
IMPORTS = Keyword('IMPORTS')
+ EXPORTS = Keyword('EXPORTS')
FROM = Keyword('FROM')
# Built-in types
sequenceof_type = Suppress(SEQUENCE) + Optional(size_constraint) + Suppress(OF) + (type_ | named_type)
setof_type = Suppress(SET) + Optional(size_constraint) + Suppress(OF) + (type_ | named_type)
choice_type = CHOICE + braced_list(named_type | extension_marker)
- enumerated_type = ENUMERATED + braced_list(enumeration)
+ enumerated_type = ENUMERATED + braced_list(enumeration | extension_marker)
bitstring_type = BIT_STRING + braced_list(named_number)
plain_integer_type = INTEGER
restricted_integer_type = INTEGER + braced_list(named_number)
# and we use them.
named_type << (Optional(identifier) + type_)
- # EXT: Trailing semi-colon is not allowed by standard
- # grammar, but our other ASN.1 code generator accepts it
- # and we happen to use it.
- type_assignment = typereference + '::=' + type_ + Suppress(Optional(';'))
+ type_assignment = typereference + '::=' + type_
value_assignment = valuereference + type_ + '::=' + value
assignment = type_assignment | value_assignment
- assignment_list = OneOrMore(assignment)
+ assignment_list = ZeroOrMore(assignment)
assigned_identifier = Optional(object_identifier_value | defined_value)
global_module_reference = module_reference + assigned_identifier
symbol = Unique(reference) # TODO: parameterized reference?
symbol_list = Group(delimitedList(symbol))
-
symbols_from_module = symbol_list + Suppress(FROM) + global_module_reference
symbols_from_module_list = OneOrMore(symbols_from_module)
symbols_imported = Optional(symbols_from_module_list)
+ exports = Optional(Suppress(EXPORTS) + symbol_list + Suppress(';'))
imports = Optional(Suppress(IMPORTS) + symbols_imported + Suppress(';'))
- module_body = (imports + assignment_list) | empty
+ module_body = (exports + imports + assignment_list)
module_defaults = Suppress(tag_default + extension_default) # we don't want these in the AST
module_identifier = module_reference + definitive_identifier
module_definition = module_identifier + DEFINITIONS + module_defaults + '::=' + BEGIN + module_body + END
definitive_number_form.setParseAction(annotate('DefinitiveNumberForm'))
definitive_name_and_number_form.setParseAction(annotate('DefinitiveNameAndNumberForm'))
imports.setParseAction(annotate('Imports'))
+ exports.setParseAction(annotate('Exports'))
assignment_list.setParseAction(annotate('AssignmentList'))
- return module_definition
+ start = ZeroOrMore(module_definition)
+ return start
def Unique(token):