2 @brief This is the APG command line parser grammar generator.
3 It takes an input SABNF grammar syntax and generates a
4 grammar object suitable for use with a Python APG parser.
7 -h, --help show this help message and exit
8 -i INPUT, --input INPUT
9 the input SABNF source file name (see note 1)
10 -o OUTPUT, --output OUTPUT
11 the output grammar file name (see note 2)
12 -v, --version display the version and copyright information
13 -s, --strict allow only strict ABNF (RFC5234 & RFC7405) syntax
14 --dry-run inhibits output file generation
15 -dr, --display-rules display the grammar rule and UDT(if any) names
16 -dd, --display-rule-dependencies
17 for each rule, display the rules it references and all rules referring to it
18 -da, --display-rule-attributes
19 for each rule, display the rule attributes (left-recursive, etc.)
20 --index if specified, rules are displayed by index(the order they appear in the grammar), otherwise alphabetically
22 NOTES: 1) Multiple input files can be specified with by comma-separated names. The files will be concatenated in the order in which they appear. 2) The output file name is
23 optional. If no output name is specified the first input name will be stripped of its extension, if any, and the extension ".py" added.
29 sys.path.append(os.getcwd())
37 '''Get the list of input file names, open them and concatenate the files.
38 Construct the default output file name from the first input name.'''
40 names = file_names.split(
',')
41 name_range = range(
len(names))
43 names[i] = names[i].replace(
' ',
'')
51 dir_name = os.path.dirname(names[0])
52 base_name = os.path.basename(names[0])
53 exts = base_name.split(
'.')
60 for i
in range(1, len_exts - 1):
61 base_name +=
'.' + exts[i]
62 default_output = dir_name + os.path.sep + base_name +
'.py'
63 return {
'source': source,
'default_output': default_output}
67 This is Python APG - an ABNF Parser Generator.
68 It generates a grammar object from a superset of ABNF(SABNF)
69 suitable for use with the APG parser.
71 ep =
'''NOTES: 1) Multiple input files can be specified with by
72 comma-separated names.
73 The files will be concatenated in the order in which they appear.
74 2) The output file name is optional. If no output name is specified
75 the first input name will be stripped of its extension, if any,
76 and the extension ".py" added.
81 parser = argparse.ArgumentParser(
89 help=
'the input SABNF source file name (see note 1)',
93 parser.add_argument(
'-o',
'--output',
94 help=
'the output grammar file name (see note 2)',
97 parser.add_argument(
'-v',
'--version',
98 help=
'display the version and copyright information',
101 parser.add_argument(
'-s',
'--strict',
102 help=
'allow only strict ABNF (RFC5234 & RFC7405) syntax',
105 parser.add_argument(
'--dry-run',
106 help=
'inhibits output file generation',
112 help=
'display the grammar rule and UDT(if any) names',
113 dest=
'display_rules',
115 hlp =
'for each rule, display the rules it references '
116 hlp +=
'and all rules referring to it'
119 '--display-rule-dependencies',
121 dest=
'display_dependencies',
125 '--display-rule-attributes',
126 help=
'for each rule, display the rule attributes (left-recursive, etc.)',
127 dest=
'display_attributes',
129 hlp =
'if specified, rules are displayed by index'
130 hlp +=
'(the order they appear in the grammar), '
131 hlp +=
'otherwise alphabetically'
137 args = parser.parse_args()
141 text =
'Python APG version 1.0'
142 text +=
'\nCopyright (c) 2022 Lowell D. Thomas'
148 print(
'--input argument required.', end=
' ')
149 print(
'Use --help for options and descriptions.')
157 api.generate(result[
'source'], args.strict)
159 print(
'\nGRAMMAR ERRORS')
160 print(api.display_errors())
162 print(
'ANNOTATED GRAMMAR')
163 print(api.display_grammar())
166 if(args.display_rules):
170 print(
'\nGRAMMAR RULES')
171 print(api.display_rules(sort_type))
173 if(args.display_dependencies):
177 print(
'\nRULE DEPENDENCIES')
178 print(api.display_rule_dependencies(sort_type))
180 if(args.display_attributes):
184 print(
'\nRULE ATTRIBUTES')
185 print(api.display_rule_attributes(sort_type))
187 if(
not args.dry_run):
188 outname = args.output if(args.output)
else result[
'default_output']
189 api.write_grammar(outname)
190 print(
'grammar object written to file ' + outname)
def get_source(file_names)
Get the list of input file names, open them and concatenate the files.