Add parsing of elseif and else
This commit is contained in:
parent
0faeeae0ea
commit
b6a38101f7
@ -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::
|
|
||||||
|
|||||||
43
src/ast.rs
43
src/ast.rs
@ -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,
|
||||||
|
|||||||
@ -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(if_part.0.kind.find_constants(scope));
|
||||||
|
constants.extend(if_part.1.find_constants(scope, Vec::new()));
|
||||||
|
|
||||||
|
for (cond, block) in elif {
|
||||||
constants.extend(cond.kind.find_constants(scope));
|
constants.extend(cond.kind.find_constants(scope));
|
||||||
constants.extend(then.find_constants(scope, Vec::new()));
|
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
|
||||||
)));
|
)));
|
||||||
|
|||||||
@ -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",
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user