asn1c: initiate work on asn1c with the last ITU-T version of 2021 in mind

This commit is contained in:
p1-bmu 2021-11-08 12:30:26 +01:00
parent 93ab3bfbd7
commit 2757678df1
3 changed files with 70 additions and 34 deletions

View File

@ -312,10 +312,7 @@ def _compile_text_pass(text, with_order, **kwargs):
m = SYNT_RE_MODULEDEF.search(text)
if not m:
break
#print(text[:m.start()])
#print(text[m.start():m.start()+100])
#
name, oidstr = module_get_name(text[:m.start()], fn)
module['_name_'] = name
if oidstr:
@ -370,8 +367,6 @@ def _compile_text_pass(text, with_order, **kwargs):
#
# 5) scan the asnblock for module imports
imports, cur = module_get_import(asnblock)
#if name == 'SUPL-REPORT':
# assert()
module['_imp_'] = {}
if cur:
asnblock = asnblock[cur:]
@ -663,10 +658,10 @@ def module_get_import(text=''):
fro = SYNT_RE_MODULEFROM.search(imp)
while fro:
# get module name / oid
name, oidstr, oidref = fro.groups()
# clean-up the oid
if oidstr:
oidstr = re.sub('\s{1,}', ' ', oidstr).strip()
cur_end, import_prm = extract_from_import(imp[fro.start():])
# clean-up the OID
if import_prm['oid']:
oidstr = re.sub('\s{1,}', ' ', import_prm['oid']).strip()
OidDummy = OID()
_path_stack(['val'])
try:
@ -677,27 +672,29 @@ def module_get_import(text=''):
else:
oid = OidDummy._val
_path_pop()
new_imp = imp[fro.end():].strip()
elif oidref:
oidstr = oidref
elif import_prm['oidref']:
oidstr = import_prm['oidref']
# at this stage, nothing is compiled, so there is no way to
# get the OID value referenced
oid = []
new_imp = imp[fro.regs[-1][1]:].strip()
else:
oidstr = ''
oid = []
new_imp = imp[fro.end():].strip()
# get all ASN.1 objects reference before
obj = imp[:fro.start()]
next_imp = imp[fro.start() + cur_end:].strip()
# get all ASN.1 objects reference before FROM
obj = imp[:fro.start()].strip()
# clean them up and split them to a list
obj = map(strip, re.sub('\s{1,}', ' ', obj).split(','))
# remove {} at the end of parameterized objects
obj = [o[:-2].strip() if o[-2:] == '{}' else o for o in obj]
# fill-in the import list
l.append({'name':name, 'oidstr':oidstr, 'oid':oid, 'obj':obj})
# iterate
imp = new_imp
l.append({'name':import_prm['name'],
'with':import_prm['with'],
'oidstr':oidstr,
'oid':oid,
'obj':obj})
# iterate to next import clause
imp = next_imp
fro = SYNT_RE_MODULEFROM.search(imp)
return l, m.end()
else:

View File

