mjackson / citrus

Parsing Expressions for Ruby

Home Page:http://mjackson.github.io/citrus

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

single item in rule body results in infinite loop.

sriram-srinivasan opened this issue · comments

The following code runs into an infinite loop when value is called.

grammar X
  rule item
      num {
        num.value 
      }
  end

  rule num 
     /[0-9]+/ {to_i * 1000}
  end
end
x = X.parse("100")
x.value 

It is likely that item.value and num.value are somehow conflated and that it calls itself.

The following does not have a problem.

grammar X
  rule item
      (n1:num ',' n2:num) {
        n1.value + n2.value
      }
  end

  rule num 
     /[0-9]+/ {to_i}
  end
end

x=X.parse("100,200")
x.value # no problem.

When you call num.value inside the semantic block, it will look for a match named num and take the value of it. In this case, the match named num is the match itself, which will simply call the block again, causing your loop. The thing is, you don't need a semantic block at all for the match contained in item as it is written in the first example. Consider the following ruby script:

require 'citrus'

Citrus.eval(<<CITRUS)
grammar X
  rule item
    num
  end

  rule num
    /[0-9]+/ {to_i * 1000}
  end
end
CITRUS

puts X.parse('5').value

When you call the value of an item match, it will simply return the value of its inner num match since item is merely an alias for num.

This is probably a bit too brief an example, but what I really wanted was to create a separate ast node from "item", and hide the fact that it called "num".

You can do that too. Try something like this:

require 'citrus'

Citrus.eval(<<CITRUS)
grammar X
  rule item
    num {super() - 1}
  end

  rule num
    /[0-9]+/ {to_i * 1000}
  end
end
CITRUS

puts X.parse('5').value

In this example, you can use super() to call the original num value. You can then modify the value to be whatever item wants it to be.