From e73684f3425670bee37c0684b13e2a7de6ffed86 Mon Sep 17 00:00:00 2001 From: Kim Grasman Date: Mon, 6 Jan 2014 11:16:12 +0100 Subject: [PATCH] Support for hex string literals. --- asn1ate/parser.py | 28 +++++++++++++++++++++++----- asn1ate/pyasn1gen.py | 3 +++ asn1ate/sema.py | 15 +++++++++++++++ testdata/hstring.asn | 7 +++++++ 4 files changed, 48 insertions(+), 5 deletions(-) create mode 100644 testdata/hstring.asn diff --git a/asn1ate/parser.py b/asn1ate/parser.py index 20648e6..c77ef8c 100644 --- a/asn1ate/parser.py +++ b/asn1ate/parser.py @@ -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) diff --git a/asn1ate/pyasn1gen.py b/asn1ate/pyasn1gen.py index bf921ac..d214712 100644 --- a/asn1ate/pyasn1gen.py +++ b/asn1ate/pyasn1gen.py @@ -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) diff --git a/asn1ate/sema.py b/asn1ate/sema.py index dd4b6fc..b5cac07 100644 --- a/asn1ate/sema.py +++ b/asn1ate/sema.py @@ -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 index 0000000..1a564fa --- /dev/null +++ b/testdata/hstring.asn @@ -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 -- 1.7.10.4