Version 1.0
Copyright © 2022 Lowell D. Thomas
Python APG
… an
A
BNF
P
arser
G
enerator
Main Page
Related Pages
Packages
Packages
Package Functions
All
a
b
c
d
e
f
g
h
i
k
l
m
n
p
r
s
t
u
v
x
Functions
a
b
c
d
e
f
g
h
i
k
l
m
n
p
r
s
t
u
v
x
Variables
a
b
c
d
e
f
g
h
i
k
l
m
n
p
r
s
t
u
v
Classes
Class List
Class Index
Class Members
All
_
a
b
c
d
e
f
g
h
i
l
m
n
o
p
r
s
t
u
w
Functions
_
a
c
d
e
f
g
h
i
o
p
r
s
t
u
w
Variables
a
b
c
e
f
g
h
i
l
m
n
o
p
r
s
t
u
Files
File List
•
All
Classes
Namespaces
Files
Functions
Variables
Pages
examples
ini_file
ini_file.py
Go to the documentation of this file.
1
''' @file examples/ini_file/ini_file.py
2
@brief The ini file class for parsing an ini file into section/key/values.
3
'''
4
import
sys
5
import
os
6
from
pprint
import
pprint
7
# add the current working directory to the path
8
# DO NOT MOVE THE FOLLOWING STATEMENT
9
# if using autopep8 formatter, for example, set argument '--ignore=E402'
10
sys.path.append(os.getcwd())
11
from
apg_py.lib
import
utilities
as
utils
12
from
apg_py.lib.parser
import
Parser
13
# from apg.lib.trace import Trace
14
from
apg_py.lib.ast
import
Ast
15
import
examples.ini_file.grammar
as
grammar
16
import
examples.ini_file.parser_callbacks
as
pcb
17
import
examples.ini_file.ast_callbacks
as
acb
18
19
# Note: The ABNF syntax for the ini file parser is in grammar.abnf.
20
# The grammar object, grammar.py was generated with
21
# python3 apg.py -i examples/ini_file/grammar.abnf
22
23
24
class
IniFile
:
25
26
def
__init__
(self):
27
self.
__have_file
__have_file =
False
28
self.
__no_file
__no_file =
'Must first call IniFile.get_ini_file(file_name).'
29
30
def
help
(self):
31
display =
'''IniFile is a class for parsing and retrieving named values from an ini formatted file.
32
This format is similar to, but has some variations from, the WikiPedia description at
33
https://en.wikipedia.org/wiki/INI_file.
34
35
- Named values may be in an unnamed "global" section and/or in named sections.
36
- Each section consists of lines of key/value pairs.
37
- Section names are case sensitive and are alphanumeric with underscores.
38
- Section names are enclosed in square brackets and must begin in the first column of a line.
39
- Spaces are allowed, e.g. [ Section1 ]
40
- Keys are case sensitive and are alphanumeric with underscores.
41
- Values are multi-valued lists.
42
- Multiple occurrances of a section name will merge the two sections.
43
- Multiple occurrances of a key name within a section will merge the lists of values.
44
- Blank lines are ignored.
45
- Comments begin with a semicolon, ";", and continue to the end of the line.
46
- Values may be boolean, integers or strings.
47
- True booleans may be true or yes, case insensitive.
48
- False booleans may be false or no, case insensitive.
49
- Null values may be null or void, case insensitive.
50
- The keywords true, false, yes, no, null, void are reserved
51
and must be quoted if needed as strings.
52
- Strings with blanks characters must be single or double quoted.
53
- Escaped characters may be used within quoted or unquoted strings.
54
55
Escaped characters:
56
\\\\ single back slash, x5C
57
\\" double quote, x22
58
\\# hash or number sign, x23
59
\\' single quote, x27
60
\\, comma, x2C
61
\\: colon, x3A
62
\\; semicolon, x3B
63
\\= equal sign, x3D
64
\\b blank or space, x20
65
\\t tab, x09
66
\\n line feed, x0A
67
\\r carriage return, x0D
68
\\xhh hexadecimal character code, xhh, h = 0-9A-F
69
\\uhhhh Unicode character code, xhhhh, h = 0-9A-F
70
71
Example:
72
; the global section
73
url = 'https://en.wikipedia.org/wiki/INI_file'
74
IP = '198.162.1.1'
75
other = null
76
[section1] ; start section A
77
numbers = 1, 2,3, 4
78
use_them = yes
79
[ SectionB ] ; start section B
80
hamburgers = '$1.99', '$2.99', '$3.99'
81
[ section1 ] ; continue with section A
82
numbers = 5,6 ; add some more numbers to the list
83
84
'''
85
return
display
86
87
def
parse_ini_file
(self, fname):
88
fd = open(fname,
'r'
)
89
input = fd.read()
90
fd.close()
91
parser =
Parser
(grammar)
92
# Trace(parser, mode='dc')
93
parser.add_callbacks({
'line-end'
: pcb.line_end})
94
parser.add_callbacks({
'bad-section-line'
: pcb.bad_section_line})
95
parser.add_callbacks({
'bad-value-line'
: pcb.bad_value_line})
96
parser.add_callbacks({
'bad-blank-line'
: pcb.bad_blank_line})
97
ast =
Ast
(parser)
98
ast.add_callback(
'section-name'
, acb.section_name)
99
ast.add_callback(
'key-name'
, acb.key_name)
100
ast.add_callback(
'value'
, acb.value)
101
ast.add_callback(
'd-quoted-value'
, acb.d_value)
102
ast.add_callback(
's-quoted-value'
, acb.s_value)
103
ast.add_callback(
'string'
, acb.string_value)
104
ast.add_callback(
'true'
, acb.true_value)
105
ast.add_callback(
'false'
, acb.false_value)
106
ast.add_callback(
'null'
, acb.null_value)
107
ast.add_callback(
'number'
, acb.number_value)
108
data = {}
109
data[
'line_no'
] = 0
110
data[
'errors'
] = []
111
result = parser.parse(utils.string_to_tuple(input), user_data=data)
112
if(
not
result.success):
113
# ABNF syntax is designed so that this should never happen
114
raise
Exception(
'internal error - parser failed'
)
115
if(
len
(data[
'errors'
])):
116
# display errors
117
pprint(data[
'errors'
])
118
raise
Exception(
'ini file syntax errors found'
)
119
self.
__data
__data = {}
120
self.
__data
__data[
'current_section'
] =
None
121
self.
__data
__data[
'current_key'
] =
None
122
self.
__data
__data[
'global'
] = {}
123
self.
__data
__data[
'sections'
] = {}
124
ast.translate(self.
__data
__data)
125
self.
__have_file
__have_file =
True
126
# print()
127
# print('IniFile constructor')
128
# pprint(self.__data, sort_dicts=False)
129
130
def
get_keys
(self):
131
'''Get a list of the global key names.
132
@returns Returns a list, possibly empty, of global key names.
133
'''
134
if(
not
self.
__have_file
__have_file):
135
raise
Exception(self.
__no_file
__no_file)
136
keys = []
137
for
key, value
in
self.
__data
__data[
'global'
].items():
138
keys.append(key)
139
return
keys
140
141
def
get_values
(self, key):
142
'''Get the list of values for an global key name.
143
@param key The name of the key to get values for.
144
@returns Returns a list, possibly empty, of values.
145
'''
146
if(
not
self.
__have_file
__have_file):
147
raise
Exception(self.
__no_file
__no_file)
148
values = []
149
key_values = self.
__data
__data[
'global'
].get(key)
150
if(key_values):
151
for
value
in
key_values:
152
values.append(value)
153
return
values
154
155
def
get_sections
(self):
156
'''Get a list of the section names.
157
@returns Returns a list, possibly empty, of section names.
158
'''
159
if(
not
self.
__have_file
__have_file):
160
raise
Exception(self.
__no_file
__no_file)
161
sections = []
162
for
key, value
in
self.
__data
__data[
'sections'
].items():
163
sections.append(key)
164
return
sections
165
166
def
get_section_keys
(self, section):
167
'''Get a list of key names in the named section.
168
@param section The section name to find the key names in.
169
@returns Returns a list, possibly empty, of key names.
170
'''
171
if(
not
self.
__have_file
__have_file):
172
raise
Exception(self.
__no_file
__no_file)
173
keys = []
174
if(self.
__data
__data[
'sections'
].get(section)):
175
for
key, value
in
self.
__data
__data[
'sections'
][section].items():
176
keys.append(key)
177
return
keys
178
179
def
get_section_values
(self, section, key):
180
'''Get a list of values for the named key in the named section.
181
@param section The section name to find the key in.
182
@param key The key name to find the list of values for.
183
@returns Returns a list, possibly empty, of values.
184
'''
185
if(
not
self.
__have_file
__have_file):
186
raise
Exception(self.
__no_file
__no_file)
187
values = []
188
if(self.
__data
__data[
'sections'
].get(section)):
189
key_values = self.
__data
__data[
'sections'
][section].get(key)
190
if(key_values):
191
for
value
in
key_values:
192
values.append(value)
193
return
values
apg_py.lib.ast.Ast
A class for capturing the AST as the parser traverses the parse tree.
Definition:
ast.py:69
apg_py.lib.parser.Parser
The Parser class for parsing an APG grammar.
Definition:
parser.py:60
examples.ini_file.ini_file.IniFile
Definition:
ini_file.py:24
examples.ini_file.ini_file.IniFile.get_keys
def get_keys(self)
Get a list of the global key names.
Definition:
ini_file.py:130
examples.ini_file.ini_file.IniFile.get_values
def get_values(self, key)
Get the list of values for an global key name.
Definition:
ini_file.py:141
examples.ini_file.ini_file.IniFile.get_section_values
def get_section_values(self, section, key)
Get a list of values for the named key in the named section.
Definition:
ini_file.py:179
examples.ini_file.ini_file.IniFile.__have_file
__have_file
Definition:
ini_file.py:27
examples.ini_file.ini_file.IniFile.__init__
def __init__(self)
Definition:
ini_file.py:26
examples.ini_file.ini_file.IniFile.__data
__data
Definition:
ini_file.py:119
examples.ini_file.ini_file.IniFile.help
def help(self)
Definition:
ini_file.py:30
examples.ini_file.ini_file.IniFile.__no_file
__no_file
Definition:
ini_file.py:28
examples.ini_file.ini_file.IniFile.get_sections
def get_sections(self)
Get a list of the section names.
Definition:
ini_file.py:155
examples.ini_file.ini_file.IniFile.parse_ini_file
def parse_ini_file(self, fname)
Definition:
ini_file.py:87
examples.ini_file.ini_file.IniFile.get_section_keys
def get_section_keys(self, section)
Get a list of key names in the named section.
Definition:
ini_file.py:166
apg_py.lib.ast
Definition:
ast.py:1
apg_py.lib.parser
Definition:
parser.py:1
apg_py.lib
Definition:
__init__.py:1
examples.basics.substrings.len
int len
Definition:
substrings.py:27
examples.ini_file.ast_callbacks
Definition:
ast_callbacks.py:1
examples.ini_file.grammar
Definition:
grammar.py:1
examples.ini_file.parser_callbacks
Definition:
parser_callbacks.py:1
Generated by
1.9.1
Python APG, Version 1.0, is licensed under the
2-Clause BSD License
,
an
Open Source Initiative
Approved License.