@ -952,12 +952,12 @@ class PycrateGenerator(_Generator):
for ident in pres:
if FLAG_OPT in Obj._cont[ident]._flag:
del Obj._cont[ident]._flag[FLAG_OPT]
'''
#
if len(Consts_comps[0]['root']) > 1:
asnlog('WNG: {0}.{1}: multiple root parts in WITH COMPONENTS constraint, '\
'unable to compile them'.format(self._mod_name, Obj._name))
return
'''
#
# 3) apply additional constraint on components
# only if we have a single root component in the constraint
@ -1009,6 +1009,7 @@ def asnmod_build_dep(mods):
CallerDict[objname] = [ Ref ]
return CallerDict, CalledDict
class JSONDepGraphGenerator(_Generator):
"""
JSONDepGraphGenerator generates a JSON file that enables to produce a directed

View File

@ -333,10 +333,28 @@ SYNT_RE_MODULEDEF = re.compile(
'\s{1,}(DEFINITIONS)\s{1,}')
SYNT_RE_MODULEREF = re.compile(
'(?:^|\s{1})(%s){1}\s{0,}(\{[\s\-a-zA-Z0-9\(\)]{1,}\}){0,1}' % _RE_TYPEREF)
'''
# FROM $ModuleRef $ModuleOIDOrOIDRef{0,1}
SYNT_RE_MODULEFROM = re.compile(
'(?:FROM\s{1,})(%s)' \
'(?:\s{0,}(\{[\s\-a-zA-Z0-9\(\)]{1,}\})|\s{1,}(%s)(?:\s{1,}%s(?:\s*\{\})?(?:\s{0,},|\s{1,}FROM)|\s{0,}$)){0,1}' \
'(?:\s*' \
'(\{[\s\-a-zA-Z0-9\(\)]{1,}\})|' \
'\s{1,}(%s)(?:\s{1,}%s(?:\s*\{\})?(?:\s*,|\s{1,}FROM)|\s*$)' \
'){0,1}' \
'(?:\s*WITH\s{1,}(SUCCESSORS|DESCENDANTS)){0,1}' \
% (_RE_TYPEREF, _RE_IDENT, _RE_WORD))
# TODO, catch "WITH SUCCESSORS" / "WITH DESCENDANTS" after the imported module name
'''
SYNT_RE_MODULEFROM = re.compile(
'(?:FROM\s{1,})(%s)\s*' % _RE_TYPEREF)
SYNT_RE_MODULEFROM_SYM = re.compile(
'(%s)(?:\s*\{\s*\}){0,1}(?:\s*,|\s{1,}FROM)' % _RE_WORD)
SYNT_RE_MODULEFROM_OID = re.compile(
'(%s)\s*|(\{[a-zA-Z0-9\(\)\-\s]{4,}\})\s*' % _RE_IDENT)
SYNT_RE_MODULEFROM_WIT = re.compile(
'WITH\s{1,}(SUCCESSORS|DESCENDANTS)\s*')
SYNT_RE_MODULEEXP = re.compile(
'(?:^|\s{1})EXPORTS((.|\n)*?);')
SYNT_RE_MODULEIMP = re.compile(
@ -804,16 +822,36 @@ def extract_set(text=''):
.format(valset)))
#------------------------------------------------------------------------------#
# following definitions are (yet) unused
#------------------------------------------------------------------------------#
def extract_from_import(text=''):
"""
extracts the module name, reference and / or OID set after a FROM import
statement, test `text` argument must start with the FROM keyword
returns a 2-tuple with
integer: length of the text containing the whole FROM statement
dict: with "name", "oid", "oidref" and "with" keys
"""
m = SYNT_RE_MODULEFROM.match(text)
assert(m)
cur = m.end()
ret = {'name': m.group(1), 'oid': None, 'oidref': None, 'with': None}
# check if we stop or continue with an OID value or OID reference
if SYNT_RE_MODULEFROM_SYM.match(text[cur:]) or not text[cur:]:
return cur, ret
m = SYNT_RE_MODULEFROM_OID.match(text[cur:])
assert(m)
cur += m.end()
assert(None in m.groups())
if m.group(1):
ret['oidref'] = m.group(1)
else:
ret['oid'] = m.group(2)
# check if there is a final WITH stmt
m = SYNT_RE_MODULEFROM_WIT.match(text[cur:])
if m:
ret['with'] = m.group(1)
cur += m.end()
# final control
assert(SYNT_RE_MODULEFROM_SYM.match(text[cur:]) or not text[cur:])
return cur, ret
#------------------------------------------------------------------------------#
# class syntax processing routines
#------------------------------------------------------------------------------#
def class_syntax_gidbl(gidbl, gidcur):
for gid in gidbl:
if gid == gidcur[:len(gid)]:
return True
return False