Version 1.0
Copyright © 2022 Lowell D. Thomas
Python APG
 … an ABNF Parser Generator
udts.py
Go to the documentation of this file.
1 ''' @file examples/basics/udts.py
2 @brief Example of using User-Defined Terminals (UDTs).
3 
4 A well-known non-context free language is
5 [L ={a<sup>n</sup>b<sup>n</sup>c<sup>n</sup> | n>0}]
6 (https://en.wikipedia.org/wiki/Syntactic_predicate).
7 It is shown there how to parse this using look ahead operators
8 and that will be demonstrated in the look ahead example,
9 @ref examples/basics/look_ahead.py.
10 Here, we demonstrate a more brute-force method - namely
11 simply hand writting a code snippet to match the language.
12 '''
13 import sys
14 import os
15 # add the current working directory to the path
16 # DO NOT MOVE THE FOLLOWING STATEMENT
17 # if using autopep8 formatter, for example, set argument '--ignore=E402'
18 sys.path.append(os.getcwd())
19 from apg_py.lib import utilities as utils
20 from apg_py.lib import identifiers as id
21 from apg_py.lib.parser import Parser
22 from apg_py.api.api import Api
23 
24 
25 def anbncn(cb_data):
26  # the UDT callback function
27  # default to failure - NOMATCH
28  cb_data['state'] = id.NOMATCH
29  cb_data['phrase_length'] = 0
30  na = 0
31  nb = 0
32  nc = 0
33  for i in range(cb_data['phrase_index'], cb_data['sub_end']):
34  if(cb_data['input'][i] == 97):
35  na += 1
36  else:
37  break
38  if(na == 0):
39  return
40  for i in range(cb_data['phrase_index'] + na, cb_data['sub_end']):
41  if(cb_data['input'][i] == 98):
42  nb += 1
43  else:
44  break
45  if(nb != na):
46  return
47  for i in range(cb_data['phrase_index'] + na + nb, cb_data['sub_end']):
48  if(cb_data['input'][i] == 99):
49  nc += 1
50  else:
51  break
52  if(nc != na):
53  return
54  # success
55  cb_data['state'] = id.MATCH
56  cb_data['phrase_length'] = na + nb + nc
57 
58 
59 title = '''Demonstrate the use of User-Defined Terminals (UDTs).
60 These are handwritten code snippets for matching
61 difficult to express or non-context-free phrases.
62 '''
63 print()
64 print(title)
65 
66 # the SABNF syntax
67 abnf_syntax = 'S = u_anbncn\n'
68 
69 # construct the grammar object
70 api = Api()
71 grammar = api.generate(abnf_syntax)
72 if(api.errors):
73  # report any errors
74  print('\n1) Grammar Errors')
75  print(api.display_errors())
76 else:
77  # parse a string that matches the language
78  parser = Parser(grammar)
79  parser.add_callbacks({'u_anbncn': anbncn})
80  input_string = 'aaabbbccc'
81  result = parser.parse(utils.string_to_tuple(input_string))
82  print('\n1) Parser Result - input = "' + input_string + '"')
83  print(result)
84 
85  # parse a string that does not match the language
86  input_string = 'aaabbbcc'
87  result = parser.parse(utils.string_to_tuple(input_string))
88  print('\n2) Parser Result - input = "' + input_string + '"')
89  print(result)
The API class.
Definition: api.py:61
The Parser class for parsing an APG grammar.
Definition: parser.py:60
def anbncn(cb_data)
Definition: udts.py:25
Python APG, Version 1.0, is licensed under the 2-Clause BSD License,
an Open Source Initiative Approved License.