Support for binary string literals.
authorKim Grasman <kim.grasman@gmail.com>
Fri, 3 Jan 2014 16:42:47 +0000 (17:42 +0100)
committerKim Grasman <kim.grasman@gmail.com>
Fri, 3 Jan 2014 16:42:47 +0000 (17:42 +0100)
Codegen still TBD.
Inspired by patch by James Ward.

asn1ate/parser.py
asn1ate/sema.py
testdata/binary_string.asn [new file with mode: 0644]

index cef74d0..1ecdf0c 100644 (file)
@@ -25,7 +25,7 @@
 
 import re
 from copy import copy
-from pyparsing import Keyword, Literal, Word, OneOrMore, ZeroOrMore, 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, White
 
 
 __all__ = ['parse_asn1', 'AnnotatedToken']
@@ -158,7 +158,10 @@ def _build_asn1_grammar():
     # Literals
     number = Word(nums)
     signed_number = Combine(Optional('-') + number)  # todo: consider defined values from 18.1
-    bstring = Literal('\'') + Regex('[01]+') + Literal('\'B')
+    horizontal_whitespace = White('\t ')
+    binary_digit = Literal('0') | Literal('1')
+    binary_string = Combine(ZeroOrMore(Suppress(horizontal_whitespace) | binary_digit))
+    bstring = Suppress('\'') + binary_string + Suppress('\'B')
     hstring = Literal('\'') + Regex('[0-9A-F]+') + Literal('\'H')
 
     # Comments
@@ -349,6 +352,7 @@ def _build_asn1_grammar():
     imports.setParseAction(annotate('Imports'))
     exports.setParseAction(annotate('Exports'))
     assignment_list.setParseAction(annotate('AssignmentList'))
+    bstring.setParseAction(annotate('BinaryStringValue'))
 
     start = ZeroOrMore(module_definition)
     return start
index 6989b2c..dd4b6fc 100644 (file)
@@ -635,10 +635,10 @@ class ObjectIdentifierValue(object):
     def references(self):
         refs = []
         for component in self.components:
-            if not isinstance(component, str):
-                refs.extend(component.references())
-            else:
+            if isinstance(component, str):
                 refs.append(component)
+            else:
+                refs.extend(component.references())
 
         return refs
 
@@ -648,6 +648,19 @@ class ObjectIdentifierValue(object):
     __repr__ = __str__
 
 
+class BinaryStringValue(object):
+    def __init__(self, elements):
+        self.value = elements[0]
+
+    def references(self):
+        return []
+
+    def __str__(self):
+        return '\'%s\'B' % self.value
+
+    __repr__ = __str__
+
+
 def _maybe_create_sema_node(token):
     if isinstance(token, parser.AnnotatedToken):
         return _create_sema_node(token)
@@ -708,6 +721,8 @@ def _create_sema_node(token):
         return NumberForm(token.elements)
     elif token.ty == 'NameAndNumberForm':
         return NameAndNumberForm(token.elements)
+    elif token.ty == 'BinaryStringValue':
+        return BinaryStringValue(token.elements)
 
     raise Exception('Unknown token type: %s' % token.ty)
 
diff --git a/testdata/binary_string.asn b/testdata/binary_string.asn
new file mode 100644 (file)
index 0000000..b241273
--- /dev/null
@@ -0,0 +1,13 @@
+Test DEFINITIONS ::=
+BEGIN
+  value OCTET STRING ::= '0101010'B
+
+  -- With whitespace
+  whitespace OCTET STRING ::= '1 1     0'B
+
+  -- Whitespace only. This should probably be invalid.
+  whitespace-only OCTET STRING ::= '   'B
+
+  -- Empty literal. This should probably be invalid.
+  empty OCTET STRING ::= ''B
+END