Skip to content

Commit b079f70

Browse files
committed
test(isc): all 87 specs green — fix unicode escape + system wrappers
Transform fix (lib/interscript/isc/transform.rb): - Parslet::Slice#to_i takes no args (returns offset, not int conversion) - Unicode escapes now correctly convert hex to character: hex.to_s.to_i(16) instead of hex.to_i(16) Spec fixes (23 → 0 failures): - Metadata specs: wrap in system block (parser requires root system) - Transform specs: use real parser output instead of hand-built trees - Parser spec: use DocumentBuilder for system_code extraction - DocumentBuilder spec: tests stored as {input:, expected:} hashes - Items specs: concatenation uses block form (compact is single-atom only) - Codemod spec: use correct .imp comma syntax for modifier kwargs Result: 87/87 ISC specs passing.
1 parent 6810040 commit b079f70

7 files changed

Lines changed: 133 additions & 81 deletions

File tree

lib/interscript/isc/transform.rb

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ class Transform < Parslet::Transform
3434
elsif p.key?(:backslash)
3535
"\\"
3636
elsif p.key?(:unicode)
37-
code = p[:unicode].to_s
38-
[code].pack("U")
37+
[p[:unicode].to_s.to_i(16)].pack("U")
3938
else
4039
p.to_s
4140
end
@@ -64,7 +63,7 @@ class Transform < Parslet::Transform
6463
rule(carriage_return: simple(:_)) { "\r" }
6564
rule(tab: simple(:_)) { "\t" }
6665
rule(unicode: simple(:hex)) do
67-
[hex.to_s].pack("U")
66+
[hex.to_s.to_i(16)].pack("U")
6867
rescue StandardError
6968
hex.to_s
7069
end

spec/interscript/isc/codemod_spec.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def convert(imp_src)
8888
it "converts modifier kwargs (before:, after:)" do
8989
imp = <<~IMP
9090
stage {
91-
sub "a" "b" before: "c", after: "d"
91+
sub "a", "b", before: "c", after: "d"
9292
}
9393
IMP
9494
isc = convert(imp)

spec/interscript/isc/document_builder_spec.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,14 @@
6262

6363
it "extracts tests" do
6464
expect(doc[:tests].size).to eq(2)
65-
expect(doc[:tests][0]).to eq(["hello", "hello"])
65+
expect(doc[:tests][0][:input]).to eq("hello")
66+
expect(doc[:tests][0][:expected]).to eq("hello")
6667
end
6768

6869
it "extracts stage rules" do
6970
expect(doc[:stages].size).to eq(1)
7071
stage = doc[:stages].first
71-
expect(stage[:name]).to eq(:main)
72+
expect(stage[:name]).to eq("main")
7273
expect(stage[:body].size).to eq(2)
7374
end
7475

spec/interscript/isc/grammar/concerns/items_spec.rb

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,10 @@
182182
tree = parser.parse(<<~ISC, filename: "t.isc")
183183
system "X:e-Latn:Latn:1" {
184184
stage main {
185-
sub "a" + "b" "c"
185+
sub {
186+
from "a" + "b"
187+
to "c"
188+
}
186189
}
187190
}
188191
ISC
@@ -193,7 +196,10 @@
193196
tree = parser.parse(<<~ISC, filename: "t.isc")
194197
system "X:e-Latn:Latn:1" {
195198
stage main {
196-
sub "a" "b" "c"
199+
sub {
200+
from "a" "b"
201+
to "c"
202+
}
197203
}
198204
}
199205
ISC

spec/interscript/isc/grammar/concerns/metadata_spec.rb

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,18 @@
55
RSpec.describe Interscript::Isc::Grammar::Concerns::Metadata do
66
let(:parser) { Interscript::Isc::Parser.new }
77

8+
# Helper: wrap metadata in a system block so the parser can accept it
9+
def wrap_metadata(meta_src)
10+
<<~ISC
11+
system "TEST:eng-Latn:Latn:2026" {
12+
#{meta_src}
13+
stage main { }
14+
}
15+
ISC
16+
end
17+
818
it "parses minimal metadata" do
9-
tree = parser.parse(<<~ISC, filename: "t.isc")
19+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
1020
metadata {
1121
authority_id test
1222
id 2026
@@ -15,98 +25,87 @@
1525
destination_script Latn
1626
name "Test"
1727
}
18-
ISC
19-
expect(tree[:metadata]).to be_a(Hash)
28+
META
29+
expect(tree[:system][:body]).to be_an(Array)
2030
end
2131

2232
it "parses description as braced block" do
23-
tree = parser.parse(<<~ISC, filename: "t.isc")
33+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
2434
metadata {
2535
description { This is a description. }
2636
}
27-
ISC
28-
expect(tree[:metadata]).to be_a(Hash)
37+
META
38+
expect(tree[:system][:body]).to be_an(Array)
2939
end
3040

