Permalink
Browse files

refactoring: organize methods in Rule::Position; added setup_lr metho…

…d in LREntry to describe what is doing
  • Loading branch information...
1 parent ef85d9f commit 181e8186f01e31adab80918371c566c17c570b2a @xli committed Aug 19, 2011
Showing with 62 additions and 61 deletions.
  1. +62 −61 lib/parslet/atoms/rule.rb
View
@@ -8,10 +8,13 @@ def error?
class LREntry < Struct.new(:lr, :pos, :context)
def answer
+ setup_lr
+ self.lr.seed
+ end
+ def setup_lr
self.lr.ensure_head do |head|
context.lr_stack.mark_involved_lrs(head)
end
- self.lr.seed
end
end
@@ -23,7 +26,6 @@ def head_rule?(rule)
def ensure_head(&block)
yield(self.head ||= Head.new(rule, [], []))
end
-
end
class Head < Struct.new(:rule, :involved_rules, :eval_rules)
@@ -43,6 +45,10 @@ def eval?(rule)
def exclude_eval_rule!(rule)
eval_rules.delete(rule)
end
+
+ def reset_eval_rules
+ self.eval_rules = self.involved_rules.dup
+ end
end
# Update/fetch parsed entry at a given position in source
@@ -73,76 +79,71 @@ def pop_lr_stack
context.lr_stack.pop
end
end
- include Context
- def apply_rule
- recall || eval_rule_body_with_lr_support
- end
-
- # Eval rule body with LR supported by
- # placing a LR flag before eval rule body
- # and growing LR seed after detected LR
- def eval_rule_body_with_lr_support
- with_lr_flag { self.entry = eval_rule_body }
- self.entry
- end
-
- def eval_rule_body
- rewind
- answer = rule.eval_rule_body(source, context)
- MemoEntry.new(answer, source.pos)
- end
-
- private
- def rewind
- source.pos = self.pos
- end
+ module LRSupport
+ def recall
+ # if not growing a seed parse, just return what is stored
+ # in the memo table
+ return self.entry if self.head.nil?
+ # do not evaluate any rule that is not involved in this
+ # left recursion
+ # question: why self.entry.nil?
+ if self.entry.nil? && !self.head.involved?(self.rule)
+ return fail('not involved in head left recursion')
+ end
+
+ # allow involved rules to be evaluated, but only once
+ # during a seed-growing iteration
+ if self.head.eval?(self.rule)
+ self.head.exclude_eval_rule!(self.rule)
+ self.entry = self.eval_rule_body
+ end
+ self.entry
+ end
- def fail(message)
- MemoEntry.new(rule.error(source, message), source.pos)
- end
+ def with_lr_flag
+ lr = LR.new(rule.error(source, 'left recursion detected'), self.rule)
+ push_into_lr_stack(lr)
+ self.entry = LREntry.new lr, self.pos, context
+ yield
+ pop_lr_stack
+ if !self.entry.error? && lr.head_rule?(rule)
+ grow_lr(lr.head)
+ end
+ self.entry
+ end
- def recall
- # if not growing a seed parse, just return what is stored
- # in the memo table
- return self.entry if self.head.nil?
- # do not evaluate any rule that is not involved in this
- # left recursion
- # question: why self.entry.nil?
- if self.entry.nil? && !self.head.involved?(self.rule)
- return fail('not involved in head left recursion')
+ # Tries to grow the parse of rule at given position
+ def grow_lr(h)
+ self.head = h
+ loop do
+ h.reset_eval_rules
+ entry = eval_rule_body
+ break if entry.error? || entry.pos <= self.entry.pos
+ self.entry = entry
+ end
+ self.head = nil
end
- # allow involved rules to be evaluated, but only once
- # during a seed-growing iteration
- if self.head.eval?(self.rule)
- self.head.exclude_eval_rule!(self.rule)
- self.entry = self.eval_rule_body
+ def fail(message)
+ MemoEntry.new(rule.error(source, message), source.pos)
end
- self.entry
end
- def with_lr_flag
- lr = LR.new(rule.error(source, 'left recursion detected'), self.rule)
- push_into_lr_stack(lr)
- self.entry = LREntry.new lr, self.pos, context
- yield
- pop_lr_stack
+ include Context
+ include LRSupport
- return if self.entry.error?
- grow_lr(lr.head) if lr.head_rule?(rule)
+ def apply_rule
+ # Eval rule body with LR supported by
+ # placing a LR flag before eval rule body
+ # and growing LR seed after detected LR
+ recall || with_lr_flag { self.entry = eval_rule_body }
end
- # Tries to grow the parse of rule at given position
- def grow_lr(h)
- self.head = h
- loop do
- h.eval_rules = h.involved_rules.dup
- entry = eval_rule_body
- break if entry.error? || entry.pos <= self.entry.pos
- self.entry = entry
- end
- self.head = nil
+ def eval_rule_body
+ source.pos = self.pos
+ answer = rule.eval_rule_body(source, context)
+ MemoEntry.new(answer, source.pos)
end
end

0 comments on commit 181e818

Please sign in to comment.