Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions lib/interscript/isc/grammar/concerns/stages.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ module Stages
whitespace?
end

# Comments and stray identifiers are silently consumed.
# Comments are consumed; stray identifiers are a parse error
# (WO87/A4 strict-parse ruling: the corpus is 295/295 strict-clean,
# so a typo'd map can no longer silently no-op).
rule(:comment_item) do
(str("#") >> (str("\n").absent? >> any).repeat).as(:comment) |
identifier.as(:noop)
(str("#") >> (str("\n").absent? >> any).repeat).as(:comment)
end

# Bare rule directly in a stage body (not wrapped in sequence/parallel).
Expand Down
26 changes: 16 additions & 10 deletions spec/isc/semantics_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,17 @@ def system_map(id, body)
ISC
end

it "rules: run <stdlib-name> dispatches the stdlib function" do
with_map("tst-fn-1.isc", system_map(51, "stage main { run downcase }")) do
it "rules: stdlib string functions are stage DIRECTIVES (downcase), not run targets" do
# The strict parse revealed `run downcase` only ever worked by
# accident (noop + case-directive). The sanctioned spelling is the
# bare directive.
with_map("tst-fn-1.isc", system_map(51, "stage main { downcase }")) do
expect(Interscript.transliterate("tst-fn-1", "AbC")).to eq("abc")
end
with_map("tst-fn-1b.isc", system_map(51, "stage main { run downcase }")) do
expect { Interscript.transliterate("tst-fn-1b", "AbC") }
.to raise_error(Interscript::Isc::ParseError)
end
end

it "rules: stage-level case directives run at their position, on the whole string" do
Expand All @@ -249,15 +256,14 @@ def system_map(id, body)
end
end

it "rules: stray identifiers are consumed as no-ops — pinned as a hazard" do
# HAZARD (A4 follow-up): `run nosuchfunction` drops BOTH identifiers
# at parse time and the stage becomes empty — a typo'd map is
# silently wrong. Ruled normative-for-now (legacy .imp corpus
# tolerance, grammar/concerns/stages.rb comment_item); the stricter
# parse is an open item tracked in the IS-1 v2 text, gated on a
# clean parse of the full 293-map corpus across all three compilers.
it "rules: stray identifiers are a PARSE ERROR (the strict-parse ruling, A4 adopted)" do
# The batch-4 hazard (silent no-op) is CLOSED: the corpus gate
# passed (295/295 strict-clean after the odni-prs stray-'s' fix,
# maps#207), so the grammar rejects stray identifiers — a typo'd
# map fails loudly instead of being silently wrong.
with_map("tst-fn-4.isc", system_map(54, "stage main { run nosuchfunction parallel { sub { from \"a\" to \"b\" } } }")) do
expect(Interscript.transliterate("tst-fn-4", "a")).to eq("b")
expect { Interscript.transliterate("tst-fn-4", "a") }
.to raise_error(Interscript::Isc::ParseError)
end
end
end
Expand Down
Loading