# class Racc::GrammarFileParser

### Constants

USER_CODE_LABELS

### Public Class Methods

new(debug_flags = DebugFlags.new) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 173
    def initialize(debug_flags = DebugFlags.new)
      @yydebug = debug_flags.parse
    end

parse(src, filename = '-', lineno = 1) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 169
    def GrammarFileParser.parse(src, filename = '-', lineno = 1)
      new().parse(src, filename, lineno)
    end

parse_file(filename) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 165
    def GrammarFileParser.parse_file(filename)
      parse(File.read(filename), filename, 1)
    end

### Public Instance Methods

parse(src, filename = '-', lineno = 1) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 177
    def parse(src, filename = '-', lineno = 1)
      @filename = filename
      @lineno = lineno
      @scanner = GrammarFileScanner.new(src, @filename)
      @scanner.debug = @yydebug
      @grammar = Grammar.new
      @result = Result.new(@grammar)
      @embedded_action_seq = 0
      yyparse @scanner, :yylex
      parse_user_code
      @result.grammar.init
      @result
    end

### Private Instance Methods

add_rule(target, list, sprec) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 236
    def add_rule(target, list, sprec)
      if list.last.kind_of?(UserAction)
        act = list.pop
      else
        act = UserAction.empty
      end
      list.map! {|s| s.kind_of?(UserAction) ? embedded_action(s) : s }
      rule = Rule.new(target, list, act)
      rule.specified_prec = sprec
      @grammar.add rule
    end

add_rule_block(list) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 212
    def add_rule_block(list)
      sprec = nil
      target = list.shift
      case target
      when OrMark, UserAction, Prec
        raise CompileError, "#{target.lineno}: unexpected symbol #{target.name}"
      end
      curr = []
      list.each do |i|
        case i
        when OrMark
          add_rule target, curr, sprec
          curr = []
          sprec = nil
        when Prec
          raise CompileError, "'=<prec>' used twice in one rule" if sprec
          sprec = i.symbol
        else
          curr.push i
        end
      end
      add_rule target, curr, sprec
    end

add_user_code(label, src) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 289
    def add_user_code(label, src)
      @result.params.public_send(USER_CODE_LABELS[label]).push src
    end

canonical_label(src) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 281
    def canonical_label(src)
      label = src.to_s.strip.downcase.slice(/\w+/)
      unless USER_CODE_LABELS.key?(label)
        raise CompileError, "unknown user code type: #{label.inspect}"
      end
      label
    end

embedded_action(act) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 248
    def embedded_action(act)
      sym = @grammar.intern("@#{@embedded_action_seq += 1}".intern, true)
      @grammar.add Rule.new(sym, [], act)
      sym
    end

location() click to toggle source

    # File lib/racc/grammarfileparser.rb, line 208
    def location
      "#{@filename}:#{@lineno - 1 + @scanner.lineno}"
    end

next_token() click to toggle source

    # File lib/racc/grammarfileparser.rb, line 193
    def next_token
      @scanner.scan
    end

on_error(tok, val, _values) click to toggle source

    # File lib/racc/grammarfileparser.rb, line 197
    def on_error(tok, val, _values)
      if val.respond_to?(:id2name)
        v = val.id2name
      elsif val.kind_of?(String)
        v = val
      else
        v = val.inspect
      end
      raise CompileError, "#{location()}: unexpected token '#{v}'"
    end

parse_user_code() click to toggle source

User Code Block

    # File lib/racc/grammarfileparser.rb, line 258
    def parse_user_code
      line = @scanner.lineno
      _, *blocks = *@scanner.epilogue.split(/^----/)
      blocks.each do |block|
        header, *body = block.lines.to_a
        label0, paths = *header.sub(/\A-+/, '').split('=', 2)
        label = canonical_label(label0)
        (paths ? paths.strip.split(' ') : []).each do |path|
          add_user_code label, SourceText.new(File.read(path), path, 1)
        end
        add_user_code label, SourceText.new(body.join(''), @filename, line + 1)
        line += (1 + body.size)
      end
    end