Age | Commit message (Collapse) | Author |
|
|
|
As currently implemented, there is one call to asn1db:dbget() and
asn1db:dbput() for each type/value definitions in an ASN.1 specification.
If we check for duplicate definitions locally, we can send all
definitions in a single call.
|
|
Three fields ('type','value', and 'vname') are almost unused. They
are set, but almost never read. Eliminate the last remaining uses
and the fields themselves.
|
|
|
|
And while we are at it cleanup and rewrite code to use try catch.
|
|
|
|
|
|
|
|
In the parsing of a value assignment, such as:
value INTEGER ::= 42
there is call to a function called lookahead_assignment/1 that
will ensure that the sequence of tokens that follows the value
is a valid assignment. The problem is that if the next assignment
is a value assignment, that too will look ahead to the next
assignment. That means that the complexity will be quadratic
if there are many value assignments following each other.
The reason for the test in the first place is unclear; my guess
is that it was an attempt to provide better error reporting.
|
|
Errors were reported using a throw like this:
throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module),
[got,get_token(hd(Tokens)),expected,typereference]}}).
The attempt to tell the user what was expected was often mis-leading.
It is time-consuming and non-trival to provide correct information
of what is expected. Therefore, we will not even try. Instead we will
spend more effort to report the token where the error was discovered.
We will replace each throw with a function call:
parse_error(Tokens).
Also add the syntax_SUITE test suite to test error reporting and to
cover all error reporting code. Remove the old c_syntax/1 test case.
Also remove all out-commented code.
|
|
Responsibilities for parse error handling were split between
asn1ct and asn1ct_parser2 in a confusing way. Let asn1ct_parser2
return structured_error tuples in the same way as the check
pass.
|
|
Most uses of 'catch' are not necessary. For example,
parse_or/2 is typically called like this:
case catch parse_or(Tokens, Flist) of
{'EXIT',Reason} ->
exit(Reason);
{asn1_error,_}=AsnErr ->
throw(AsnErr);
Result ->
Result
end.
Since {asn1_error,_} is always thrown (never returned) and
a successful is always returned (never thrown), the 'case' and
the 'catch' are not necessary. The code can be simplified too:
parse_or(Tokens, Flist)
In a few cases, we will need to replace the 'catch' with
'try'...'catch'.
|
|
Use try...catch instead of catch.
|
|
The first position in a token tuple is always an atom, the second
the line number. The code tested the third position.
|
|
In a future commit, we want to tighten what we catch. Therefore,
legitimate parsing errors should always throw a controlled exception,
instead of arbitrarily crashing.
|
|
The parse_Type/1 calls various type parse functions. Most of those
functions return a #type record, but not all of them. If a #type{}
record is not returned, parse_Type/1 will wrap the return value in a
We can simplify the code in parse_Type/1 if we make sure that the
type parsing functions called by parse_Type/1 always return
a #type{} record.
|
|
The TypeFromObject and ValueSetFromObjects grammar productions cannot
be distinguished by the parser without the help of type information
(which the parser does not have). Since the parser attempts to
parse TypeFromObject before ValueSetFromObjects, the parsing of
ValueSetFromObjects will always fail.
|
|
To keep the error reporting code in asn1ct_parser2 simple, we
only want to handle pure syntactic errors. Therefore, move the check
that UNIQUE and DEFAULT are not applied to the same field to
asn1ct_check.
|
|
asn1ct_gen_check.erl was added in 7df687d6.
|
|
|
|
|
|
While we are at it, also remove an unreachable (too many extensions)
error case.
|
|
|
|
|
|
|
|
Clean up the checking of ENUMERATED and modernize the error reporting.
Also eliminate the unused constraints argument for check_enumerated().
|
|
The ASN.1 compiler would go into an infinite loop if a value
in an ENUMERATED was negative.
|
|
|
|
|
|
get_unique_fieldname/2 would throw an exception that *all* callers
would catch and handle. Since all callers catch the exception, it
is much easier to return a special return value.
Also use the new error reporting style.
While we are at it, remove all catches of {asn1,Error} which
are no longer thrown.
|
|
Split the test case duplicate_tags/1 into two parts. Do the
error checking test in error_SUITE. Keep the SeqOptional2
specification and compile it from the per/1 and ber_other/1
test cases (for coverage).
|
|
|
|
Change to new error handling system and cover with tests.
|
|
All errors were not reported. Furthermore, get_referenced_type/2
will report errors if any module is missing, so the attempt to
report additional errors in chained_import/4 would not find any
errors.
|
|
The internal representation for constraints (and object sets)
as produced by the parser was awkward, making further processing
convoluted. Here follows some examples of the old representation
for INTEGER constraints.
The constraint 1..2 is represented as:
{'ValueRange',{1,2}}
If we extend the constraint like this:
1..2, ...,
or like this:
1..2, ..., 3
the representation would be:
{{'ValueRange',{1,2}},[]}
and
{{'ValueRange',{1,2}},{'SingleValue',3}}
respectively. Note that the pattern {A,B} will match all these
constraints.
When combining constraints using set operators:
1..2 | 3..4 ^ 5..6
the representation will no longer be a tuple but a list:
[{'ValueRange',{1..2}} union
{'ValueRange',{3..4}} intersection
{'ValueRange',{5..6}}]
The parse has full knowledge of the operator precedence; unfortunately,
the following pass (asn1ct_check) must also have the same knowledge
in order to correctly evaluate the constraints.
If we would change the order of the evaulation with round brackets:
(1..2 | 3..4) ^ 5..6
there would be a nested listed in the representation:
[[{'ValueRange',{1..2}} union {'ValueRange',{3..4}}]
intersection {'ValueRange',{5..6}}]
We will change the representation to make it more explicit.
At the outer level, a constraint is always represented as
{element_set,Root,Extension}
Extension will be 'none' if there is no extension, and 'empty' if
there is an empty extension. Root may also be 'empty' in an object set
if there are no objects in the root. Thus the constraints:
1..2
1..2, ...
1..2, ..., 3
will be represented as:
{element_set,{'ValueRange',{1,2}},none}
{element_set,{'ValueRange',{1,2}},empty}
{element_set,{'ValueRange',{1,2}},{'SingleValue',3}}
We will change the set operators too. This constraint:
1..2 | 3..4 ^ 5..6
will be represented as:
{element_set,
{union,
{'ValueRange',{1,2}},
{intersection,
{'ValueRange',{3,4}},
{'ValueRange',{5,6}}},
none}}
which is trivial to understand and evaluate. Similarly:
(1..2 | 3..4) ^ 5..6
will be represented as:
{element_set,
{intersection,
{union,{'ValueRange',{1,2}},{'ValueRange',{3,4}}},
{'ValueRange',{5,6}}},
none}
|
|
NeedRest was introduced in df7bb30f, for unknown reasons (my guess
is that the argument was needed at some point during the development
of the commit).
Found by dialyzer.
|
|
Fixes needed to avoid a compiling asn1 files in order.
For example the x420 directory in test now compiles with
erlc *.asn
Do not save class records without module information in asn1db files.
Use recursive get_referenced_type in get_objclass_fields/2
|
|
|
|
|
|
The ObjectSetFromObjects construct is implemented using
the object_set_from_objects() function, which is similar
to get_fieldname_element(). Rewrite the ObjectSetFromObjects
handling to use get_fieldname_element() to share more code.
|
|
|
|
|
|
a1260b2ffa60581ce3af0728320b593cca3fd7b0 fixed a problem with
expansion of parameterized types, but it didn't go all the way.
The compiler would still crash if we attempted to define a value
using the instantiated type.
|
|
Introduce match_parameter/2 for matching a single parameter and
match_parameters/2 for matching all of them.
|
|
The constraint_member/2 function is used for looking up 'simpletable'
and 'componentrelation' constraints. Both parts of its name are
misleading. The "constraint" part makes you think that it is a general
function for constraints, but it is not - it can only search for
'simpletable' and 'componentrelation'. The "member" part makes you
think that it would return a boolean, but it returns either
{true,Tuple} or false, making it more similar to lists:keysearch/3.
Use lists:keyfind/3 (or lists:keymember/3) instead of
constraint_member/2. Also use lists:keyfind/3 in one place where
there was a direct matching of a 'simpletable' constraint.
|
|
|
|
There is no reason to handle tags differently depending on the
back-end. The PER back-end will simply ignore tags.
There is also a bug in tags the ABSTRACT-SYNTAX and TYPE-IDENTIFIER
pre-defined classes. So far it has not caused problems, but it could
do in a future commit, such as the next commit...
|
|
|
|
To be sure that indirect references to classes are solved.
|
|
|