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