Class: LexerKit::Format::LKT1

Inherits:
Object
  • Object
show all
Defined in:
lib/lexer_kit/format/lkt1.rb

Overview

LKT1 (LexerKit Text format version 1) is a JSON-based container format for compiled lexer programs. It supports compression and includes integrity checking via SHA256.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(program) ⇒ LKT1

Create a new LKT1 instance from a compiled program

Parameters:



18
19
20
# File 'lib/lexer_kit/format/lkt1.rb', line 18

def initialize(program)
  @program = program
end

Instance Attribute Details

#programObject (readonly)

Returns the value of attribute program.



14
15
16
# File 'lib/lexer_kit/format/lkt1.rb', line 14

def program
  @program
end

Class Method Details

.decode(json_string) ⇒ LKT1

Decode a compiled lexer program from lkt1 JSON string

Parameters:

  • json_string (String)

    lkt1 JSON string

Returns:

  • (LKT1)

    LKT1 instance



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
# File 'lib/lexer_kit/format/lkt1.rb', line 40

def self.decode(json_string)
  container = JSON.parse(json_string, symbolize_names: true)

  # Validate format
  unless container[:format] == "lkt1"
    raise LexerKit::IntegrityError, "Unknown format: #{container[:format]}"
  end

  unless container[:kind] == "program"
    raise LexerKit::IntegrityError, "Unknown kind: #{container[:kind]}"
  end

  # Decode based on codec
  unless container[:codec] == "deflate+base64"
    raise LexerKit::IntegrityError, "Unknown codec: #{container[:codec]}"
  end

  compressed = Base64.strict_decode64(container[:data])
  binary = Zlib::Inflate.inflate(compressed)

  # Verify integrity (sha256 is required)
  unless container[:sha256]
    raise LexerKit::IntegrityError, "Missing required field: sha256"
  end

  actual_hash = Digest::SHA256.hexdigest(binary)
  unless actual_hash == container[:sha256]
    raise LexerKit::IntegrityError, "SHA256 mismatch: expected #{container[:sha256]}, got #{actual_hash}"
  end

  if container[:uncompressed_len] && binary.bytesize != container[:uncompressed_len]
    raise LexerKit::IntegrityError, "Length mismatch: expected #{container[:uncompressed_len]}, got #{binary.bytesize}"
  end

  program = IR::CompiledProgram.from_binary(binary)
  program.load_native! if LexerKit.native?
  new(program)
rescue JSON::ParserError => e
  raise LexerKit::IntegrityError, "Invalid JSON: #{e.message}"
rescue ArgumentError => e
  # Base64 decode errors
  raise LexerKit::IntegrityError, "Decoding error: #{e.message}"
rescue Zlib::Error => e
  raise LexerKit::IntegrityError, "Decompression error: #{e.message}"
end

.load(path) ⇒ LKT1

Load a compiled lexer program from a .lkt1 file

Parameters:

  • path (String)

    path to .lkt1 file

Returns:

  • (LKT1)

    LKT1 instance



25
26
27
28
# File 'lib/lexer_kit/format/lkt1.rb', line 25

def self.load(path)
  content = File.read(path)
  decode(content)
end

.save(program, path:) ⇒ Object

Save a compiled lexer program to a .lkt1 file (shortcut)

Parameters:



33
34
35
# File 'lib/lexer_kit/format/lkt1.rb', line 33

def self.save(program, path:)
  new(program).save(path)
end

Instance Method Details

#encodeString

Encode the program to lkt1 JSON string

Returns:

  • (String)

    JSON string



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/lexer_kit/format/lkt1.rb', line 88

def encode
  binary = @program.to_binary
  compressed = Zlib::Deflate.deflate(binary)
  encoded = Base64.strict_encode64(compressed)

  JSON.generate({
    format: "lkt1",
    codec: "deflate+base64",
    kind: "program",
    table_version: 2,
    uncompressed_len: binary.bytesize,
    sha256: Digest::SHA256.hexdigest(binary),
    data: encoded
  })
end

#save(path) ⇒ Object

Save the program to a .lkt1 file

Parameters:

  • path (String)

    output file path



106
107
108
# File 'lib/lexer_kit/format/lkt1.rb', line 106

def save(path)
  File.write(path, encode)
end