# encoding: utf-8
# frozen_string_literal: true

require 'open-uri'
require_relative "../task_helper"

LLVM_KEYWORDS_FILE = "./lib/rouge/lexers/llvm/keywords.rb"

namespace :builtins do
  task :llvm do
    LLVMBuiltins.process(LLVM_KEYWORDS_FILE)
  end
end

class LLVMBuiltins < BuiltinsGenerator
  # TODO: Newer versions require parsing Attributes.td separately.
  LLVM_SYNTAX_URI = "https://raw.githubusercontent.com/llvm/llvm-project/9de7b93bc00804585a8e36fc35f6449329d8225a/llvm/lib/AsmParser/LLLexer.cpp"

  def fetch
    URI.open(LLVM_SYNTAX_URI) { |f| f.read }
  end

  def parse
    keywords = Hash.new { |h,k| h[k] = Array.new }
    kind = nil

    @input.each_line(";") do |line|
      if line =~ /#define (.*?)\(/
        case $1
        when "KEYWORD"
          kind = "keywords"
        when "TYPEKEYWORD"
          kind = "types"
        when "INSTKEYWORD"
          kind = "instructions"
        else
          kind = nil
        end

        next
      end

      next unless kind && line =~ /KEYWORD\("?([^)",]+)/

      keywords[kind].push $1
    end

    # Does not use TYPEKEYWORD() due to special handling.
    keywords["types"].push "ptr"

    keywords.transform_values! { |v| v.sort.uniq }
  end

  def generate
    yield "# encoding: utf-8"
    yield "# frozen_string_literal: true"
    yield ""
    yield "# DO NOT EDIT"
    yield "# This file is automatically generated by `rake builtins:llvm`."
    yield "# See tasks/builtins/llvm.rake for more info."
    yield ""
    yield "module Rouge"
    yield "  module Lexers"
    yield "    class LLVM"
    @keywords.each do |k,v|
      yield "      #{k.upcase} = Set.new #{v.inspect}"
    end
    yield "    end"
    yield "  end"
    yield "end"
  end
end
