class Racc::GrammarFileScanner

def scan_action

def scan_action
  buf = String.new
  nest = 1
  pre = nil
  @in_block = 'action'
  begin
    pre = nil
    if s = reads(/\A\s+/)
      # does not set 'pre'
      buf << s
    end
    until @line.empty?
      if s = reads(/\A[^'"`{}%#\/\$]+/)
        buf << (pre = s)
        next
      end
      case ch = read(1)
      when '{'
        nest += 1
        buf << (pre = ch)
      when '}'
        nest -= 1
        if nest == 0
          @in_block = nil
          buf.sub!(/[ \t\f]+\z/, '')
          return buf
        end
        buf << (pre = ch)
      when '#'   # comment
        buf << ch << @line
        break
      when "'", '"', '`'
        buf << (pre = scan_quoted(ch))
      when '%'
        if literal_head? pre, @line
          # % string, regexp, array
          buf << ch
          case ch = read(1)
          when /[qQx]/n
            buf << ch << (pre = scan_quoted(read(1), '%string'))
          when /wW/n
            buf << ch << (pre = scan_quoted(read(1), '%array'))
          when /s/n
            buf << ch << (pre = scan_quoted(read(1), '%symbol'))
          when /r/n
            buf << ch << (pre = scan_quoted(read(1), '%regexp'))
          when /[a-zA-Z0-9= ]/n   # does not include "_"
            scan_error! "unknown type of % literal '%#{ch}'"
          else
            buf << (pre = scan_quoted(ch, '%string'))
          end
        else
          # operator
          buf << '||op->' if $raccs_print_type
          buf << (pre = ch)
        end
      when '/'
        if literal_head? pre, @line
          # regexp
          buf << (pre = scan_quoted(ch, 'regexp'))
        else
          # operator
          buf << '||op->' if $raccs_print_type
          buf << (pre = ch)
        end
      when '$'   # gvar
        buf << ch << (pre = read(1))
      else
        raise 'racc: fatal: must not happen'
      end
    end
    buf << "\n"
  end while next_line()
  raise 'racc: fatal: scan finished before parser finished'
end