asn1: Fix 5 shift/reduce conflicts

There remains one tough shift/reduce conflict, the warning for which is
quieted with an `%expect 1` directive.

The remaining conflict has to do with whether a constraint attaches to
the inner type that some other outer type is a SET OF or SEQUENCE OF or
tagged-type of, or whether it attaches to the outer type.  The two are
really the same thing.  The latter is the reduce side, so it's not used,
but if it were we could grab the constraint in the action and attach it
to the inner type anyways.
This commit is contained in:
Nicolas Williams
2022-01-21 22:34:12 -06:00
parent f0f6bb03f4
commit e1fa08a4d6
3 changed files with 53 additions and 36 deletions

View File

@@ -4,7 +4,7 @@ include $(top_srcdir)/Makefile.am.common
WFLAGS += $(WFLAGS_ENUM_CONV)
YFLAGS = -d -t
YFLAGS = -o asn1parse.c -t
AM_CPPFLAGS += $(ROKEN_RENAME) -I$(top_builddir)/include -I$(top_srcdir)/lib/base

View File

@@ -242,6 +242,7 @@ static unsigned long idcounter;
%type <type> BooleanType
%type <type> ChoiceType
%type <type> ConstrainedType
%type <type> UnconstrainedType
%type <type> EnumeratedType
%type <type> IntegerType
%type <type> NullType
@@ -288,6 +289,7 @@ static unsigned long idcounter;
%type <constraint_spec> Constraint
%type <constraint_spec> ConstraintSpec
%type <constraint_spec> SubtypeConstraint
%type <constraint_spec> GeneralConstraint
%type <constraint_spec> ContentsConstraint
%type <constraint_spec> UserDefinedConstraint
@@ -295,7 +297,7 @@ static unsigned long idcounter;
%type <constraint_spec> ComponentRelationConstraint
%expect 1
%start ModuleDefinition
%%
@@ -364,8 +366,6 @@ ModuleDefinition: Identifier objid_opt kw_DEFINITIONS TagDefault ExtensionDefaul
fprintf(jsonfile, "]}\n");
free(o);
}
| CLASS_IDENTIFIER objid_opt kw_DEFINITIONS TagDefault ExtensionDefault
EEQUAL kw_BEGIN ModuleBody kw_END
;
TagDefault : kw_EXPLICIT kw_TAGS
@@ -914,10 +914,9 @@ ParamGovernor : DefinedObjectClass
/* | Type */
;
Type : BuiltinType
| ReferencedType
| ConstrainedType
;
UnconstrainedType : BuiltinType | ReferencedType;
Type : UnconstrainedType | ConstrainedType ;
BuiltinType : BitStringType
| BooleanType
@@ -948,39 +947,49 @@ BooleanType : kw_BOOLEAN
}
;
range : '(' Value RANGE Value ')'
/*
* The spec says the values in a ValueRange are Values, but a) all
* the various value ranges do not involve OBJECT IDENTIFIER, b)
* we only support integer value ranges at this time (as opposed
* to, e.g., time ranges, and we don't even support time values at
* this time), c) allowing OBJECT IDENTIFIER here causes a
* shift-reduce conflict, so we limit ourselves to integer values
* in ranges. We could always define IntegerValueRange,
* TimeValueRange, etc. when we add support for more value types.
*/
range : IntegerValue RANGE IntegerValue
{
if($2->type != integervalue)
if($1->type != integervalue)
lex_error_message("Non-integer used in first part of range");
if($2->type != integervalue)
if($1->type != integervalue)
lex_error_message("Non-integer in second part of range");
$$ = ecalloc(1, sizeof(*$$));
$$->min = $2->u.integervalue;
$$->max = $4->u.integervalue;
$$->min = $1->u.integervalue;
$$->max = $3->u.integervalue;
}
| '(' Value RANGE kw_MAX ')'
| IntegerValue RANGE kw_MAX
{
if($2->type != integervalue)
if($1->type != integervalue)
lex_error_message("Non-integer in first part of range");
$$ = ecalloc(1, sizeof(*$$));
$$->min = $2->u.integervalue;
$$->min = $1->u.integervalue;
$$->max = INT_MAX;
}
| '(' kw_MIN RANGE Value ')'
| kw_MIN RANGE IntegerValue
{
if($4->type != integervalue)
if($3->type != integervalue)
lex_error_message("Non-integer in second part of range");
$$ = ecalloc(1, sizeof(*$$));
$$->min = INT_MIN;
$$->max = $4->u.integervalue;
$$->max = $3->u.integervalue;
}
| '(' Value ')'
| IntegerValue
{
if($2->type != integervalue)
if($1->type != integervalue)
lex_error_message("Non-integer used in limit");
$$ = ecalloc(1, sizeof(*$$));
$$->min = $2->u.integervalue;
$$->max = $2->u.integervalue;
$$->min = $1->u.integervalue;
$$->max = $1->u.integervalue;
}
;
@@ -990,12 +999,6 @@ IntegerType : kw_INTEGER
$$ = new_tag(ASN1_C_UNIV, UT_Integer,
TE_EXPLICIT, new_type(TInteger));
}
| kw_INTEGER range
{
$$ = new_type(TInteger);
$$->range = $2;
$$ = new_tag(ASN1_C_UNIV, UT_Integer, TE_EXPLICIT, $$);
}
| kw_INTEGER '{' NamedNumberList '}'
{
$$ = new_type(TInteger);
@@ -1101,8 +1104,8 @@ NullType : kw_NULL
size :
{ $$ = NULL; }
| kw_SIZE range
{ $$ = $2; }
| kw_SIZE '(' range ')'
{ $$ = $3; }
;
@@ -1250,10 +1253,17 @@ UsefulType : kw_GeneralizedTime
}
;
ConstrainedType : Type Constraint
ConstrainedType : UnconstrainedType Constraint
{
$$ = $1;
$$->constraint = $2;
if ($2->ctype == CT_RANGE) {
if ($1->type != TTag || $1->subtype->type != TInteger)
lex_error_message("RANGE constraints apply only to INTEGER types");
$$->subtype->range = $2->u.range;
free($2);
} else {
$$->constraint = $2;
}
/* if (Constraint.type == contentConstraint) {
assert(Constraint.u.constraint.type == octetstring|bitstring-w/o-NamedBitList); // remember to check type reference too
if (Constraint.u.constraint.type) {
@@ -1274,9 +1284,15 @@ Constraint : '(' ConstraintSpec ')'
}
;
ConstraintSpec : GeneralConstraint
ConstraintSpec : SubtypeConstraint | GeneralConstraint
;
SubtypeConstraint: range
{
$$ = new_constraint_spec(CT_RANGE);
$$->u.range = $1;
}
GeneralConstraint: ContentsConstraint
| UserDefinedConstraint
| TableConstraint
@@ -1452,7 +1468,7 @@ tagenv : /* */
;
ValueAssignment : Identifier Type EEQUAL Value
ValueAssignment : VALUE_IDENTIFIER Type EEQUAL Value
{
Symbol *s;
s = addsym ($1);

View File

@@ -120,7 +120,7 @@ struct range {
int64_t max;
};
enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT } ;
enum ctype { CT_CONTENTS, CT_USER, CT_TABLE_CONSTRAINT, CT_RANGE } ;
struct constraint_spec;
@@ -217,6 +217,7 @@ struct constraint_spec {
struct value *encoding;
struct component_relation_constraint crel;
} content;
struct range *range;
} u;
};