Version 1.0
Copyright © 2022 Lowell D. Thomas
Python APG
 … an ABNF Parser Generator
semantic.py
Go to the documentation of this file.
1 ''' @file apg_py/api/semantic.py
2 @brief Semantic translation of the SABNF AST.
3 
4 The AST is computed in the syntax phase (@ref syntax.py).
5 The AST is translated to generate all rules, UDTs and opcodes.
6 '''
7 from apg_py.lib import identifiers as id
8 
9 
10 def semantic(api):
11  '''Translate the AST, generating a list of rule objects,
12  and UDT objects, if any.
13  @param api The api object for the grammar syntax (@ref api.py)'''
14  data = {}
15  data['find_line'] = api.find_line
16  data['rules'] = []
17  data['udts'] = []
18  data['errors'] = []
19  data['rule_names'] = api.NameList()
20  data['udt_names'] = api.NameList()
21  api.ast.translate(data)
22  rules = data['rules']
24  return {
25  'errors': data['errors'],
26  'rules': rules,
27  'udts': data['udts'],
28  'rule_names': data['rule_names'],
29  'udt_names': data['udt_names']}
30 
31 
33  '''Opcodes ALT and CAT with only one child are redundant
34  and can be removed.
35  Opcodes REP with min = max = 1 are redundant and can be removed.
36  @param rules The grammar object rules.'''
37  for rule in rules:
38  i = 0
39  opcodes = rule['opcodes']
40  while(i < len(opcodes)):
41  i = check_for_removal(i, opcodes)
42  if(i < len(opcodes)):
43  del(opcodes[i])
44 
45 
46 def check_for_removal(i, opcodes):
47  '''Scan all opcodes and check for ALT, CAT and REP that can be removed.
48  @param i The opcode index of reference.
49  @param opcodes The list of opcodes for a given rule.
50  @returns Returns the number of remaining opcodes after removal.'''
51  for j in range(i, len(opcodes)):
52  opj = opcodes[j]
53  if(opj['type'] == id.ALT or opj['type'] == id.CAT):
54  if(len(opj['children']) == 1):
55  # remove this ALT, adjust other children indexes
56  adjust_children(j, opcodes)
57  return j
58  elif(opj['type'] == id.REP and opj['min'] == 1 and opj['max'] == 1):
59  adjust_children(j, opcodes)
60  return j
61  return len(opcodes)
62 
63 
64 def adjust_children(j, opcodes):
65  '''When an opcode is removed the indecies of the ALT and CAT children
66  must be corrected for the removed opcodes.
67  @param j The opcode index of reference.
68  @param opcodes The list of opcodes for a particular rule.'''
69  for op in opcodes:
70  if(op['type'] == id.ALT or op['type'] == id.CAT):
71  if(len(op['children'])):
72  for m in range(len(op['children'])):
73  if(op['children'][m] > j):
74  op['children'][m] -= 1
def check_for_removal(i, opcodes)
Scan all opcodes and check for ALT, CAT and REP that can be removed.
Definition: semantic.py:46
def adjust_children(j, opcodes)
When an opcode is removed the indecies of the ALT and CAT children must be corrected for the removed ...
Definition: semantic.py:64
def remove_redundant_opcodes(rules)
Opcodes ALT and CAT with only one child are redundant and can be removed.
Definition: semantic.py:32
def semantic(api)
Translate the AST, generating a list of rule objects, and UDT objects, if any.
Definition: semantic.py:10
Python APG, Version 1.0, is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.