Skip to content

Commit 25ca2a7

Browse files
committed
make Python Part21 lexer more extensible for writing custom parser rules
1 parent a80489d commit 25ca2a7

1 file changed

Lines changed: 18 additions & 14 deletions

File tree

src/exp2python/python/SCL/Part21.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -46,22 +46,23 @@
4646
# Common Code for Lexer / Parser
4747
####################################################################################################
4848
class Base:
49-
tokens = ('INTEGER', 'REAL', 'USER_DEFINED_KEYWORD', 'STANDARD_KEYWORD', 'STRING', 'BINARY',
49+
tokens = ['INTEGER', 'REAL', 'USER_DEFINED_KEYWORD', 'STANDARD_KEYWORD', 'STRING', 'BINARY',
5050
'ENTITY_INSTANCE_NAME', 'ENUMERATION', 'PART21_END', 'PART21_START', 'HEADER_SEC',
51-
'ENDSEC', 'DATA_SEC')
51+
'ENDSEC', 'DATA_SEC']
5252

5353
####################################################################################################
5454
# Lexer
5555
####################################################################################################
5656
class Lexer(Base):
57-
def __init__(self, debug=0, optimize=0, compatibility_mode=False, header_limit=1024):
58-
self.lexer = lex.lex(module=self, debug=debug, debuglog=logger, optimize=optimize,
59-
errorlog=logger)
60-
self.entity_keywords = []
57+
states = (('compatibility', 'inclusive'),)
58+
59+
def __init__(self, debug=0, optimize=0, compatibility_mode=False, header_limit=1024, extra_tokens=None):
60+
if extra_tokens: self.tokens += extra_tokens
61+
self.entity_mapping = {}
6162
self.compatibility_mode = compatibility_mode
6263
self.header_limit = header_limit
63-
64-
states = (('compatibility', 'inclusive'),)
64+
self.lexer = lex.lex(module=self, debug=debug, debuglog=logger, optimize=optimize,
65+
errorlog=logger)
6566

6667
def __getattr__(self, name):
6768
if name == 'lineno':
@@ -90,7 +91,10 @@ def token(self):
9091
return None
9192

9293
def register_entities(self, entities):
93-
self.entity_keywords.extend(entities)
94+
if isinstance(entities, list):
95+
entities = {k: k for k in entities}
96+
97+
self.entity_mapping.update(entities)
9498

9599
# Comment (ignored)
96100
def t_ANY_COMMENT(self, t):
@@ -115,24 +119,24 @@ def t_ANY_ENDSEC(self, t):
115119

116120
# Keywords
117121
def t_compatibility_STANDARD_KEYWORD(self, t):
118-
r'(?:!|)[A-Z_][0-9A-Za-z_]*'
122+
r'(?:!|)[A-Za-z_][0-9A-Za-z_]*'
119123
t.value = t.value.upper()
120124
if t.value == 'DATA':
121125
t.type = 'DATA_SEC'
126+
elif t.value in self.entity_mapping:
127+
t.type = self.entity_mapping[t.value]
122128
elif t.value.startswith('!'):
123129
t.type = 'USER_DEFINED_KEYWORD'
124-
elif t.value in self.entity_keywords:
125-
t.type = t.value
126130
return t
127131

128132
def t_ANY_STANDARD_KEYWORD(self, t):
129133
r'(?:!|)[A-Z_][0-9A-Z_]*'
130134
if t.value == 'DATA':
131135
t.type = 'DATA_SEC'
136+
elif t.value in self.entity_mapping:
137+
t.type = self.entity_mapping[t.value]
132138
elif t.value.startswith('!'):
133139
t.type = 'USER_DEFINED_KEYWORD'
134-
elif t.value in self.entity_keywords:
135-
t.type = t.value
136140
return t
137141

138142
def t_ANY_newline(self, t):

0 commit comments

Comments
 (0)