This file is indexed.

/usr/bin/y2racc is in racc 1.4.5-1.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
#!/usr/bin/ruby1.8
#
# y2racc  --  yacc to racc converter
#
# Copyright (c) 1999-2005 Minero Aoki
#
# This program is free software.
# You can distribute/modify this program under the terms of
# the GNU LGPL, Lesser General Public Lisence version 2.1.
# For details of the GNU LGPL, see the file "COPYING".
#

require 'optparse'
require 'strscan'
StringScanner.must_C_version

Y2RACC_VERSION = '1.1.1'

def usage(status = 1)
  $stderr.puts "#{File.basename $0}: wrong option" unless status == 0
  (status == 0 ? $stdout : $stderr).print(<<EOS)
Usage: y2racc [-AC] [-c classname] [-o outfile] yaccfile
    -o <file>    name of output file  [r.<inputfile>]
    -c <name>    name of parser class [MyParser]
    -u           output also user code (%%....)
    -H           cut off header (%{....%})
    -A           cut off actions
    -U           cut off user code (%%....) (default)
EOS
  exit status
end

def main
  op = OptionParser.new do |op|
    op.banner = 'Usage: y2racc [-AC] [-c classname] [-o outfile] yaccfile'

    op.on('-o <file>', 'name of output file  [r.<inputfile>]') do |file|
      $OPT_o = file
    end
    op.on('-c <name>', 'name of parser class [MyParser]') do |name|
      $OPT_c = name
    end
    op.on('-u', 'output also user code (%%....)') do
      $OPT_u = true
      $OPT_U = false
    end
    op.on('-H', 'cut off header (%{....%})') do
      $OPT_H = true
    end
    op.on('-A', 'cut off actions') do
      $OPT_A = true
    end
    op.on('-U', 'cut off user code (%%....) (default)') do
      $OPT_U = true
      $OPT_u = false
    end
    op.on('--help', 'print this message and quit') do
      $OPT_help = true
    end
    op.on('--version', 'print version and quit') do
      $OPT_version = true
    end
    op.on('--copyright', 'print copyright and quit') do
      $OPT_copyright = true
    end

    begin
      op.parse!
    rescue
      usage 1
    end
  end

  if $OPT_version
    puts "y2racc version #{Y2RACC_VERSION}"
    exit 0
  end
  if $OPT_copyright
    puts 'Copyright (c) 1999-2005 Minero Aoki'
    exit 0
  end
  usage 0 if $OPT_help
  usage 1 unless ARGV.size == 1

  cname = $OPT_c || 'MyParser'
  fname = ARGV[0]
  outf = $OPT_o || 'r.' + File.basename(fname)
  conv = Converter.new(cname)
  begin
    File.open(fname) {|f|
      conv.parse f, fname
    }
  rescue Errno::ENOENT
    $stderr.puts "no such file: #{fname}"
    exit 1
  end
  File.open(outf, 'w') {|f|
    conv.output f
  }
end


class Converter

  def initialize(cname)
    @cname = cname
    @prectab = []
    @start = nil
    @tokens = []
    @grammer = []

    @header = nil
    @footer = nil
  end

  COMMENT = %r</\*[^*]*\*+(?:[^/*][^*]*\*+)*/>

  #
  # parse
  #

  def parse(f, fname)
    @fname = fname
    str = f.read
    s = StringScanner.new(str)
    procdef s
    procrule s
  end


  def procdef(s)
    skip_until_percent s
    until s.empty?
      if t = s.scan(/(left|right|nonassoc|token|start)\b/)
        __send__ 'proc_' + t, get_tokens(s)
      elsif s.skip %r<(?:
            type | union | expect | thong | binary |
            semantic_parser | pure_parser | no_lines |
            raw | token_table                          )\b>x
        skip_until_percent s
      elsif s.skip /\{/
        @header = s.scan_until(/\%\}/)
        @header.chop!; @header.chop!   # %}
        skip_until_percent s
      elsif s.skip /\%/   # %%
        return
      else
        raise 'scan error'
      end
    end
  end

  def skip_until_percent(s)
    until s.empty?
      s.skip /[^\%\/]+/
      if t = s.scan(COMMENT)
        ;
      elsif s.getch == '/'
        ;
      else
        return
      end
    end
  end

  def get_tokens(s)
    list = []
    until s.empty?
      s.skip /\s+/
      next if s.skip(COMMENT)
      if t = s.scan(/'((?:[^'\\]+|\\.)*)'/)
        list.push t
      elsif t = s.scan(/"((?:[^"\\]+|\\.)*)"/)
        list.push t
      elsif s.skip(/\%/)
        break
      elsif t = s.scan(/\S+/)
        list.push t
      else
        raise 'scan error'
      end
    end
    list
  end

  def proc_left(list)
    @prectab.push ['left', list]
  end

  def proc_right(list)
    @prectab.push ['right', list]
  end

  def proc_nonassoc(list)
    @prectab.push ['nonassoc', list]
  end

  def proc_token(list)
    list.shift if /\A<(.*)>\z/ === list[0]
    @tokens.concat list
  end

  def proc_start(list)
    @start = list[0]
  end

  ###

  STRINGq = /'(?:[^'\\]+|\\.)*'/
  STRINGQ = /"(?:[^"\\]+|\\.)*"/

  def procrule(s)
    @text = []
    until s.empty?
      if t = s.scan(/[^%'"{\/]+/)
        @text.push t
        break if s.empty?
      end
      if s.skip /\{/
        if $OPT_A
          skip_action s
        else
          scan_action s
        end
      elsif t = s.scan(STRINGq) then @text.push t
      elsif t = s.scan(STRINGQ) then @text.push t
      elsif t = s.scan(COMMENT) then @text.push t
      elsif s.skip(/%prec\b/)   then @text.push '='
      elsif s.skip(/%%/)
        @footer = s.rest if $OPT_u
        break
      else
        @text.push s.getch
      end
    end
  end

  def skip_action(s)
    @text, save = [], @text
    scan_action s
    @text = save
    #@text.push "{\n                # action\n            }"
    @text.push "{  }"
  end

  def scan_action(s)
    @text.push '{'
    nest = 1
    until s.empty?
      if t = s.scan(/[^{'"}\/]+/)
        @text.push t
        break if s.empty?
      end
      if t = s.scan(COMMENT)
        @text.push t
        next
      end
      c = s.getch
      @text.push c
      case c
      when '{'
        nest += 1
      when '}'
        nest -= 1
        if nest == 0
          return
        end
      else
        ;
      end
    end
    $stderr.puts "warning: unterminated action in #{@fname}"
  end

  #
  # output
  #

  def output(f)
    f.print(<<SRC)
#
# converted from "#{@fname}" by y2racc version #{Y2RACC_VERSION}
#

class #{@cname}

SRC
    f.print 'token'
    total = 0
    @tokens.each do |t|
      if total > 60
        f.print "\n     "
        total = 0
      end
      total += f.write(" #{t}")
    end
    f.puts
    f.puts

    unless @prectab.empty?
      f.puts 'preclow'
      @prectab.each do |type, toks|
        f.printf "  %-8s %s\n", type, toks.join(' ') unless toks.empty?
      end
      f.puts 'prechigh'
      f.puts
    end

    if @start
      f.puts "start #{@start}"
      f.puts
    end

    f.puts 'rule'
    @text.each {|t| f.print t }
    f.puts
    f.puts 'end'

    if not $OPT_H and @header
      f.puts
      f.puts '---- header'
      f.puts @header
    end
    if $OPT_u and @footer
      f.puts
      f.puts '---- footer'
      f.puts @footer
    end
  end

end


main