Skip to content

Commit 4515ffc

Browse files
committed
improvements to error handling
* Lexer now has a compatibility mode for entity names not all in uppercase * Lexer now takes an extra argument header_limit, input is searched for valid start point, extra text up to header_limit is ignored.
1 parent 4e90ff6 commit 4515ffc

1 file changed

Lines changed: 62 additions & 24 deletions

File tree

src/exp2python/python/SCL/Part21.py

Lines changed: 62 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,10 +54,14 @@ class Base:
5454
# Lexer
5555
####################################################################################################
5656
class Lexer(Base):
57-
def __init__(self, debug=0, optimize=0):
57+
def __init__(self, debug=0, optimize=0, compatibility_mode=False, header_limit=1024):
5858
self.lexer = lex.lex(module=self, debug=debug, debuglog=logger, optimize=optimize,
5959
errorlog=logger)
6060
self.entity_keywords = []
61+
self.compatibility_mode = compatibility_mode
62+
self.header_limit = header_limit
63+
64+
states = (('compatibility', 'inclusive'),)
6165

6266
def __getattr__(self, name):
6367
if name == 'lineno':
@@ -68,8 +72,17 @@ def __getattr__(self, name):
6872
raise AttributeError
6973

7074
def input(self, s):
71-
self.lexer.input(s)
72-
75+
startidx = s.find('ISO-10303-21;', 0, self.header_limit)
76+
if startidx == -1:
77+
sys.exit('Aborting... ISO-10303-21; header not found')
78+
self.lexer.input(s[startidx:])
79+
self.lexer.lineno += s[0:startidx].count('\n')
80+
81+
if self.compatibility_mode:
82+
self.lexer.begin('compatibility')
83+
else:
84+
self.lexer.begin('INITIAL')
85+
7386
def token(self):
7487
try:
7588
return next(self.lexer)
@@ -80,29 +93,39 @@ def register_entities(self, entities):
8093
self.entity_keywords.extend(entities)
8194

8295
# Comment (ignored)
83-
def t_COMMENT(self, t):
96+
def t_ANY_COMMENT(self, t):
8497
r'/\*(.|\n)*?\*/'
8598
t.lexer.lineno += t.value.count('\n')
8699

87-
def t_PART21_START(self, t):
100+
def t_ANY_PART21_START(self, t):
88101
r'ISO-10303-21;'
89102
return t
90103

91-
def t_PART21_END(self, t):
104+
def t_ANY_PART21_END(self, t):
92105
r'END-ISO-10303-21;'
93106
return t
94107

95-
def t_HEADER_SEC(self, t):
108+
def t_ANY_HEADER_SEC(self, t):
96109
r'HEADER;'
97110
return t
98111

99-
def t_ENDSEC(self, t):
112+
def t_ANY_ENDSEC(self, t):
100113
r'ENDSEC;'
101114
return t
102115

103116
# Keywords
104-
# TODO: provide a hook for entity validation i.e. t.value in list_of_entities_for_AP###
105-
def t_STANDARD_KEYWORD(self, t):
117+
def t_compatibility_STANDARD_KEYWORD(self, t):
118+
r'(?:!|)[A-Z_][0-9A-Za-z_]*'
119+
t.value = t.value.upper()
120+
if t.value == 'DATA':
121+
t.type = 'DATA_SEC'
122+
elif t.value.startswith('!'):
123+
t.type = 'USER_DEFINED_KEYWORD'
124+
elif t.value in self.entity_keywords:
125+
t.type = t.value
126+
return t
127+
128+
def t_ANY_STANDARD_KEYWORD(self, t):
106129
r'(?:!|)[A-Z_][0-9A-Z_]*'
107130
if t.value == 'DATA':
108131
t.type = 'DATA_SEC'
@@ -112,24 +135,22 @@ def t_STANDARD_KEYWORD(self, t):
112135
t.type = t.value
113136
return t
114137

115-
def t_newline(self, t):
138+
def t_ANY_newline(self, t):
116139
r'\n+'
117140
t.lexer.lineno += len(t.value)
118141

119142
# Simple Data Types
120-
t_REAL = r'[+-]*[0-9][0-9]*\.[0-9]*(?:E[+-]*[0-9][0-9]*)?'
121-
t_INTEGER = r'[+-]*[0-9][0-9]*'
122-
t_STRING = r"'(?:[][!\"*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_\\ ]|'')*'"
123-
t_BINARY = r'"[0-3][0-9A-F]*"'
124-
t_ENTITY_INSTANCE_NAME = r'\#[0-9]+'
125-
t_ENUMERATION = r'\.[A-Z_][A-Z0-9_]*\.'
143+
t_ANY_REAL = r'[+-]*[0-9][0-9]*\.[0-9]*(?:E[+-]*[0-9][0-9]*)?'
144+
t_ANY_INTEGER = r'[+-]*[0-9][0-9]*'
145+
t_ANY_STRING = r"'(?:[][!\"*$%&.#+,\-()?/:;<=>@{}|^`~0-9a-zA-Z_\\ ]|'')*'"
146+
t_ANY_BINARY = r'"[0-3][0-9A-F]*"'
147+
t_ANY_ENTITY_INSTANCE_NAME = r'\#[0-9]+'
148+
t_ANY_ENUMERATION = r'\.[A-Z_][A-Z0-9_]*\.'
126149

127150
# Punctuation
128151
literals = '()=;,*$'
129152

130-
# TODO: is it okay to ignore \n?
131-
t_ignore = ' \t'
132-
153+
t_ANY_ignore = ' \t'
133154

134155

135156
####################################################################################################
@@ -324,17 +345,34 @@ def p_empty(self, p):
324345
"""empty :"""
325346
pass
326347

348+
def test_debug():
349+
logging.basicConfig()
350+
logger.setLevel(logging.DEBUG)
351+
352+
s = open('io1-tu-203.stp', 'r').read()
353+
parser = Parser()
354+
355+
try:
356+
r = parser.parse(s, debug=1)
357+
except SystemExit:
358+
pass
359+
360+
return (parser, r)
327361

328362
def test():
329363
logging.basicConfig()
330364
logger.setLevel(logging.ERROR)
331365

332366
s = open('io1-tu-203.stp', 'r').read()
333-
parser = Parser(debug=1)
367+
parser = Parser()
368+
369+
try:
370+
r = parser.parse(s)
371+
except SystemExit:
372+
pass
373+
374+
return (parser, r)
334375

335-
r = parser.parse(s, debug=1)
336-
#r = parser.parse(s)
337-
return r
338376

339377
if __name__ == '__main__':
340378
test()

0 commit comments

Comments
 (0)