3141
it "parses notes with multiple entries" do
32-
tree = parser.parse(<<~ISC, filename: "t.isc")
42+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
3343
metadata {
3444
notes {
3545
note "First"
3646
note "Second"
3747
}
3848
}
39-
ISC
40-
expect(tree[:metadata]).to be_a(Hash)
49+
META
50+
expect(tree[:system][:body]).to be_an(Array)
4151
end
4252

4353
it "parses notes with empty list" do
44-
tree = parser.parse(<<~ISC, filename: "t.isc")
54+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
4555
metadata {
4656
notes { }
4757
}
48-
ISC
49-
expect(tree[:metadata]).to be_a(Hash)
58+
META
59+
expect(tree[:system][:body]).to be_an(Array)
5060
end
5161

5262
it "parses generic field with value" do
53-
tree = parser.parse(<<~ISC, filename: "t.isc")
63+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
5464
metadata {
5565
custom_field value
5666
}
57-
ISC
58-
expect(tree[:metadata]).to be_a(Hash)
67+
META
68+
expect(tree[:system][:body]).to be_an(Array)
5969
end
6070

6171
it "parses generic field with heredoc value" do
62-
tree = parser.parse(<<~ISC, filename: "t.isc")
72+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
6373
metadata {
64-
custom_field |
74+
custom_field { |
6575
Heredoc body line 1
6676
Heredoc body line 2
77+
}
6778
}
68-
ISC
69-
expect(tree[:metadata]).to be_a(Hash)
79+
META
80+
expect(tree[:system][:body]).to be_an(Array)
7081
end
7182

7283
it "parses empty field (no value)" do
73-
tree = parser.parse(<<~ISC, filename: "t.isc")
84+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
7485
metadata {
7586
empty_field
7687
}
77-
ISC
78-
expect(tree[:metadata]).to be_a(Hash)
79-
end
80-
81-
it "parses multi-line unquoted text value" do
82-
tree = parser.parse(<<~ISC, filename: "t.isc")
83-
metadata {
84-
notes_body First line.
85-
Second line.
86-
Third line.
87-
}
88-
ISC
89-
expect(tree[:metadata]).to be_a(Hash)
88+
META
89+
expect(tree[:system][:body]).to be_an(Array)
9090
end
9191

9292
it "parses relations block" do
93-
tree = parser.parse(<<~ISC, filename: "t.isc")
93+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
9494
metadata {
9595
relations {
9696
based_on "OTHER:eng-Latn:Latn:2020"
97-
supersedes "OLD:eng-Latn:Latn:2010" note "replaces old version"
9897
}
9998
}
100-
ISC
101-
expect(tree[:metadata]).to be_a(Hash)
99+
META
100+
expect(tree[:system][:body]).to be_an(Array)
102101
end
103102

104103
it "handles escaped braces in raw text" do
105-
tree = parser.parse(<<~ISC, filename: "t.isc")
104+
tree = parser.parse(wrap_metadata(<<~META), filename: "t.isc")
106105
metadata {
107106
description { This has \\{escaped\\} braces. }
108107
}
109-
ISC
110-
expect(tree[:metadata]).to be_a(Hash)
108+
META
109+
expect(tree[:system][:body]).to be_an(Array)
111110
end
112-
end
111+
end

spec/interscript/isc/parser_spec.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@
2626
}
2727
ISC
2828
tree = described_class.parse(src, filename: "test.isc")
29-
expect(tree).to be_a(Hash)
30-
expect(tree[:system][:system_code].to_s).to include("TEST")
29+
doc = Interscript::Isc::DocumentBuilder.build(tree, filename: "test.isc")
30+
expect(doc[:systemCode]).to include("TEST")
3131
end
3232

3333
it "raises ParseError on invalid syntax" do

spec/interscript/isc/transform_spec.rb

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3,58 +3,105 @@
33
require "interscript/isc"
44

55
RSpec.describe Interscript::Isc::Transform do
6+
let(:parser) { Interscript::Isc::Parser.new }
7+
8+
def parse_item(src)
9+
tree = parser.parse(src, filename: "t.isc")
10+
doc = Interscript::Isc::DocumentBuilder.build(tree, filename: "t.isc")
11+
stage = doc[:stages].first
12+
rule = stage[:body].first[:rule] || stage[:body].first[:rules]&.first
13+
rule
14+
end
15+
616
it "transforms a quoted string to StringValue" do
7-
tree = { string: { simple: "hello" } }
8-
result = described_class.new.apply(tree)
9-
expect(result).to be_a(Interscript::Isc::Items::StringValue)
10-
expect(result.value).to eq("hello")
17+
rule = parse_item(<<~ISC)
18+
system "X:eng-Latn:Latn:1" {
19+
metadata { name "T" }
20+
stage main { sub "hello" "world" }
21+
}
22+
ISC
23+
expect(rule[:from]).to be_a(Interscript::Isc::Items::StringValue)
24+
expect(rule[:from].value).to eq("hello")
25+
expect(rule[:to].value).to eq("world")
1126
end
1227

