Module: LexerKit::CLI::Commands::Compile

Defined in:
lib/lexer_kit/cli/commands.rb

Overview

Compile DSL to .lkt1 or .lkb1 binary format

Class Method Summary collapse

Class Method Details

.run(argv) ⇒ Object



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
# File 'lib/lexer_kit/cli/commands.rb', line 8

def self.run(argv)
  options = { output: nil, verbose: false, dry_run: false }

  parser = OptionParser.new do |opts|
    opts.banner = "Usage: lexer_kit compile [options] <file.rb>"

    opts.on("-o", "--output FILE", "Output file (default: <input>.lkt1)") do |v|
      options[:output] = v
    end

    opts.on("--verbose", "Show conflict warnings") do
      options[:verbose] = true
    end

    opts.on("-n", "--dry-run", "Check for conflicts without generating output") do
      options[:dry_run] = true
    end

    opts.on("-h", "--help", "Show this help") do
      puts opts
      return 0
    end
  end

  parser.parse!(argv)

  if argv.empty?
    warn "error: No input file specified"
    warn parser.banner
    return 1
  end

  path = argv.shift
  unless File.exist?(path)
    warn "error: File not found: #{path}"
    return 1
  end

  # Load builder
  builder = LexerKit.load_builder(path)

  # Check for conflicts with --verbose or --dry-run
  if options[:verbose] || options[:dry_run]
    conflicts = builder.check_conflicts
    if conflicts.any?
      conflicts.each do |c|
        warn "warning: #{c.token1} vs #{c.token2}: #{c.description}"
      end
      warn ""
      warn "#{conflicts.size} potential conflict(s) found"
    elsif options[:dry_run]
      warn "No conflicts found."
    end
  end

  # Exit early if dry-run
  if options[:dry_run]
    return 0
  end

  # Compile
  compiled = builder.compile

  # Write output
  output_path = options[:output] || path.sub(/\.rb$/, ".lkt1")
  if output_path.end_with?(".lkb1")
    Format::LKB1.save(compiled, path: output_path)
  else
    Format::LKT1.save(compiled, path: output_path)
  end
  warn "Compiled: #{output_path}"

  0
end