Why We Replaced else if with elseif in Jyro
TL;DR: Jyro now uses elseif as a single keyword instead of else if (two keywords). This fixes an unintuitive parsing behavior where the visual structure of code didn't match its semantic structure.
This is a breaking change that is fixed by simply finding and replacing all instances of
else ifwith
elseifThe original behaviour will stay the same, and a new construct elseif can be used where appropriate.
The Problem
Consider these two Jyro scripts:
# Script A
if a then
# foo
else if b then
# bar
end
# Script B
if a then
# foo
else
if b then
# bar
end
A programmer might expect these to behave differently. Script A looks like an else-if chain (one end), while Script B looks like a nested if inside an else block (visually suggesting it might need two ends, or share the outer one).
However both scripts parsed identically.
Why This Happened
Jyro's lexer, like most languages, discards whitespace before the parser sees the token stream:
WS : [ \t\r\n]+ -> skip ;
The old grammar rule for if statements was:
ifStmt
: IF expression THEN statement*
(ELSE IF expression THEN statement*)*
(ELSE statement*)?
END
;
The parser looked for the token sequence ELSE IF to identify an else-if branch. But since newlines are whitespace, and whitespace is discarded, both:
else if b then
and
else
if b then
produce the identical token stream: ELSE IF b THEN. The parser couldn't distinguish between them.
This created several problems:
Visual layout lies to the reader. Indentation suggests nesting, but the parser ignores it.
Impossible to express nested if-in-else. There was no way to write a genuinely nested
ifinside anelseblock-the parser would always consumeELSE IFas an else-if chain.Silent misinterpretation. The worst kind of bug: code parses successfully but means something different than what the author intended.
The Solution
We introduced elseif as a single, unambiguous keyword:
// New lexer token
ELSEIF : 'elseif';
// Updated grammar rule
ifStmt
: IF expression THEN statement*
(ELSEIF expression THEN statement*)*
(ELSE statement*)?
END
;
Now the semantics match the visual structure:
# Else-if chain (one end)
if score >= 90 then
grade = "A"
elseif score >= 80 then
grade = "B"
else
grade = "F"
end
# Nested if inside else (two ends)
if a then
# foo
else
if b then
# bar
end
end
Breaking Change
This is a breaking change. Scripts using else if (two tokens) will now either:
Parse differently if they happen to have the right number of
ends for nested interpretationFail to parse if they only have one
end(the common case)
Migration
The fix is straightforward-replace else if with elseif:
if quantity >= 10 then
discount = 0.15
- else if quantity >= 5 then
+ elseif quantity >= 5 then
discount = 0.10
end