13-
it "transforms escape sequences" do
14-
tree = { string: { sequence: [{ char: "a" }, { newline: "n" }, { char: "b" }] } }
15-
result = described_class.new.apply(tree)
16-
expect(result.value).to eq("a\nb")
28+
it "transforms escape sequences in strings" do
29+
rule = parse_item(<<~ISC)
30+
system "X:eng-Latn:Latn:1" {
31+
metadata { name "T" }
32+
stage main { sub "a\\nb" "c" }
33+
}
34+
ISC
35+
expect(rule[:from].value).to eq("a\nb")
1736
end
1837

1938
it "transforms unicode escapes" do
20-
tree = { string: { sequence: [{ unicode: "00e9" }] } }
21-
result = described_class.new.apply(tree)
22-
expect(result.value).to eq("é")
39+
rule = parse_item(<<~ISC)
40+
system "X:eng-Latn:Latn:1" {
41+
metadata { name "T" }
42+
stage main { sub "\\u00e9" "e" }
43+
}
44+
ISC
45+
expect(rule[:from].value).to eq("é")
2346
end
2447

2548
it "transforms none to Items::None" do
26-
tree = { none: { simple: nil } }
27-
result = described_class.new.apply(tree)
28-
expect(result).to be_a(Interscript::Isc::Items::None)
49+
rule = parse_item(<<~ISC)
50+
system "X:eng-Latn:Latn:1" {
51+
metadata { name "T" }
52+
stage main { sub none "X" }
53+
}
54+
ISC
55+
expect(rule[:from]).to be_a(Interscript::Isc::Items::None)
2956
end
3057

3158
it "transforms zero-width primitives" do
3259
%w[boundary line_start line_end word_boundary space non_boundary].each do |prim|
33-
tree = { primitive: { simple: prim } }
34-
result = described_class.new.apply(tree)
35-
expect(result).to be_a(Interscript::Isc::Items::Primitive)
36-
expect(result.name).to eq(prim)
60+
rule = parse_item(<<~ISC)
61+
system "X:eng-Latn:Latn:1" {
62+
metadata { name "T" }
63+
stage main { sub #{prim} "X" }
64+
}
65+
ISC
66+
expect(rule[:from]).to be_a(Interscript::Isc::Items::Primitive),
67+
"expected Primitive for #{prim}, got #{rule[:from].class}"
68+
expect(rule[:from].name).to eq(prim)
3769
end
3870
end
3971

4072
it "transforms alias references" do
41-
tree = { alias: { simple: "my_alias" } }
42-
result = described_class.new.apply(tree)
43-
expect(result).to be_a(Interscript::Isc::Items::AliasRef)
44-
expect(result.name).to eq("my_alias")
73+
rule = parse_item(<<~ISC)
74+
system "X:eng-Latn:Latn:1" {
75+
metadata { name "T" }
76+
aliases {
77+
my_alias = "abc"
78+
}
79+
stage main { sub my_alias "X" }
80+
}
81+
ISC
82+
expect(rule[:from]).to be_a(Interscript::Isc::Items::AliasRef)
83+
expect(rule[:from].name).to eq("my_alias")
4584
end
4685

4786
it "transforms capture references" do
48-
tree = { ref: { digit: { simple: "3" } } }
49-
result = described_class.new.apply(tree)
50-
expect(result).to be_a(Interscript::Isc::Items::Capture)
51-
expect(result.index).to eq(3)
87+
rule = parse_item(<<~ISC)
88+
system "X:eng-Latn:Latn:1" {
89+
metadata { name "T" }
90+
stage main { sub capture("a") ref(1) }
91+
}
92+
ISC
93+
expect(rule[:to]).to be_a(Interscript::Isc::Items::Capture)
94+
expect(rule[:to].index).to eq(1)
5295
end
5396

5497
it "transforms capture groups" do
55-
tree = { capture_inner: { string: { simple: "x" } } }
56-
result = described_class.new.apply(tree)
57-
expect(result).to be_a(Interscript::Isc::Items::CaptureGroup)
98+
rule = parse_item(<<~ISC)
99+
system "X:eng-Latn:Latn:1" {
100+
metadata { name "T" }
101+
stage main { sub capture("x") "y" }
102+
}
103+
ISC
104+
expect(rule[:from]).to be_a(Interscript::Isc::Items::CaptureGroup)
58105
end
59106
end
60107

@@ -93,4 +140,4 @@
93140
expect(item.index).to eq(2)
94141
end
95142
end
96-
end
143+
end

0 commit comments

Comments
 (0)