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 if

with

elseif

The 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:

  1. Visual layout lies to the reader. Indentation suggests nesting, but the parser ignores it.

  2. Impossible to express nested if-in-else. There was no way to write a genuinely nested if inside an else block-the parser would always consume ELSE IF as an else-if chain.

  3. 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 interpretation

  • Fail 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
Previous
Previous

Jyro 0.7.5

Next
Next

Jyro 0.7.1