Skip to content

Commit 0eee0a9

Browse files
committed
feat: If statements
1 parent 61f90c9 commit 0eee0a9

File tree

4 files changed

+139
-19
lines changed

4 files changed

+139
-19
lines changed

packages/engine/src/parser/ast.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,19 @@ pub enum Expression {
1616
ShellCommand(Box<ShellCommand>),
1717
Identifier(Box<Identifier>),
1818
FunctionCall(Box<(Identifier, Vec<Expression>)>),
19-
If(Box<(Expression, WithCursor<Block>, Option<Statement>)>),
19+
If(Box<(WithCursor<Expression>, WithCursor<Block>, Option<Else>)>),
2020
Match(Box<(Expression, Vec<(Expression, Expression)>)>),
2121
}
2222

23+
pub type Else = WithCursor<Block>;
24+
2325

2426
#[derive(lang_macro::EnumVariants, Debug, Clone, PartialEq, Eq)]
2527
pub enum Statement {
2628
While(Box<(WithCursor<Expression>, WithCursor<Block>)>),
2729
For(Box<(Variable, WithCursor<Expression>, WithCursor<Block>)>),
2830
Return(Box<Option<WithCursor<Expression>>>),
31+
If(Box<WithCursor<Expression>>),
2932
Expression(Box<WithCursor<Expression>>),
3033
Continue,
3134
Break,
@@ -124,7 +127,7 @@ impl TryFrom<LexerTokenKind> for LogicalOperator {
124127

125128
fn try_from(value: LexerTokenKind) -> Result<Self, Self::Error> {
126129
Ok(match value {
127-
LexerTokenKind::Equal => Self::Equal,
130+
LexerTokenKind::EqualEqual => Self::Equal,
128131
LexerTokenKind::NotEqual => Self::NotEqual,
129132
LexerTokenKind::LesserThan => Self::LesserThan,
130133
LexerTokenKind::LesserEqualThan => Self::LesserEqualThan,
@@ -156,6 +159,7 @@ impl TryFrom<LexerTokenKind> for AssignmentOperator {
156159
LexerTokenKind::MinusEqual => Self::MinusAssign,
157160
LexerTokenKind::MultiplyEqual => Self::MultiplyAssign,
158161
LexerTokenKind::DivideEqual => Self::DivideAssign,
162+
LexerTokenKind::Equal => Self::Assign,
159163
_ => return Err(ParserErrorKind::ConvertError(value))
160164
})
161165
}

packages/engine/src/parser/error.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ pub enum ParserErrorKind {
99
#[error("couldn't convert lexer token {0} to ast node")]
1010
ConvertError(LexerTokenKind),
1111
#[error("expected token '{0:?}' but found {1:?}")]
12-
ExpectedToken(LexerTokenKind, Option<LexerTokenKind>),
12+
ExpectedToken(Vec<LexerTokenKind>, Option<LexerTokenKind>),
13+
#[error("expected expression")]
14+
ExpectedExpression,
15+
#[error("expected statement")]
16+
ExpectedStatement,
1317
#[error("unexpected token '{0:?}'")]
1418
UnexpectedToken(LexerTokenKind),
1519
#[error("unexpected end of input")]

packages/engine/src/parser/mod.rs

Lines changed: 117 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
use std::{iter::Peekable, slice::Iter};
22

33
use ast::{
4-
ArithmeticOperator, AssignmentOperator, Block, Expression, Function, Literal, LogicalOperator, ProgramTree, Statement, UnaryOperator, Variable
4+
ArithmeticOperator, AssignmentOperator, Block, Expression, Function, Identifier, Literal,
5+
LogicalOperator, ProgramTree, Statement, UnaryOperator, Variable,
56
};
67
use error::ParserResult;
78

@@ -64,12 +65,17 @@ impl<'a> Parser<'a> {
6465
pub fn parse(&mut self) -> ProgramTree {
6566
let mut statements = ProgramTree::new();
6667

67-
while let Some(token) = self.next() {
68+
while let Some(token) = self.peek().cloned() {
6869
match self.parse_statement(token) {
6970
Ok(Some(statement)) => statements.push(statement),
70-
Err(err) => self.add_error(self.token.as_ref().unwrap_or(token).start, self.cursor, err),
71-
_ => {}
71+
Err(err) => {
72+
let token = self.token.as_ref().unwrap_or(token);
73+
self.add_error(token.start, token.end, err)
74+
}
75+
_ => warn!("empty")
7276
}
77+
78+
self.next();
7379
}
7480

7581
statements
@@ -91,17 +97,22 @@ impl<'a> Parser<'a> {
9197
Ok(Some(match &token.kind {
9298
Var => self.var_decl()?,
9399
Function => self.func_decl()?,
100+
If => self.parse_if()?,
94101
EOF | EOL => return Ok(None),
95102

96103
_ => {
97104
let_expr!(expr = self.expression()?);
98105
Statement::Expression(Box::new(expr))
99-
},
106+
}
100107
}))
101108
}
102109

103110
fn var_decl(&mut self) -> ParserResult<Statement> {
104-
Ok(Statement::Variable(Box::from(self.parse_var()?)))
111+
self.expect_token(&LexerTokenKind::Var)?;
112+
let value = self.parse_var()?;
113+
self.expect_terminator()?;
114+
115+
Ok(Statement::Variable(Box::from(value)))
105116
}
106117

107118
fn parse_var(&mut self) -> ParserResult<Variable> {
@@ -129,7 +140,8 @@ impl<'a> Parser<'a> {
129140

130141
fn parse_explicit_type(&mut self) -> ParserResult<Option<String>> {
131142
Ok(if self.next_if_eq(&&LexerTokenKind::Colon).is_some() {
132-
let identifier = self.expect_token(&LexerTokenKind::Identifier)?
143+
let identifier = self
144+
.expect_token(&LexerTokenKind::Identifier)?
133145
.as_identifier()?
134146
.clone();
135147

@@ -140,6 +152,8 @@ impl<'a> Parser<'a> {
140152
}
141153

142154
fn func_decl(&mut self) -> ParserResult<Statement> {
155+
self.expect_token(&LexerTokenKind::Function)?;
156+
143157
let identifier = self
144158
.expect_token(&LexerTokenKind::Identifier)?
145159
.as_identifier()?
@@ -149,7 +163,7 @@ impl<'a> Parser<'a> {
149163

150164
let parameters = if self.next_if_eq(&&LexerTokenKind::RParen).is_none() {
151165
let mut variables = vec![];
152-
166+
153167
while let Some(token) = self.peek() {
154168
if token.kind == LexerTokenKind::RParen {
155169
break;
@@ -185,18 +199,86 @@ impl<'a> Parser<'a> {
185199
Ok(Statement::Function(Box::from(function)))
186200
}
187201

202+
fn parse_if(&mut self) -> ParserResult<Statement> {
203+
self.expect_token(&LexerTokenKind::If)?;
204+
205+
if let Some(expr) = self.if_expr()? {
206+
Ok(Statement::If(Box::from(expr)))
207+
} else {
208+
Err(ParserErrorKind::UnexpectedEnd)
209+
}
210+
}
211+
212+
fn if_expr(&mut self) -> ParserResult<Option<WithCursor<Expression>>> {
213+
let_expr!(condition = self.expression()?);
214+
215+
let start = self.cursor;
216+
217+
218+
let truthy_block = if self.next_if_eq(&&LexerTokenKind::LBracket).is_some() {
219+
self.parse_block()?
220+
} else if self.next_if_eq(&&LexerTokenKind::Colon).is_some() {
221+
self.parse_inline_block()?
222+
} else {
223+
return Err(ParserErrorKind::ExpectedExpression);
224+
};
225+
226+
self.next();
227+
228+
let else_condition = if self.next_if_eq(&&LexerTokenKind::Else).is_some() {
229+
let start = self.cursor;
230+
231+
Some(match self.peek().map(|t| t.kind.clone()) {
232+
Some(LexerTokenKind::LBracket) => {
233+
self.next();
234+
self.parse_block()?
235+
},
236+
Some(LexerTokenKind::Colon) => {
237+
self.next();
238+
self.parse_inline_block()?
239+
},
240+
_ => {
241+
let stmt = self.parse_if()?;
242+
WithCursor::create_with(start, self.cursor, vec![stmt])
243+
},
244+
})
245+
} else {
246+
None
247+
};
248+
249+
let if_expr = Expression::If(Box::from((condition, truthy_block, else_condition)));
250+
251+
Ok(Some(WithCursor::create_with(start, self.cursor, if_expr)))
252+
}
253+
254+
fn parse_inline_block(&mut self) -> ParserResult<WithCursor<Block>> {
255+
let Some(next) = self.next() else {
256+
return Err(ParserErrorKind::ExpectedStatement);
257+
};
258+
259+
let start = self.cursor;
260+
let Some(stmt) = self.parse_statement(next)? else {
261+
return Err(ParserErrorKind::ExpectedStatement);
262+
};
263+
264+
Ok(WithCursor::create_with(start, self.cursor, vec![stmt]))
265+
}
266+
267+
188268
fn parse_block(&mut self) -> ParserResult<WithCursor<Block>> {
189269
let mut block = Block::new();
190270
let start = self.cursor;
191271

192-
while let Some(token) = self.next() {
272+
while let Some(token) = self.peek().cloned() {
193273
if token.kind == LexerTokenKind::RBracket {
194274
break;
195275
}
196276

197277
if let Some(statement) = self.parse_statement(token)? {
198278
block.push(statement);
199279
}
280+
281+
self.next();
200282
}
201283

202284
Ok(WithCursor::create_with(start, self.cursor, block))
@@ -210,7 +292,7 @@ impl<'a> Parser<'a> {
210292
let_expr!(lhs = self.logic_or()?);
211293

212294
if let Some(op_token) = self.next_if_eq_mul(&[
213-
&LexerTokenKind::EqualEqual,
295+
&LexerTokenKind::Equal,
214296
&LexerTokenKind::PlusEqual,
215297
&LexerTokenKind::MinusEqual,
216298
&LexerTokenKind::MultiplyEqual,
@@ -409,7 +491,7 @@ impl<'a> Parser<'a> {
409491
}
410492

411493
fn literals(&mut self) -> ParserResult<Option<WithCursor<Expression>>> {
412-
let_expr!(token = self.next());
494+
let_expr!(token = self.peek());
413495

414496
let expr = match token.kind {
415497
LexerTokenKind::String => Expression::Literal(Box::from(Literal::String(Box::from(
@@ -424,23 +506,45 @@ impl<'a> Parser<'a> {
424506
Expression::Literal(Box::from(Literal::Boolean(*token.as_boolean()?)))
425507
}
426508

509+
LexerTokenKind::Identifier => {
510+
Expression::Identifier(Box::from(Identifier::from(token.as_identifier()?)))
511+
}
512+
427513
LexerTokenKind::ShellCommand => {
428514
Expression::ShellCommand(Box::from(token.as_shell_command()?.to_owned()))
429515
}
430516

431517
LexerTokenKind::EOL | LexerTokenKind::EOF => return Ok(None),
432518

433-
_ => return Err(ParserErrorKind::UnexpectedToken(token.kind.clone())),
519+
_ => {
520+
let token = token.to_owned();
521+
self.cursor_next(&token);
522+
return Err(ParserErrorKind::UnexpectedToken(token.kind.clone()))
523+
},
434524
};
435525

526+
let token = token.to_owned();
527+
self.next();
528+
436529
Ok(Some(WithCursor::create_with(token.start, token.end, expr)))
437530
}
438531

439532
fn expect_token(&mut self, expected: &'a LexerTokenKind) -> ParserResult<&LexerToken> {
440533
self.expect(&expected).map_err(|found| {
441-
ParserErrorKind::ExpectedToken(expected.clone(), found.map(|t| t.kind.clone()))
534+
ParserErrorKind::ExpectedToken(vec![expected.clone()], found.map(|t| t.kind.clone()))
442535
})
443536
}
537+
538+
fn expect_terminator(&mut self) -> ParserResult<()> {
539+
match self.peek().map(|t| t.kind.clone()) {
540+
Some(LexerTokenKind::EOL) | Some(LexerTokenKind::EOF) | None => {
541+
Ok(())
542+
},
543+
found => {
544+
Err(ParserErrorKind::ExpectedToken(vec![LexerTokenKind::EOL, LexerTokenKind::EOF], found))
545+
}
546+
}
547+
}
444548
}
445549

446550
impl ComponentErrors for Parser<'_> {

script.tsh

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1-
fn test(param: Int = 5, lol: Str) {
2-
var test = 5
3-
}
1+
var test
2+
3+
if a {
4+
test = 5
5+
} else if true {
6+
test = 10
7+
} else {
8+
test = 15
9+
}
10+
11+
var cool = test - 10

0 commit comments

Comments
 (0)