既然已经生成了DFA,按照之前的描述写出shift_reduction算法就不是什么了不起的工作了。
class Compiler
def initialize(rule_file, src_file)
@yacc = Yacc.new(rule_file)
@lex = ExtendLex.new(src_file)
@parse_stack = Array.new
end
def run
@yacc.generate
shift_reduction
end
def shift_reduction
@parse_stack.push(0)
token = @lex.get_next_token2
while true
action = @yacc.dfa.action(@parse_stack.last, token)
return false until action
action_id = action[0]
new_state = action[1]
case action_id
when DFA::SHIFT
@parse_stack.push(token)
@parse_stack.push(new_state)
token = @lex.get_next_token2
when DFA::REDUCE
rule = new_state[0].rule
eval(rule.action)
# pop 2 * rt.length
rindex = 0 - 2 * rule.rt.length
@parse_stack[rindex..-1] = nil
goto = @yacc.dfa.action(@parse_stack.last, rule.lt)
if goto
if goto[0] == DFA::SHIFT
@parse_stack.push(rule.lt)
@parse_stack.push(goto[1])
elsif goto[0] == DFA::ACCEPT
return true
end
else
return false
end
when DFA::ACCEPT
return true
end
end
end
end
class Compiler
def initialize(rule_file, src_file)
@yacc = Yacc.new(rule_file)
@lex = ExtendLex.new(src_file)
@parse_stack = Array.new
end
def run
@yacc.generate
shift_reduction
end
def shift_reduction
@parse_stack.push(0)
token = @lex.get_next_token2
while true
action = @yacc.dfa.action(@parse_stack.last, token)
return false until action
action_id = action[0]
new_state = action[1]
case action_id
when DFA::SHIFT
@parse_stack.push(token)
@parse_stack.push(new_state)
token = @lex.get_next_token2
when DFA::REDUCE
rule = new_state[0].rule
eval(rule.action)
# pop 2 * rt.length
rindex = 0 - 2 * rule.rt.length
@parse_stack[rindex..-1] = nil
goto = @yacc.dfa.action(@parse_stack.last, rule.lt)
if goto
if goto[0] == DFA::SHIFT
@parse_stack.push(rule.lt)
@parse_stack.push(goto[1])
elsif goto[0] == DFA::ACCEPT
return true
end
else
return false
end
when DFA::ACCEPT
return true
end
end
end
end