diff --git a/actionpack/lib/action_dispatch/journey/gtg/builder.rb b/actionpack/lib/action_dispatch/journey/gtg/builder.rb index 2600e7fb70..3a5f81ab45 100644 --- a/actionpack/lib/action_dispatch/journey/gtg/builder.rb +++ b/actionpack/lib/action_dispatch/journey/gtg/builder.rb @@ -13,45 +13,44 @@ module ActionDispatch def initialize(root) @root = root @ast = Nodes::Cat.new root, DUMMY - @followpos = nil + @followpos = build_followpos end def transition_table dtrans = TransitionTable.new marked = {} state_id = Hash.new { |h, k| h[k] = h.length } + dstates = [firstpos(root)] - start = firstpos(root) - dstates = [start] until dstates.empty? s = dstates.shift next if marked[s] marked[s] = true # mark s s.group_by { |state| symbol(state) }.each do |sym, ps| - u = ps.flat_map { |l| followpos(l) } + u = ps.flat_map { |l| @followpos[l] } next if u.empty? - if u.uniq == [DUMMY] - from = state_id[s] + from = state_id[s] + + if u.all? { |pos| pos == DUMMY } to = state_id[Object.new] dtrans[from, to] = sym - dtrans.add_accepting(to) + ps.each { |state| dtrans.add_memo(to, state.memo) } else - dtrans[state_id[s], state_id[u]] = sym + to = state_id[u] + dtrans[from, to] = sym if u.include?(DUMMY) - to = state_id[u] + ps.each do |state| + if @followpos[state].include?(DUMMY) + dtrans.add_memo(to, state.memo) + end + end - accepting = ps.find_all { |l| followpos(l).include?(DUMMY) } - - accepting.each { |accepting_state| - dtrans.add_memo(to, accepting_state.memo) - } - - dtrans.add_accepting(state_id[u]) + dtrans.add_accepting(to) end end @@ -92,7 +91,7 @@ module ActionDispatch firstpos(node.left) end when Nodes::Or - node.children.flat_map { |c| firstpos(c) }.uniq + node.children.flat_map { |c| firstpos(c) }.tap(&:uniq!) when Nodes::Unary firstpos(node.left) when Nodes::Terminal @@ -107,7 +106,7 @@ module ActionDispatch when Nodes::Star firstpos(node.left) when Nodes::Or - node.children.flat_map { |c| lastpos(c) }.uniq + node.children.flat_map { |c| lastpos(c) }.tap(&:uniq!) when Nodes::Cat if nullable?(node.right) lastpos(node.left) | lastpos(node.right) @@ -123,15 +122,7 @@ module ActionDispatch end end - def followpos(node) - followpos_table[node] - end - private - def followpos_table - @followpos ||= build_followpos - end - def build_followpos table = Hash.new { |h, k| h[k] = [] } @ast.each do |n| @@ -150,12 +141,7 @@ module ActionDispatch end def symbol(edge) - case edge - when Journey::Nodes::Symbol - edge.regexp - else - edge.left - end + edge.symbol? ? edge.regexp : edge.left end end end