\r
# Project files\r
.ropeproject\r
+env/\r
+dbg/\r
\r
# TODO\r
todo.txt
\ No newline at end of file
# values
# BUG: These are badly specified and cause the grammar to break if used generally.
# todo: consider more literals from 16.9
- real_value = Regex(r'-?\d+(\.\d*)?') # todo: this doesn't really follow the spec
+ real_value = Regex(r'-?\d+(\.\d*)?') # todo: this doesn't really follow the spec
boolean_value = TRUE | FALSE
- bitstring_value = bstring | hstring # todo: consider more forms from 21.9
+ bitstring_value = bstring | hstring # todo: consider more forms from 21.9
integer_value = signed_number
null_value = NULL
cstring_value = dblQuotedString
# constraints
# todo: consider the full subtype and general constraint syntax described in 45.*
- # but for now, just implement a simple integer value range.
- value_range_constraint = (signed_number | referenced_value | MIN) + Suppress('..') + (signed_number | referenced_value | MAX)
- size_constraint = Optional(Suppress('(')) + Suppress(SIZE) + Suppress('(') + value_range_constraint + Suppress(')') + Optional(Suppress(')'))
- constraint = Suppress('(') + value_range_constraint + Suppress(')')
+ lower_bound = (signed_number | referenced_value | MIN)
+ upper_bound = (signed_number | referenced_value | MAX)
+ single_value_constraint = Suppress('(') + value + 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(')'))
# TODO: consider exception syntax from 24.1
extension_marker = Unique(ELLIPSIS)
setof_type = Suppress(SET) + Optional(size_constraint) + Suppress(OF) + (type_ | named_type)
choice_type = CHOICE + braced_list(named_type | extension_marker)
enumerated_type = ENUMERATED + braced_list(enumeration | extension_marker)
- bitstring_type = BIT_STRING + braced_list(named_number)
- plain_integer_type = INTEGER
- restricted_integer_type = INTEGER + braced_list(named_number)
+ bitstring_type = BIT_STRING + braced_list(named_number) + Optional(single_value_constraint | size_constraint)
+ plain_integer_type = INTEGER + Optional(single_value_constraint)
+ restricted_integer_type = INTEGER + braced_list(named_number) + Optional(single_value_constraint)
boolean_type = BOOLEAN
real_type = REAL
null_type = NULL
object_identifier_type = OBJECT_IDENTIFIER
- octetstring_type = OCTET_STRING
+ octetstring_type = OCTET_STRING + Optional(size_constraint)
unrestricted_characterstring_type = CHARACTER_STRING
restricted_characterstring_type = BMPString | GeneralString | \
GraphicString | IA5String | \
ISO646String | NumericString | \
PrintableString | TeletexString | \
T61String | UniversalString | \
- UTF8String | VideotexString | VisibleString
- characterstring_type = restricted_characterstring_type | unrestricted_characterstring_type
+ UTF8String | VideotexString | \
+ VisibleString
+ characterstring_type = (restricted_characterstring_type | unrestricted_characterstring_type) + Optional(size_constraint)
useful_type = GeneralizedTime | UTCTime | ObjectDescriptor
# todo: consider other builtins from 16.2
- simple_type = (boolean_type | null_type | octetstring_type | characterstring_type | real_type | plain_integer_type | object_identifier_type | useful_type) + Optional(constraint)
+ simple_type = (boolean_type | null_type | octetstring_type | characterstring_type | real_type | plain_integer_type | object_identifier_type | useful_type) + Optional(value_range_constraint)
constructed_type = choice_type | sequence_type | set_type
value_list_type = restricted_integer_type | enumerated_type
builtin_type = value_list_type | tagged_type | simple_type | constructed_type | sequenceof_type | setof_type | bitstring_type
setof_type.setParseAction(annotate('SetOfType'))
named_number.setParseAction(annotate('NamedValue'))
named_nonumber.setParseAction(annotate('NamedValue'))
- constraint.setParseAction(annotate('Constraint'))
+ single_value_constraint.setParseAction(annotate('SingleValueConstraint'))
size_constraint.setParseAction(annotate('SizeConstraint'))
+ value_range_constraint.setParseAction(annotate('ValueRangeConstraint'))
component_type.setParseAction(annotate('ComponentType'))
component_type_optional.setParseAction(annotate('ComponentTypeOptional'))
component_type_default.setParseAction(annotate('ComponentTypeDefault'))
def defn_simple_type(self, class_name, t):
if t.constraint:
- return '%s.subtypeSpec = constraint.ValueRangeConstraint(%s, %s)' % (class_name, t.constraint.min_value, t.constraint.max_value)
+ return '%s.subtypeSpec = %s' % (class_name, self.build_constraint_expr(t.constraint))
return None
def inline_simple_type(self, t):
type_expr = _translate_type(t.type_name) + '()'
if t.constraint:
- type_expr += '.subtype(subtypeSpec=constraint.ValueRangeConstraint(%s, %s))' % (t.constraint.min_value, t.constraint.max_value)
+ type_expr += '.subtype(subtypeSpec=%s)' % self.build_constraint_expr(t.constraint)
return type_expr
return 'tag.Tag(%s, %s, %s)' % (context, tag_format, tag_def.class_number)
+ def build_constraint_expr(self, constraint):
+ def unpack_size_constraint(nested):
+ if isinstance(nested, SingleValueConstraint):
+ return nested.value, nested.value
+ elif isinstance(nested, ValueRangeConstraint):
+ return nested.min_value, nested.max_value
+ else:
+ assert False, "Unrecognized nested size constraint type: %s" % type(constraint.nested).__name__
+
+ if isinstance(constraint, SingleValueConstraint):
+ return 'constraint.SingleValueConstraint(%s)' % (constraint.value)
+ elif isinstance(constraint, SizeConstraint):
+ min_value, max_value = unpack_size_constraint(constraint.nested)
+ return 'constraint.ValueRangeConstraint(%s, %s)' % (min_value, max_value)
+ elif isinstance (constraint, ValueRangeConstraint):
+ return 'constraint.ValueRangeConstraint(%s, %s)' % (constraint.min_value,
+ constraint.max_value)
+ else:
+ assert False, "Unrecognized constraint type: %s" % type(constraint).__name__
+
def inline_component_type(self, t):
if t.components_of_type:
# COMPONENTS OF works like a literal include, so just
def __init__(self, elements):
self.constraint = None
self.type_name = elements[0]
- if len(elements) > 1 and elements[1].ty == 'Constraint':
- self.constraint = Constraint(elements[1].elements)
+ if len(elements) > 1:
+ _assert_annotated_token(elements[1])
+ self.constraint = _create_sema_node(elements[1])
def __str__(self):
if self.constraint is None:
__repr__ = __str__
-class Constraint(SemaNode):
+class SingleValueConstraint(SemaNode):
def __init__(self, elements):
- min_value, max_value = elements
+ self.value = _maybe_create_sema_node(elements[0])
+
+ def __str__(self):
+ return '(%s)' % self.value
+
+ __repr__ = __str__
- self.min_value = _maybe_create_sema_node(min_value)
- self.max_value = _maybe_create_sema_node(max_value)
+
+class ValueRangeConstraint(SemaNode):
+ def __init__(self, elements):
+ self.min_value = _maybe_create_sema_node(elements[0])
+ self.max_value = _maybe_create_sema_node(elements[1])
def __str__(self):
return '(%s..%s)' % (self.min_value, self.max_value)
__repr__ = __str__
-class SizeConstraint(Constraint):
- """ Size constraints have the same form as any value range constraints."""
+class SizeConstraint(SemaNode):
+ """ Size constraints nest single-value or range constraints to denote valid sizes. """
+ def __init__(self, elements):
+ self.nested = _create_sema_node(elements[0])
+ assert isinstance(self.nested, (ValueRangeConstraint, SingleValueConstraint))
+
def __str__(self):
- return 'SIZE(%s..%s)' % (self.min_value, self.max_value)
+ return 'SIZE%s' % (self.nested)
__repr__ = __str__
class ValueListType(SemaNode):
def __init__(self, elements):
self.type_name = elements[0]
+ self.named_values = None
+ self.constraint = None
+
if len(elements) > 1:
self.named_values = [_create_sema_node(token) for token in elements[1]]
for idx, n in enumerate(self.named_values):
n.value = str(0)
else:
n.value = str(int(self.named_values[idx-1].value) + 1)
- else:
- self.named_values = None
+
+ if len(elements) > 2:
+ self.constraint = _create_sema_node(elements[2])
def __str__(self):
+ named_value_list = ''
+ constraint = ''
if self.named_values:
- named_value_list = ', '.join(map(str, self.named_values))
- return '%s { %s }' % (self.type_name, named_value_list)
- else:
- return '%s' % self.type_name
+ named_value_list = ' { %s }' % ', '.join(map(str, self.named_values))
+
+ if self.constraint:
+ constraint = ' %s' % self.constraint
+
+ return '%s%s%s' % (self.type_name, named_value_list, constraint)
__repr__ = __str__
return SetOfType(token.elements)
elif token.ty == 'ExtensionMarker':
return ExtensionMarker(token.elements)
+ elif token.ty == 'SingleValueConstraint':
+ return SingleValueConstraint(token.elements)
elif token.ty == 'SizeConstraint':
return SizeConstraint(token.elements)
+ elif token.ty == 'ValueRangeConstraint':
+ return ValueRangeConstraint(token.elements)
elif token.ty == 'ObjectIdentifierValue':
return ObjectIdentifierValue(token.elements)
elif token.ty == 'NameForm':
quux SEQUENCE OF Foo -- user-defined type
}
- -- With size constraint
- Sized ::= SEQUENCE SIZE(1..100) OF INTEGER
- SizedWithParens ::= SEQUENCE (SIZE(1..100)) OF INTEGER
+ -- Constraints handled in size_constraint.asn
END
quux SET OF Foo -- user-defined type
}
- -- With size constraint
- Sized ::= SET SIZE(1..100) OF INTEGER
- SizedWithParens ::= SET (SIZE(1..100)) OF INTEGER
+ -- Constraints handled in size_constraint.asn
END
--- /dev/null
+TEST DEFINITIONS ::=\r
+BEGIN\r
+ value INTEGER ::= 128\r
+\r
+ -- Single-value constraints apply to all types.\r
+ ConstrainedInteger1 ::= INTEGER (50)\r
+ ConstrainedInteger2 ::= INTEGER (value)\r
+ ConstrainedInteger3 ::= INTEGER { one(10), two(20) } (10)\r
+\r
+ ConstrainedBitString1 ::= BIT STRING { one(1), two(2) } (1)\r
+\r
+ -- TODO: Add tests for the rest of the types as we need them.\r
+END\r
--- /dev/null
+TEST DEFINITIONS ::=\r
+BEGIN\r
+ min INTEGER ::= 128\r
+ max INTEGER ::= 256\r
+\r
+ -- Size constraints apply to the following types.\r
+ ConstrainedOctetStr1 ::= OCTET STRING (SIZE(32))\r
+ ConstrainedOctetStr2 ::= OCTET STRING (SIZE(16..32))\r
+ ConstrainedOctetStr3 ::= OCTET STRING (SIZE(min..max))\r
+\r
+ ConstrainedBitString1 ::= BIT STRING { one(1), two(2) } (SIZE(6))\r
+\r
+ -- TypeWithConstraint syntax for SET OF and SEQUENCE OF\r
+ SizedSetOf ::= SET SIZE(1..100) OF INTEGER\r
+ SizedSetOfWithParens ::= SET (SIZE(1..100)) OF INTEGER\r
+\r
+ SizedSequenceOf ::= SEQUENCE SIZE(1..100) OF INTEGER\r
+ SizedSequenceOfWithParens ::= SEQUENCE (SIZE(1..100)) OF INTEGER\r
+\r
+ \r
+ -- TODO: MIN/MAX is not yet translated in codegen.\r
+ -- ConstrainedOctetStr4 ::= OCTET STRING (SIZE(MIN..MAX))\r
+\r
+ -- TODO: Add tests for REAL types once we have them in place.\r
+END\r
--- /dev/null
+TEST DEFINITIONS ::=\r
+BEGIN\r
+ -- Value range constraints apply to the following types.\r
+ min INTEGER ::= 128\r
+ max INTEGER ::= 256\r
+ ConstraintedInteger1 ::= INTEGER(1..100)\r
+ ConstraintedInteger2 ::= INTEGER(min..max)\r
+ -- This is not yet translated in codegen\r
+ -- ConstraintedInteger3 ::= INTEGER(MIN..MAX)\r
+\r
+ -- TODO: Add tests for REAL types once we have them in place.\r
+END\r