Support for hex string literals.
authorKim Grasman <kim.grasman@gmail.com>
Mon, 6 Jan 2014 10:16:12 +0000 (11:16 +0100)
committerKim Grasman <kim.grasman@gmail.com>
Mon, 6 Jan 2014 10:16:12 +0000 (11:16 +0100)
asn1ate/parser.py
asn1ate/pyasn1gen.py
asn1ate/sema.py
testdata/hstring.asn [new file with mode: 0644]

index 20648e6..c77ef8c 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, White
+from pyparsing import Keyword, Literal, Word, OneOrMore, ZeroOrMore, Combine, Regex, Forward, Optional, Group, Suppress, delimitedList, cStyleComment, nums, alphanums, empty, srange, dblQuotedString, Or
 
 
 __all__ = ['parse_asn1', 'AnnotatedToken']
@@ -158,10 +158,8 @@ def _build_asn1_grammar():
     # Literals
     number = Word(nums)
     signed_number = Combine(Optional('-') + number)  # todo: consider defined values from 18.1
-    binary_digit = Literal('0') | Literal('1')
-    binary_string = Combine(OneOrMore(binary_digit), adjacent=False)  # Use adjacent=False to skip whiteepace
-    bstring = Suppress('\'') + binary_string + Suppress('\'B')
-    hstring = Literal('\'') + Regex('[0-9A-F]+') + Literal('\'H')
+    bstring = Suppress('\'') + StringOf('01') + Suppress('\'B')
+    hstring = Suppress('\'') + StringOf('0123456789ABCDEF') + Suppress('\'H')
 
     # Comments
     hyphen_comment = Regex(r"--[\s\S]*?(--|$)", flags=re.MULTILINE)
@@ -352,6 +350,7 @@ def _build_asn1_grammar():
     exports.setParseAction(annotate('Exports'))
     assignment_list.setParseAction(annotate('AssignmentList'))
     bstring.setParseAction(annotate('BinaryStringValue'))
+    hstring.setParseAction(annotate('HexStringValue'))
 
     start = OneOrMore(module_definition)
     return start
@@ -370,3 +369,22 @@ def Unique(token):
     with the same underlying rules.
     """
     return copy(token)
+
+
+def StringOf(elements):
+    """ Create a rule to parse a string of any of the chars in elements.
+    Skips any whitespace.
+    This is useful for the ASN.1 hstring and bstring productions.
+    """
+    element = CharSet(elements)
+    return Combine(OneOrMore(element), adjacent=False)  # Use adjacent=False to skip whitespace
+
+
+def CharSet(elements):
+    """ Create a set of valid characters as a single rule.
+    elements is a string containing all the desired chars, e.g.
+      CharSet('01234567890')        # all numbers
+      CharSet('01234567890ABCDEF')  # all hex numbers
+    """
+    unpacked_chars = [Literal(c) for c in elements]
+    return Or(unpacked_chars)
index bf921ac..d214712 100644 (file)
@@ -297,6 +297,9 @@ class Pyasn1Backend(object):
         elif isinstance(value, BinaryStringValue):
             value_type = _translate_type(type_decl.type_name)
             value_constructor = '%s(binValue=\'%s\')' % (value_type, value.value)
+        elif isinstance(value, HexStringValue):
+            value_type = _translate_type(type_decl.type_name)
+            value_constructor = '%s(hexValue=\'%s\')' % (value_type, value.value)
         else:
             value_type = _translate_type(type_decl.type_name)
             value_constructor = '%s(%s)' % (value_type, value)
index dd4b6fc..b5cac07 100644 (file)
@@ -661,6 +661,19 @@ class BinaryStringValue(object):
     __repr__ = __str__
 
 
+class HexStringValue(object):
+    def __init__(self, elements):
+        self.value = elements[0]
+
+    def references(self):
+        return []
+
+    def __str__(self):
+        return '\'%s\'H' % self.value
+
+    __repr__ = __str__
+
+
 def _maybe_create_sema_node(token):
     if isinstance(token, parser.AnnotatedToken):
         return _create_sema_node(token)
@@ -723,6 +736,8 @@ def _create_sema_node(token):
         return NameAndNumberForm(token.elements)
     elif token.ty == 'BinaryStringValue':
         return BinaryStringValue(token.elements)
+    elif token.ty == 'HexStringValue':
+        return HexStringValue(token.elements)
 
     raise Exception('Unknown token type: %s' % token.ty)
 
diff --git a/testdata/hstring.asn b/testdata/hstring.asn
new file mode 100644 (file)
index 0000000..1a564fa
--- /dev/null
@@ -0,0 +1,7 @@
+Test DEFINITIONS ::=
+BEGIN
+  value OCTET STRING ::= '0123456789ABCDEF'H
+
+  -- Whitespace is ignored in hex strings
+  whitespace OCTET STRING ::= 'A B 1 4'H
+END