Add parsing of elseif and else

This commit is contained in:
Sofia 2026-03-19 17:31:12 +02:00
parent 0faeeae0ea
commit b6a38101f7
4 changed files with 73 additions and 58 deletions

View File

@ -1,49 +1,10 @@
global b = 5
function add(x) local test = 10
return function (y) if test == 10 then
x = x + 1 print("first")
b = b + 1 elseif test == 11 then
return x + y, 1, 2, b print("second")
end else
print("third")
end end
print("after")
function min(x, y)
local m = x
if y < x then
m = y
end
return m
end
function f(x, ...)
local b = {10, ..., add(10)(15)}
return x + 5, b
end
global sometable = {}
sometable["hello"] = { 100, 150, add(10)(15) }
print(#sometable["hello"])
sometable["hello"].there = "my dude"
print(sometable.hello.there)
print(max(11.12345, 9))
print(add(10)(15))
print(add(10)(15))
print(b)
print(min(11, 9))
print(10 - 15)
print("hello there!")
print(true or 0)
global value, table = f(10, 11, 12)
print("hello")
for i=1,#table do
print(table[i])
if i > 2 then
goto test
end
end
::test::

View File

@ -234,7 +234,12 @@ impl Parse for Block {
while !matches!( while !matches!(
stream.peek(), stream.peek(),
Some(Token::Keyword(Keyword::End) | Token::Eof) Some(
Token::Keyword(Keyword::End)
| Token::Keyword(Keyword::ElseIf)
| Token::Keyword(Keyword::Else)
| Token::Eof
)
) { ) {
statements.push(stream.parse()?); statements.push(stream.parse()?);
} }
@ -254,7 +259,11 @@ pub enum Statement {
ExpressionList, ExpressionList,
), ),
Return(ExpressionList), Return(ExpressionList),
If(Node<Expression>, Block), If {
if_part: (Node<Expression>, Block),
elif: Vec<(Node<Expression>, Block)>,
else_block: Block,
},
Expression(Node<Expression>), Expression(Node<Expression>),
NumericalFor( NumericalFor(
Node<String>, Node<String>,
@ -296,11 +305,35 @@ impl Parse for Statement {
Ok(Statement::Return(stream.parse()?)) Ok(Statement::Return(stream.parse()?))
} else if peeked == Some(Token::Keyword(Keyword::If)) { } else if peeked == Some(Token::Keyword(Keyword::If)) {
stream.next(); // Consume if stream.next(); // Consume if
let cond = stream.parse()?; let if_cond = stream.parse()?;
stream.expect(Token::Keyword(Keyword::Then))?; stream.expect(Token::Keyword(Keyword::Then))?;
let then = stream.parse()?; let if_block = stream.parse()?;
let mut elif = Vec::new();
while let Some(Token::Keyword(Keyword::ElseIf)) = stream.peek() {
stream.next();
let elif_cond = stream.parse()?;
stream.expect(Token::Keyword(Keyword::Then))?;
let elif_block = stream.parse()?;
elif.push((elif_cond, elif_block));
}
let else_block = if let Some(Token::Keyword(Keyword::Else)) = stream.peek() {
stream.next();
stream.parse()?
} else {
Block {
statements: Vec::new(),
_meta: Metadata::empty(),
}
};
stream.expect(Token::Keyword(Keyword::End))?; stream.expect(Token::Keyword(Keyword::End))?;
Ok(Self::If(cond, then)) Ok(Self::If {
if_part: (if_cond, if_block),
elif: elif,
else_block,
})
} else if let Some(Token::Keyword(Keyword::Local | Keyword::Global)) = peeked { } else if let Some(Token::Keyword(Keyword::Local | Keyword::Global)) = peeked {
let access_modifier = match stream.next() { let access_modifier = match stream.next() {
Some(Token::Keyword(Keyword::Local)) => AccessModifier::Local, Some(Token::Keyword(Keyword::Local)) => AccessModifier::Local,

View File

@ -187,10 +187,21 @@ impl Statement {
} }
constants constants
} }
Statement::If(cond, then) => { Statement::If {
if_part,
elif,
else_block,
} => {
let mut constants = HashSet::new(); let mut constants = HashSet::new();
constants.extend(cond.kind.find_constants(scope)); constants.extend(if_part.0.kind.find_constants(scope));
constants.extend(then.find_constants(scope, Vec::new())); constants.extend(if_part.1.find_constants(scope, Vec::new()));
for (cond, block) in elif {
constants.extend(cond.kind.find_constants(scope));
constants.extend(block.find_constants(scope, Vec::new()));
}
constants.extend(else_block.find_constants(scope, Vec::new()));
constants constants
} }
Statement::Expression(expr) => expr.kind.find_constants(scope), Statement::Expression(expr) => expr.kind.find_constants(scope),
@ -397,8 +408,12 @@ impl Statement {
}, },
))); )));
} }
Statement::If(expr, block) => { Statement::If {
let (instr, regs) = expr.kind.compile(state, scope, Some(1)); if_part,
elif,
else_block,
} => {
let (instr, regs) = if_part.0.kind.compile(state, scope, Some(1));
instructions.extend(instr); instructions.extend(instr);
let local = scope.register_counter.next(); let local = scope.register_counter.next();
@ -408,7 +423,7 @@ impl Statement {
0, 0,
))); )));
let block_instructions = block.compile(state, scope); let block_instructions = if_part.1.compile(state, scope);
instructions.push(PreInstr::Instr(Instruction::Jmp( instructions.push(PreInstr::Instr(Instruction::Jmp(
block_instructions.len() as i32 block_instructions.len() as i32
))); )));

View File

@ -15,6 +15,8 @@ pub enum Keyword {
Global, Global,
Return, Return,
If, If,
ElseIf,
Else,
Then, Then,
True, True,
False, False,
@ -35,6 +37,8 @@ impl Keyword {
"global" => Keyword::Global, "global" => Keyword::Global,
"return" => Keyword::Return, "return" => Keyword::Return,
"if" => Keyword::If, "if" => Keyword::If,
"elseif" => Keyword::ElseIf,
"else" => Keyword::Else,
"then" => Keyword::Then, "then" => Keyword::Then,
"true" => Keyword::True, "true" => Keyword::True,
"false" => Keyword::False, "false" => Keyword::False,
@ -58,6 +62,8 @@ impl ToString for Keyword {
Keyword::Global => "global", Keyword::Global => "global",
Keyword::Return => "return", Keyword::Return => "return",
Keyword::If => "if", Keyword::If => "if",
Keyword::ElseIf => "elif",
Keyword::Else => "else",
Keyword::Then => "then", Keyword::Then => "then",
Keyword::True => "true", Keyword::True => "true",
Keyword::False => "false", Keyword::False => "false",