Index: tools/lexer_generator/code_generator.py |
diff --git a/tools/lexer_generator/code_generator.py b/tools/lexer_generator/code_generator.py |
index a3bb21d24da6046d8ea2d40c37594353dfd21d55..d806f1cf780e204417c5bb8a49b408bbdf52566e 100644 |
--- a/tools/lexer_generator/code_generator.py |
+++ b/tools/lexer_generator/code_generator.py |
@@ -52,14 +52,58 @@ class CodeGenerator: |
return code |
@staticmethod |
- def dfa_state_to_code(state, start_node_number): |
+ def __terminate_code(value): |
+ assert value == None |
+ return 'PUSH_TOKEN(Token::EOS); return 0;' |
+ |
+ @staticmethod |
+ def __terminate_illegal_code(value): |
+ assert value == None |
+ return 'PUSH_TOKEN(Token::ILLEGAL); return 1;' |
+ |
+ @staticmethod |
+ def __skip_code(value): |
+ assert value == None |
+ return 'SKIP(); goto code_start;' |
+ |
+ @staticmethod |
+ def __push_line_terminator_code(value): |
+ assert value == None |
+ return 'PUSH_LINE_TERMINATOR();' |
+ |
+ @staticmethod |
+ def __push_token_code(value): |
+ assert value != None |
+ return 'PUSH_TOKEN(Token::%s);' % value |
+ |
+ @staticmethod |
+ def __code_code(value): |
+ assert value != None |
+ return '%s\n' % value |
+ |
+ def __init__(self, dfa, default_action): |
+ self.__dfa = dfa |
+ self.__start_node_number = dfa.start_state().node_number() |
+ self.__default_action = default_action |
+ # make this better |
+ self.__action_code_map = { |
+ "terminate" : self.__terminate_code, |
+ "terminate_illegal" : self.__terminate_illegal_code, |
+ "push_token" : self.__push_token_code, |
+ "push_line_terminator" : self.__push_line_terminator_code, |
+ "skip" : self.__skip_code, |
+ "code" : self.__code_code, |
+ } |
+ |
+ def __dfa_state_to_code(self, state): |
+ start_node_number = self.__start_node_number |
# FIXME: add different check types (if, switch, lookup table) |
# FIXME: add action + break / continue |
# FIXME: add default action |
code = '' |
if start_node_number == state.node_number(): |
code += ''' |
-//code_start: |
+code_start: |
''' |
code += ''' |
code_%s: |
@@ -69,26 +113,9 @@ code_%s: |
entry_action = state.action().entry_action() if state.action() else None |
match_action = state.action().match_action() if state.action() else None |
- print entry_action |
- |
- if (entry_action and entry_action[0] != 'terminate' and |
- entry_action[0] != 'terminate_illegal' and entry_action[0] != 'code' and |
- entry_action[0] != 'push_token' and |
- entry_action[0] != 'push_line_terminator' and entry_action[0] != 'skip'): |
- raise Exception("unknown type %s" % entry_action[0]) |
if entry_action: |
- if entry_action[0] == 'terminate': |
- code += 'PUSH_TOKEN(Token::EOS); return 0;' |
- return code |
- elif entry_action[0] == 'terminate_illegal': |
- code += 'PUSH_TOKEN(Token::ILLEGAL); return 1;' |
- return code |
- elif entry_action[0] == 'skip': |
- code += 'SKIP(); goto code_start;' |
- return code |
- elif entry_action[0] == 'code': |
- code += '%s\n' % entry_action[1] |
+ code += self.__action_code_map[entry_action[0]](entry_action[1]) |
code += ''' |
//fprintf(stderr, "char at hand is %c (%d)\\n", yych, yych);\n''' |
@@ -102,20 +129,16 @@ code_%s: |
''' % s.node_number() |
if match_action: |
- if match_action[0] == 'push_token': |
- content = 'PUSH_TOKEN(Token::%s);' % match_action[1] |
- code += '%s\ngoto code_%s;\n' % (content, |
- start_node_number) |
- code += " // FIXME: goto where" |
+ code += self.__action_code_map[match_action[0]](match_action[1]) |
+ code += 'goto code_%s;\n' % start_node_number |
+ else: |
+ code += " // FIXME: goto where" |
return code |
- @staticmethod |
- def rule_processor_to_code(rule_processor, use_mdfa): |
- if use_mdfa: |
- dfa = rule_processor.default_automata().minimal_dfa() |
- else: |
- dfa = rule_processor.default_automata().dfa() |
- start_node_number = dfa.start_state().node_number() |
+ def __process(self): |
+ dfa = self.__dfa |
+ default_action = self.__default_action |
+ start_node_number = self.__start_node_number |
code = ''' |
#include "lexer/even-more-experimental-scanner.h" |
@@ -126,12 +149,12 @@ uint32_t EvenMoreExperimentalScanner::DoLex() { |
goto code_%s; |
''' % start_node_number |
def f(state, code): |
- code += CodeGenerator.dfa_state_to_code(state, start_node_number) |
+ code += self.__dfa_state_to_code(state) |
return code |
code = dfa.visit_all_states(f, code) |
default_action_code = '' |
- action = rule_processor.default_action.entry_action() if rule_processor.default_action else None |
+ action = default_action.entry_action() if default_action else None |
if action: |
if action[0] == 'push_token': |
default_action_code = ''' |
@@ -139,7 +162,7 @@ default_action: |
//fprintf(stderr, "default action\\n"); |
PUSH_TOKEN(Token::%s); |
FORWARD(); |
- goto code_%s;''' % (rule_processor.default_action.data(), start_node_number) |
+ goto code_%s;''' % (default_action, start_node_number) |
else: |
raise Exception("Default action type %s not supported" % action[0]) |
@@ -153,3 +176,11 @@ default_action: |
} |
''' % default_action_code |
return code |
+ |
+ @staticmethod |
+ def rule_processor_to_code(rule_processor, use_mdfa): |
+ if use_mdfa: |
+ dfa = rule_processor.default_automata().minimal_dfa() |
+ else: |
+ dfa = rule_processor.default_automata().dfa() |
+ return CodeGenerator(dfa, rule_processor.default_action).__process() |