Racc

Folks,

I need help using Racc. I've been trying to go through the basic calculator example, but no go. The grammar is processed without any shift-reduce conflicts. It appears I am feeding the wrong kind of tokens to it. I keep getting:

Parsing file:
/usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:377:in `on_error': (Racc::ParseError)
parse error on value 1 (NUMBER) from /usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:104:in `_racc_do_parse_c'
         from /usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:104:in `__send__'
         from /usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:104:in `do_parse'
         from racc-calc-2.y:47:in `parse'
         from ruby_calc_test.rb:20

I am feeding it tokens that are two-element arrays, as stated in the documentation. <http://i.loveruby.net/en/man/racc/parser.html> But it is not at all clear what should be in the second element.

tokens = [ [ :NUMBER, 1 ],
      [ :PLUS, "+" ],
      [ :NUMBER, 2 ],
      [ false, false ] ]

--Peter

···

--
There's neither heaven nor hell, save what we grant ourselves.
There's neither fairness nor justice, save what we grant each other.

-------- ruby_calc_test.rb --------
#!/usr/bin/ruby
require "FakeLexer"
require "RubyCalcParser"

## reuse the same parser object

p = RubyCalcParser.new
#p.yydebug = true
#p.yyerror = $stdout

print "Parsing file:\n"

tokens = [ [ :NUMBER, 1 ],
      [ :PLUS, "+" ],
      [ :NUMBER, 2 ],
      [ false, false ] ]

p.lexer = FakeLexer.new(tokens)
print(p.parse.inspect)

print "\n"
-------- racc-calc-2.y --------
class RubyCalcParser

prechigh
   left TIMES DIVIDE
   left PLUS MINUS
preclow

token NUMBER PLUS MINUS TIMES DIVIDE LPAREN RPAREN

rule

  exp: NUMBER { TestNumNode.new($1, "+") }
      > exp PLUS exp { TestBinaryOpNode.new($1, "+", $3) }
      > exp MINUS exp { TestBinaryOpNode.new($1, "-", $3) }
      > exp TIMES exp { TestBinaryOpNode.new($1, "*", $3) }
      > exp DIVIDE exp { TestBinaryOpNode.new($1, "/", $3) }
      > LPAREN exp RPAREN { TestExpNode.new($2) }
      > LPAREN error RPAREN { 1 } ## example error recovery--a bad expression is interpreted as a 1
  ;

end # RubyCalcParser

---- header ----
require 'RubyCalcAst'

---- inner ----

def initialize
  @ast = nil
end

attr_accessor :lexer ;

   def parse()
     return do_parse()
   end

protected

def next_token
     return @lexer.yylex()
end
-------- RubyCalcAst.rb --------
class TestNumNode
     def initialize(num, sign)
    @num = num
    @sign = sign
     end
end
class TestBinaryOpNode
  def initialize(term1, op, term2)
    @term1 = term1
    @op = op
    @term2 = term2
     end
end
class TestExpNode
     def initialize(exp)
    @exp = exp
     end
end
-------- FakeLexer.rb --------
require 'RubyCalcParser'

class FakeLexer

     def initialize(tokens)
    @tokens = tokens
    @index = 0
     end

     def reset()
    @index = 0
     end

     def yylex()
    rval = @tokens[@index]
    @index += @index
    return rval
     end

end
-------- end --------

Peter Suk wrote:

I need help using Racc. I've been trying to go through the basic
calculator example, but no go. The grammar is processed without any
shift-reduce conflicts. It appears I am feeding the wrong kind of
tokens to it. I keep getting:

Parsing file:
/usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:377:in `on_error':
(Racc::ParseError)
parse error on value 1 (NUMBER) from
/usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:104:in `_racc_do_parse_c'
        from /usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:104:in
`__send__'
        from /usr/local/lib/ruby/site_ruby/1.8/racc/parser.rb:104:in
`do_parse'
        from racc-calc-2.y:47:in `parse'
        from ruby_calc_test.rb:20

That means there's no rule that matches the input.

I am feeding it tokens that are two-element arrays, as stated in the
documentation. <http://i.loveruby.net/en/man/racc/parser.html&gt; But it
is not at all clear what should be in the second element.

Racc doesn't care. As long as the lexer and your productions agree on
the type (or on the duck-typing), it's OK.

Your understanding appears to be fine. You just have a simple bug--see
below.

[snip]
-------- FakeLexer.rb --------
require 'RubyCalcParser'

class FakeLexer

    def initialize(tokens)
        @tokens = tokens
        @index = 0
    end

    def reset()
        @index = 0
    end

    def yylex()
        rval = @tokens[@index]
        @index += @index

          @index += 1

        return rval
    end

end
-------- end --------

It's returning two NUMBERS in a row, which is a syntax error in your
grammar.

Don't you love bugs like this? If you didn't suspect your understanding
of Racc, you'd probably have found in in two minutes. HTH.

Steve

Doh!

···

On Apr 24, 2005, at 6:30 PM, Steven Jenkins wrote:

Your understanding appears to be fine. You just have a simple bug--see
below.

    def yylex()
        rval = @tokens[@index]
        @index += @index

          @index += 1

        return rval
    end

--
There's neither heaven nor hell, save what we grant ourselves.
There's neither fairness nor justice, save what we grant each other.