From 323b0c2434d7ee8a88c82092670df1d517bc1ec3 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Kim=20Gr=C3=A4sman?= Date: Sun, 9 Jun 2019 14:51:13 +0200 Subject: [PATCH] Make SingleValueConstraint accept alternatives SingleValueConstraint can describe a set of valid values, not necessarily just one. This is not strictly correct -- the "|" token is used to create a UNION constraint composed of multiple other constraints of different types, so e.g. (1 | a | 6..10) is valid ASN.1, but not accepted by asn1ate. When proper combined constraints are implemented, this should fall out nicely and just work, but for now, support a common scenario with more than one SingleValue. --- asn1ate/parser.py | 3 ++- asn1ate/pyasn1gen.py | 4 ++-- asn1ate/sema.py | 4 ++-- testdata/single_value_constraint.asn | 2 ++ 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/asn1ate/parser.py b/asn1ate/parser.py index 7b0012f..4fd341e 100644 --- a/asn1ate/parser.py +++ b/asn1ate/parser.py @@ -239,7 +239,8 @@ def _build_asn1_grammar(): # todo: consider the full subtype and general constraint syntax described in 45.* lower_bound = (constraint_real_value | signed_number | referenced_value | MIN) upper_bound = (constraint_real_value | signed_number | referenced_value | MAX) - single_value_constraint = Suppress('(') + value + Suppress(')') + + single_value_constraint = Suppress('(') + Group(delimitedList(value, delim='|')) + Suppress(')') value_range_constraint = Suppress('(') + lower_bound + Suppress('..') + upper_bound + Suppress(')') # TODO: Include contained subtype constraint here if we ever implement it. size_constraint = Optional(Suppress('(')) + Suppress(SIZE) + (single_value_constraint | value_range_constraint) + Optional(Suppress(')')) diff --git a/asn1ate/pyasn1gen.py b/asn1ate/pyasn1gen.py index 6b77cd3..30bc56b 100755 --- a/asn1ate/pyasn1gen.py +++ b/asn1ate/pyasn1gen.py @@ -364,14 +364,14 @@ class Pyasn1Backend(object): def build_constraint_expr(self, constraint): def unpack_size_constraint(nested): if isinstance(nested, SingleValueConstraint): - return self.translate_value(nested.value), self.translate_value(nested.value) + return self.translate_value(nested.values[0]), self.translate_value(nested.values[0]) elif isinstance(nested, ValueRangeConstraint): return self.translate_value(nested.min_value), self.translate_value(nested.max_value) else: raise Exception('Unrecognized nested size constraint type: %s' % nested.__class__.__name__) if isinstance(constraint, SingleValueConstraint): - return 'constraint.SingleValueConstraint(%s)' % (self.translate_value(constraint.value)) + return 'constraint.SingleValueConstraint(%s)' % ', '.join(self.translate_value(v) for v in constraint.values) elif isinstance(constraint, SizeConstraint): min_value, max_value = unpack_size_constraint(constraint.nested) return 'constraint.ValueSizeConstraint(%s, %s)' % (self.translate_value(min_value), self.translate_value(max_value)) diff --git a/asn1ate/sema.py b/asn1ate/sema.py index 35270b2..06687a7 100644 --- a/asn1ate/sema.py +++ b/asn1ate/sema.py @@ -672,10 +672,10 @@ class ReferencedValue(SemaNode): class SingleValueConstraint(SemaNode): def __init__(self, elements): - self.value = _maybe_create_sema_node(elements[0]) + self.values = [_maybe_create_sema_node(e) for e in elements[0]] def __str__(self): - return '(%s)' % self.value + return '(%s)' % ' | '.join(map(str, self.values)) __repr__ = __str__ diff --git a/testdata/single_value_constraint.asn b/testdata/single_value_constraint.asn index 427d8cd..50177c1 100644 --- a/testdata/single_value_constraint.asn +++ b/testdata/single_value_constraint.asn @@ -6,6 +6,7 @@ BEGIN ConstrainedInteger1 ::= INTEGER (50) ConstrainedInteger2 ::= INTEGER (value) ConstrainedInteger3 ::= INTEGER { one(10), two(20) } (10) + ConstrainedInteger4 ::= INTEGER (100 | 50 | 25) ConstrainedBitString1 ::= BIT STRING { one(1), two(2) } (1) @@ -13,6 +14,7 @@ BEGIN ConstrainedReal1 ::= REAL (2.73) ConstrainedReal2 ::= REAL (realValue) ConstrainedReal3 ::= REAL (4E9) + ConstrainedReal4 ::= REAL (2.73 | 3.14 | 1.23) Alias ::= OCTET STRING ConstrainedAlias ::= Alias (SIZE(8)) -- 2.34.1