Minero Aoki wrote:
> > Following racc-rule raises an error during parsing (not during 'racc parser.y'), 
> > and I don't know why.
> 
> Please tell me an entire part of error. I cannot answer
> before I got, at least, the error message from ruby.
> Your grammer file, input token stream is also helpful.
> If it is very big, feel free to send me them directory.

As you perhaps noticed, it is (or will be) a XPath parser.

I use racc version 1.3.9.
I create successfully parser.tab.rb from parser.y with racc.
Input token stream is "child::processing-instructin ( 'hallo' ) []".
Executing parser.tab.rb gives following output:

parsing:
child::processing-instruction ( 'hallo' ) []
AxisSpecifier

Exception `Racc::ParseError' at /usr/pkg/lib/ruby/site_ruby/1.6/racc/parser.rb:371 - 
parse error on value "processing-instruction" (NodeType)
/usr/pkg/lib/ruby/site_ruby/1.6/racc/parser.rb:371:in `on_error':  (Racc::ParseError)
parse error on value "processing-instruction" (NodeType)
	from /usr/pkg/lib/ruby/site_ruby/1.6/racc/parser.rb:97:in `_racc_do_parse_c'
	from /usr/pkg/lib/ruby/site_ruby/1.6/racc/parser.rb:97:in `__send__'
	from /usr/pkg/lib/ruby/site_ruby/1.6/racc/parser.rb:97:in `do_parse'
	from parser.wrong.y:74:in `parse'
	from parser.wrong.tab.rb:259





###########
# parser.y
###########

class XPathParser

token Number Literal Operator NameTest AxisName NodeType FunctionName VariableReference    


start LocationPath

rule

LocationPath : RelativeLocationPath 
             | AbsoluteLocationPath 
             ;

AbsoluteLocationPath : '/' 
		     | '/' RelativeLocationPath
		     ;


RelativeLocationPath : Step { puts "Relative Location Path" }
                     | RelativeLocationPath '/' Step
		     ;

Step : AxisSpecifier NodeTest Predicates { puts "Step" }
     ;

AxisSpecifier : AxisName '::' { puts "AxisSpecifier" }
              ;





OtherNodeTypes : 'comment'
               | 'text'
               | 'node'
               ;

##### here's the error

NodeTest : NameTest  { puts "NameTest" }
         | 'processing-instruction' '(' Literal ')'  { puts "PI" }
         | OtherNodeTypes '(' ')' { puts "other" }
         ;

Predicates : /* empty */
           | Predicates Predicate
           {
           puts "Predicates"
           }


Predicate :  '[' ']'
         {
          puts "Predicate"
         }

end

---- header

require "tokenizer"

---- inner

def parse( str )
  @tokenizer = Tokenizer.new(str)
  do_parse
end

def next_token
  tok = @tokenizer.next_token
  if tok.nil?
    [false, '$']
  else
    if tok.size == 1 then
      [tok[0], tok[0]]
    else
      tok
    end
  end
end

---- footer

if $0 == __FILE__ then
  $DEBUG=true

  src = "child::processing-instruction ( 'hallo' ) []"

  puts "parsing:"
  puts src


  XPathParser.new.parse(src)
end


###############
# tokenizer.rb
###############

require "strscan"

class Tokenizer

  NCName = "[a-zA-Z_][-a-zA-Z0-9._]*"
  QName = "(#{NCName}:)?#{NCName}"
  AxisName = "(ancestor-or-self|ancestor|attribute|child|descendant-or-self" +
             "|descendant|following-sibling|following|namespace" + 
             "|parent|preceding-sibling|preceding|self)" 
  NodeType = "(comment|text|processing-instruction|node)"
  OperatorName = "(and|or|mod|div)"
  Digits = "([0-9]+)"
  Literal = %{("[^"]*"|'[^']*')}


  def initialize( str )
    @scanner = StringScanner.new( str ) 
    @last_token = nil
  end

  def next_token
    s = @scanner


    # skip whitespaces
    s.skip /\A\s+/

    token = 

    # match ( ) [ ] @ ,
    if s.scan /\A[()@,\]\[]/ then
      [s.matched]

    # match digits (before . and .. !!!)
    elsif s.scan /\A(#{Digits}([.]#{Digits}?)?|[.]#{Digits})/
      [:Number, s.matched]

    # match . .. ::
    elsif s.scan /\A(::|[.][.]?)/
      [s.matched]

    # match literals
    elsif s.scan /\A#{Literal}/
      [:Literal, s.matched] 

    elsif s.scan /\A([+-]|\/\/?|!=|=|[<]=?|[>]=?)/
      [:Operator, s.matched]

    elsif s.scan /\A[*]/ then
      if @last_token.nil? or @last_token[0] == :Operator or %w{@ :: ( [ ,}.include?( @last_token[1] )
        [:NameTest, s.matched]
      else
        [:Operator, s.matched]
      end

    # match AxisName
    elsif s.check /\A#{AxisName}\s*::/
      s.scan /\A#{AxisName}/
      [:AxisName, s.matched]

    # match NodeType
    elsif s.check /\A#{NodeType}\s*\(/
      s.scan /\A#{NodeType}/
      [:NodeType, s.matched]

    # match FunctionName
    elsif s.check /\A#{QName}\s*\(/
      s.scan /\A#{QName}/
      [:FunctionName, s.matched]

    # match VariableReference
    elsif s.scan /\A[\$]#{QName}/
      [:VariableReference, s.matched]

    # match NameTest
    elsif s.scan /\A((#{NCName}:)?[*]|#{QName})/
      [:NameTest, s.matched]

    elsif s.scan /\A#{OperatorName}/
      [:Operator, s.matched]
 

    elsif s.empty?
      nil
    elsif s.rest?
      raise "Syntax Error!"
    end

    @last_token = token

    return token

  end

end

############


Thanks in advance.


Regards

Michael



-- 
Michael Neumann
merlin.zwo InfoDesign GmbH
http://www.merlin-zwo.de