1 # Copyright (c) 2013-2017, Schneider Electric Buildings AB
4 # Redistribution and use in source and binary forms, with or without
5 # modification, are permitted provided that the following conditions are met:
6 # * Redistributions of source code must retain the above copyright
7 # notice, this list of conditions and the following disclaimer.
8 # * Redistributions in binary form must reproduce the above copyright
9 # notice, this list of conditions and the following disclaimer in the
10 # documentation and/or other materials provided with the distribution.
11 # * Neither the name of Schneider Electric Buildings AB nor the
12 # names of contributors may be used to endorse or promote products
13 # derived from this software without specific prior written permission.
15 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
19 # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 # ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 from asn1ate import parser
29 def build_semantic_model(parse_result):
30 """ Build a semantic model of the ASN.1 definition
31 from a syntax tree generated by asn1ate.parser.
34 for token in parse_result:
35 _assert_annotated_token(token)
36 root.append(_create_sema_node(token))
38 # Head back through the model to act on any automatic tagging
39 # Objects in root must be Modules by definition of the parser
41 if module.tag_default == TagImplicitness.AUTOMATIC:
42 # Automatic tagging is on - wrap the members of constructed types
43 for descendant in module.descendants():
44 if isinstance(descendant, ConstructedType):
50 def topological_sort(assignments):
51 """ Algorithm adapted from:
52 http://en.wikipedia.org/wiki/Topological_sorting.
54 Use this in code generators to sort assignments in dependency order, IFF
55 there are no circular dependencies.
57 Assumes assignments is an iterable of items with two methods:
58 - reference_name() -- returns the reference name of the assignment
59 - references() -- returns an iterable of reference names
60 upon which the assignment depends.
62 graph = dict((a.reference_name(), a.references()) for a in assignments)
64 def has_predecessor(node):
65 for predecessors in graph.values():
66 if node in predecessors:
71 # Build a topological order of reference names
72 topological_order = []
73 roots = [name for name in graph.keys()
74 if not has_predecessor(name)]
79 # Remove the current node from the graph
80 # and collect all new roots (the nodes that
81 # were previously only referenced from n)
82 successors = graph.pop(root, set())
83 roots.extend(successor for successor in successors
84 if not has_predecessor(successor))
86 topological_order.insert(0, root)
89 raise Exception('Can\'t sort cyclic references: %s' % graph)
91 # Sort the actual assignments based on the topological order
92 return sorted(assignments,
93 key=lambda a: topological_order.index(a.reference_name()))
96 def dependency_sort(assignments):
97 """ We define a dependency sort as a Tarjan strongly-connected
98 components resolution. Tarjan's algorithm happens to topologically
99 sort as a by-product of finding strongly-connected components.
101 Use this in code generators to sort assignments in dependency order, if
102 there are circular dependencies. It is slower than ``topological_sort``.
104 In the sema model, each node depends on types mentioned in its
105 ``descendants``. The model is nominally a tree, except ``descendants``
106 can contain node references forming a cycle.
108 Returns a list of tuples, where each item represents a component
109 in the graph. Ideally they're one-tuples, but if the graph has cycles
110 items can have any number of elements constituting a cycle.
112 This is nice, because the output is in perfect dependency order,
113 except for the cycle components, where there is no order. They
114 can be detected on the basis of their plurality and handled
117 # Build reverse-lookup table from name -> node.
118 assignments_by_name = {a.reference_name(): a for a in assignments}
120 # Build the dependency graph.
122 for assignment in assignments:
123 references = assignment.references()
124 graph[assignment] = [assignments_by_name[r] for r in references
125 if r in assignments_by_name]
127 # Now let Tarjan do its work! Adapted from here:
128 # http://www.logarithmic.net/pfh-files/blog/01208083168/tarjan.py
135 def strongconnect(node):
136 # Set the depth index for this node to the smallest unused index
137 index[node] = index_counter[0]
138 lowlinks[node] = index_counter[0]
139 index_counter[0] += 1
142 # Consider successors of `node`
143 successors = graph.get(node, [])
144 for successor in successors:
145 if successor not in lowlinks:
146 # Successor has not yet been visited; recurse on it
147 strongconnect(successor)
148 lowlinks[node] = min(lowlinks[node], lowlinks[successor])
149 elif successor in stack:
150 # the successor is in the stack and hence in the current
151 # strongly connected component (SCC)
152 lowlinks[node] = min(lowlinks[node], index[successor])
154 # If `node` is a root node, pop the stack and generate an SCC
155 if lowlinks[node] == index[node]:
156 connected_component = []
159 successor = stack.pop()
160 connected_component.append(successor)
161 if successor == node:
164 component = tuple(connected_component)
165 result.append(component)
167 for node in sorted(graph.keys(), key=lambda a: a.reference_name()):
168 if node not in lowlinks:
174 # Registered object identifier names
175 REGISTERED_OID_NAMES = {
178 'joint-iso-ccitt': 2,
183 'network-operator': 3,
186 'registration-authority': 1,
188 'identified-organization': 3,
191 'registration-procedures': 17
195 class TagImplicitness(object):
196 """ Tag implicit/explicit enumeration """
205 Concepts in the ASN.1 specification are mirrored here as a simple object model.
207 Class and member names typically follow the ASN.1 terminology, but there are
208 some concepts captured which are not expressed in the spec.
210 Most notably, we build a dependency graph of all types and values in a module,
211 to allow code generators to build code in dependency order.
213 All nodes that somehow denote a referenced type or value, either definitions
214 (type and value assignments) or references (referenced types, referenced values,
215 etc) must have a method called ``reference_name``.
219 class SemaNode(object):
220 """ Base class for all sema nodes. """
223 """ Return a list of all contained sema nodes.
225 This implementation finds all member variables of type
226 SemaNode. It also expands list members, to transparently
227 handle the case where a node holds a list of other
230 # Collect all SemaNode members.
231 members = list(vars(self).values())
232 children = [m for m in members if isinstance(m, SemaNode)]
234 # Expand SemaNodes out of list members, but do not recurse
235 # through lists of lists.
236 list_members = [m for m in members if isinstance(m, list)]
237 for m in list_members:
238 children.extend(n for n in m if isinstance(n, SemaNode))
242 def descendants(self):
243 """ Return a list of all recursively contained sema nodes.
246 for child in self.children():
247 descendants.append(child)
248 descendants.extend(child.descendants())
253 class Module(SemaNode):
254 def __init__(self, elements):
255 self._user_types = {}
257 module_reference, definitive_identifier, tag_default, extension_default, module_body = elements
258 exports, imports, assignments = module_body.elements
260 self.name = module_reference.elements[0]
262 if tag_default == 'IMPLICIT TAGS':
263 self.tag_default = TagImplicitness.IMPLICIT
264 elif tag_default == 'EXPLICIT TAGS':
265 self.tag_default = TagImplicitness.EXPLICIT
266 elif tag_default == 'AUTOMATIC TAGS':
267 self.tag_default = TagImplicitness.AUTOMATIC
269 if tag_default is not None:
270 raise Exception('Unexpected tag default: %s' % tag_default)
271 # Tag default was not specified, default to explicit
272 self.tag_default = TagImplicitness.EXPLICIT
274 self.assignments = [_create_sema_node(token) for token in assignments.elements]
276 def user_types(self):
277 if not self._user_types:
278 # Index all type assignments by name
279 type_assignments = [a for a in self.assignments if isinstance(a, TypeAssignment)]
280 for user_defined in type_assignments:
281 self._user_types[user_defined.type_name] = user_defined.type_decl
283 return self._user_types
285 def resolve_type_decl(self, type_decl, referenced_modules):
286 """ Recursively resolve user-defined types to their built-in
289 if isinstance(type_decl, ReferencedType):
291 if not type_decl.module_name or type_decl.module_name == self.name:
294 # Find the referenced module
295 for ref_mod in referenced_modules:
296 if ref_mod.name == type_decl.module_name:
300 raise Exception('Unrecognized referenced module %s in %s.' % (type_decl.module_name,
301 [module.name for module in
302 referenced_modules]))
303 return module.resolve_type_decl(module.user_types()[type_decl.type_name], referenced_modules)
307 def get_type_decl(self, type_name):
308 user_types = self.user_types()
309 return user_types[type_name]
311 def resolve_selection_type(self, selection_type_decl):
312 if not isinstance(selection_type_decl, SelectionType):
313 raise Exception("Expected SelectionType, was %s" % selection_type_decl.__class__.__name__)
315 choice_type = self.get_type_decl(selection_type_decl.type_decl.type_name)
316 for named_type in choice_type.components:
317 if named_type.identifier == selection_type_decl.identifier:
318 return named_type.type_decl
322 def resolve_tag_implicitness(self, tag_implicitness, tagged_type_decl):
323 """ The implicitness for a tag depends on three things:
324 * Any written implicitness on the tag decl itself (``tag_implicitness``)
325 * The module's tag default (kept in ``self.tag_default``)
326 * Details of the tagged type according to X.680, 30.6c (``tagged_type_decl``)
328 if tag_implicitness is not None:
329 return tag_implicitness
331 # Tagged CHOICEs must always be explicit if the default is implicit, automatic or empty
333 if isinstance(tagged_type_decl, ChoiceType):
334 return TagImplicitness.EXPLICIT
336 # No tag implicitness specified, use module-default
337 if self.tag_default is None:
338 # Explicit is default if nothing
339 return TagImplicitness.EXPLICIT
340 elif self.tag_default == TagImplicitness.AUTOMATIC:
341 # TODO: Expand according to rules for automatic tagging.
342 return TagImplicitness.IMPLICIT
344 return self.tag_default
347 return '%s DEFINITIONS ::=\n' % self.name \
349 + '\n'.join(map(str, self.assignments)) + '\n' \
355 class Assignment(SemaNode):
356 def references(self):
357 """ Return a set of all reference names (both values and types) that
358 this assignment depends on.
360 This happens to coincide with all contained SemaNodes as exposed by
361 ``descendants`` with a ``reference_name`` method.
363 return set(d.reference_name() for d in self.descendants()
364 if hasattr(d, 'reference_name'))
367 class TypeAssignment(Assignment):
368 def __init__(self, elements):
369 if len(elements) != 3:
370 raise Exception('Malformed type assignment')
371 type_name, _, type_decl = elements
372 self.type_name = type_name
373 self.type_decl = _create_sema_node(type_decl)
375 def reference_name(self):
376 return self.type_name
379 return '%s ::= %s' % (self.type_name, self.type_decl)
384 class ValueAssignment(Assignment):
385 def __init__(self, elements):
386 value_name, type_name, _, value = elements
387 self.value_name = value_name
388 self.type_decl = _create_sema_node(type_name)
389 self.value = _maybe_create_sema_node(value)
391 def reference_name(self):
392 return self.value_name
395 return '%s %s ::= %s' % (self.value_name, self.type_decl, self.value)
400 class ConstructedType(SemaNode):
401 """ Base type for SEQUENCE, SET and CHOICE. """
403 def __init__(self, elements):
404 type_name, component_tokens = elements
405 self.type_name = type_name
406 self.components = [_create_sema_node(token)
407 for token in component_tokens]
410 # Constructed types can have ExtensionMarkers as components, ignore them
411 component_types = [c.type_decl for c in self.components
412 if hasattr(c, 'type_decl')]
413 already_tagged = any(isinstance(c, TaggedType) for c in component_types)
414 if not already_tagged:
415 # Wrap components in TaggedTypes
416 for tag_number, child in enumerate([c for c in self.children()
417 if hasattr(c, 'type_decl')]):
418 element = child.type_decl
419 tagged_type = TaggedType((None, str(tag_number), None, element))
420 child.type_decl = tagged_type
423 component_type_list = ', '.join(map(str, self.components))
424 return '%s { %s }' % (self.type_name, component_type_list)
429 class ChoiceType(ConstructedType):
430 def __init__(self, elements):
431 super(ChoiceType, self).__init__(elements)
434 class SequenceType(ConstructedType):
435 def __init__(self, elements):
436 super(SequenceType, self).__init__(elements)
439 class SetType(ConstructedType):
440 def __init__(self, elements):
441 super(SetType, self).__init__(elements)
444 class CollectionType(SemaNode):
445 """ Base type for SET OF and SEQUENCE OF. """
447 def __init__(self, kind, elements):
449 self.type_name = self.kind + ' OF'
450 self.size_constraint = _maybe_create_sema_node(elements[0])
451 self.type_decl = _create_sema_node(elements[1])
454 if self.size_constraint:
455 return '%s %s OF %s' % (self.kind, self.size_constraint, self.type_decl)
457 return '%s OF %s' % (self.kind, self.type_decl)
462 class SequenceOfType(CollectionType):
463 def __init__(self, elements):
464 super(SequenceOfType, self).__init__('SEQUENCE', elements)
467 class SetOfType(CollectionType):
468 def __init__(self, elements):
469 super(SetOfType, self).__init__('SET', elements)
472 class TaggedType(SemaNode):
473 def __init__(self, elements):
474 self.class_name = None
475 self.class_number = None
476 if len(elements) == 3:
477 tag_token, implicitness, type_token = elements
478 for tag_element in tag_token.elements:
479 if tag_element.ty == 'TagClassNumber':
480 self.class_number = tag_element.elements[0]
481 elif tag_element.ty == 'TagClass':
482 self.class_name = tag_element.elements[0]
484 raise Exception('Unknown tag element: %s' % tag_element)
485 self.type_decl = _create_sema_node(type_token)
486 elif len(elements) == 4:
487 self.class_name, self.class_number, implicitness, self.type_decl = elements
489 raise Exception('Incorrect number of elements passed to TaggedType')
491 if implicitness == 'IMPLICIT':
492 self.implicitness = TagImplicitness.IMPLICIT
493 elif implicitness == 'EXPLICIT':
494 self.implicitness = TagImplicitness.EXPLICIT
495 elif implicitness is None:
496 self.implicitness = None # Module-default or automatic
500 return self.type_decl.type_name
505 class_spec.append(self.class_name)
506 class_spec.append(self.class_number)
508 result = '[%s] ' % ' '.join(class_spec)
509 if self.implicitness == TagImplicitness.IMPLICIT:
510 result += 'IMPLICIT '
511 elif self.implicitness == TagImplicitness.EXPLICIT:
512 result += 'EXPLICIT '
514 pass # module-default
516 result += str(self.type_decl)
523 class SimpleType(SemaNode):
524 def __init__(self, elements):
525 self.constraint = None
526 self.type_name = elements[0]
527 if len(elements) > 1:
528 _assert_annotated_token(elements[1])
529 self.constraint = _create_sema_node(elements[1])
532 if self.constraint is None:
533 return self.type_name
535 return '%s %s' % (self.type_name, self.constraint)
540 class ReferencedType(SemaNode):
544 class DefinedType(ReferencedType):
545 def __init__(self, elements):
546 self.constraint = None
547 self.module_name = None
549 module_ref, type_ref, size_constraint = elements
551 self.module_name = module_ref.elements[0]
552 self.type_name = type_ref
554 self.constraint = _create_sema_node(size_constraint)
556 def reference_name(self):
557 return self.type_name
561 type_name = self.module_name + '.' + self.type_name
563 type_name = self.type_name
565 if self.constraint is None:
568 return '%s %s' % (type_name, self.constraint)
573 class SelectionType(ReferencedType):
574 def __init__(self, elements):
575 self.identifier = elements[0].elements[0]
576 self.type_decl = _create_sema_node(elements[1])
580 return self.type_decl.type_name
582 def reference_name(self):
583 return self.type_name
586 return '%s < %s' % (self.identifier, self.type_name)
591 class ReferencedValue(SemaNode):
592 def __init__(self, elements):
593 if len(elements) > 1 and elements[0].ty == 'ModuleReference':
594 self.module_reference = elements[0].elements[0]
595 self.name = elements[1]
597 self.module_reference = None
598 self.name = elements[0]
600 def reference_name(self):
604 if not self.module_reference:
606 return '%s.%s' % (self.module_reference, self.name)
611 class SingleValueConstraint(SemaNode):
612 def __init__(self, elements):
613 self.value = _maybe_create_sema_node(elements[0])
616 return '(%s)' % self.value
621 class ValueRangeConstraint(SemaNode):
622 def __init__(self, elements):
623 self.min_value = _maybe_create_sema_node(elements[0])
624 self.max_value = _maybe_create_sema_node(elements[1])
627 return '(%s..%s)' % (self.min_value, self.max_value)
632 class SizeConstraint(SemaNode):
633 """ Size constraints nest single-value or range constraints to denote valid sizes. """
635 def __init__(self, elements):
636 self.nested = _create_sema_node(elements[0])
637 if not isinstance(self.nested, (ValueRangeConstraint, SingleValueConstraint)):
638 raise Exception('Unexpected size constraint type %s' % self.nested.__class__.__name__)
641 return 'SIZE%s' % self.nested
646 class ComponentType(SemaNode):
647 def __init__(self, elements):
648 self.identifier = None
649 self.type_decl = None
650 self.default_value = None
651 self.optional = False
652 self.components_of_type = None
654 def crack_named_type(token):
655 named_type = NamedType(token)
656 self.identifier = named_type.identifier
657 self.type_decl = named_type.type_decl
659 first_token = elements[0]
660 if first_token.ty == 'NamedType':
661 crack_named_type(first_token.elements)
662 elif first_token.ty == 'ComponentTypeOptional':
663 crack_named_type(first_token.elements[0].elements)
665 elif first_token.ty == 'ComponentTypeDefault':
666 crack_named_type(first_token.elements[0].elements)
667 self.default_value = _maybe_create_sema_node(first_token.elements[1])
668 elif first_token.ty == 'ComponentTypeComponentsOf':
669 self.components_of_type = _create_sema_node(first_token.elements[0])
671 raise Exception('Unknown component type %s' % first_token)
674 if self.components_of_type:
675 return 'COMPONENTS OF %s' % self.components_of_type
677 result = '%s %s' % (self.identifier, self.type_decl)
679 result += ' OPTIONAL'
680 elif self.default_value is not None:
681 result += ' DEFAULT %s' % self.default_value
688 class NamedType(SemaNode):
689 def __init__(self, elements):
690 first_token = elements[0]
691 if first_token.ty == 'Type':
692 # EXT: unnamed member
693 type_token = first_token
694 self.identifier = _get_next_unnamed()
695 elif first_token.ty == 'Identifier':
697 self.identifier = first_token.elements[0]
698 type_token = elements[1]
700 raise Exception('Unexpected token %s' % first_token.ty)
702 self.type_decl = _create_sema_node(type_token)
705 return '%s %s' % (self.identifier, self.type_decl)
710 class ValueListType(SemaNode):
711 def __init__(self, elements):
712 self.constraint = None
713 self.type_name = elements[0]
715 self.named_values = [_create_sema_node(token) for token in elements[1]]
716 for idx, n in enumerate(self.named_values):
717 if isinstance(n, NamedValue) and n.value is None:
721 n.value = str(int(self.named_values[idx - 1].value) + 1)
723 if len(elements) > 2:
724 self.constraint = _maybe_create_sema_node(elements[2])
727 named_value_list = ''
730 if self.named_values:
731 named_value_list = ' { %s }' % ', '.join(map(str, self.named_values))
734 constraint = ' %s' % self.constraint
736 return '%s%s%s' % (self.type_name, named_value_list, constraint)
741 class BitStringType(SemaNode):
742 def __init__(self, elements):
743 self.type_name = elements[0]
744 self.named_bits = [_create_sema_node(token) for token in elements[1]]
745 self.constraint = _maybe_create_sema_node(elements[2])
752 named_bit_list = ' { %s }' % ', '.join(map(str, self.named_bits))
755 constraint = ' %s' % self.constraint
757 return '%s%s%s' % (self.type_name, named_bit_list, constraint)
762 class NamedValue(SemaNode):
763 def __init__(self, elements):
764 if len(elements) == 1:
765 identifier_token = elements[0]
766 self.identifier = identifier_token
769 identifier_token, value_token = elements
770 self.identifier = identifier_token.elements[0]
771 self.value = value_token.elements[0]
774 return '%s (%s)' % (self.identifier, self.value)
779 class ExtensionMarker(SemaNode):
780 def __init__(self, elements):
789 class NameForm(SemaNode):
790 def __init__(self, elements):
791 self.name = elements[0]
793 def reference_name(self):
802 class NumberForm(SemaNode):
803 def __init__(self, elements):
804 self.value = elements[0]
807 return str(self.value)
812 class NameAndNumberForm(SemaNode):
813 def __init__(self, elements):
814 self.name = _create_sema_node(elements[0])
815 self.number = _create_sema_node(elements[1])
818 return '%s(%s)' % (self.name, self.number)
823 class ObjectIdentifierValue(SemaNode):
824 def __init__(self, elements):
825 self.components = [_create_sema_node(c) for c in elements]
828 return '{' + ' '.join(str(x) for x in self.components) + '}'
833 class BinaryStringValue(SemaNode):
834 def __init__(self, elements):
835 self.value = elements[0]
838 return '\'%s\'B' % self.value
843 class HexStringValue(SemaNode):
844 def __init__(self, elements):
845 self.value = elements[0]
848 return '\'%s\'H' % self.value
853 def _maybe_create_sema_node(token):
854 if isinstance(token, parser.AnnotatedToken):
855 return _create_sema_node(token)
860 def _create_sema_node(token):
861 _assert_annotated_token(token)
863 if token.ty == 'ModuleDefinition':
864 return Module(token.elements)
865 elif token.ty == 'TypeAssignment':
866 return TypeAssignment(token.elements)
867 elif token.ty == 'ValueAssignment':
868 return ValueAssignment(token.elements)
869 elif token.ty == 'ComponentType':
870 return ComponentType(token.elements)
871 elif token.ty == 'NamedType':
872 return NamedType(token.elements)
873 elif token.ty == 'ValueListType':
874 return ValueListType(token.elements)
875 elif token.ty == 'BitStringType':
876 return BitStringType(token.elements)
877 elif token.ty == 'NamedValue':
878 return NamedValue(token.elements)
879 elif token.ty == 'Type':
880 # Type tokens have a more specific type category
881 # embedded as their first element
882 return _create_sema_node(token.elements[0])
883 elif token.ty == 'SimpleType':
884 return SimpleType(token.elements)
885 elif token.ty == 'DefinedType':
886 return DefinedType(token.elements)
887 elif token.ty == 'SelectionType':
888 return SelectionType(token.elements)
889 elif token.ty == 'ReferencedValue':
890 return ReferencedValue(token.elements)
891 elif token.ty == 'TaggedType':
892 return TaggedType(token.elements)
893 elif token.ty == 'SequenceType':
894 return SequenceType(token.elements)
895 elif token.ty == 'ChoiceType':
896 return ChoiceType(token.elements)
897 elif token.ty == 'SetType':
898 return SetType(token.elements)
899 elif token.ty == 'SequenceOfType':
900 return SequenceOfType(token.elements)
901 elif token.ty == 'SetOfType':
902 return SetOfType(token.elements)
903 elif token.ty == 'ExtensionMarker':
904 return ExtensionMarker(token.elements)
905 elif token.ty == 'SingleValueConstraint':
906 return SingleValueConstraint(token.elements)
907 elif token.ty == 'SizeConstraint':
908 return SizeConstraint(token.elements)
909 elif token.ty == 'ValueRangeConstraint':
910 return ValueRangeConstraint(token.elements)
911 elif token.ty == 'ObjectIdentifierValue':
912 return ObjectIdentifierValue(token.elements)
913 elif token.ty == 'NameForm':
914 return NameForm(token.elements)
915 elif token.ty == 'NumberForm':
916 return NumberForm(token.elements)
917 elif token.ty == 'NameAndNumberForm':
918 return NameAndNumberForm(token.elements)
919 elif token.ty == 'BinaryStringValue':
920 return BinaryStringValue(token.elements)
921 elif token.ty == 'HexStringValue':
922 return HexStringValue(token.elements)
924 raise Exception('Unknown token type: %s' % token.ty)
927 def _assert_annotated_token(obj):
928 if type(obj) is not parser.AnnotatedToken:
929 raise Exception('Object %r is not an annotated token' % obj)
932 # HACK: Generate unique names for unnamed members
936 def _get_next_unnamed():
937 global _unnamed_counter
938 _unnamed_counter += 1
939 return 'unnamed%d' % _unnamed_counter