diff --git a/src/main.rs b/src/main.rs index b5166e3..f1e98ff 100644 --- a/src/main.rs +++ b/src/main.rs @@ -110,8 +110,13 @@ mod test { } #[test] - fn if_expr() -> Result<()> { - load_and_run("test/if.rush") + fn if_base() -> Result<()> { + load_and_run("test/base_if.rush") + } + + #[test] + fn if_else() -> Result<()> { + load_and_run("test/if_else.rush") } #[test] diff --git a/src/parser/ast.rs b/src/parser/ast.rs index 68c056b..fbd7afb 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -275,33 +275,70 @@ impl Tree { fn parse_if(&mut self, end: usize) -> Result { self.inc(); let condition = self.get_expression(end).with_context(|| "Error getting condition for if expression")?; - dbg!(&condition); let mut contents = Vec::new(); loop { - match self.get_next_token() { + match self.get_current_token() { Tokens::End => break, - Tokens::Space => { self.inc(); }, + Tokens::Space => {}, + Tokens::Else => break, + Tokens::CommandEnd(_) => {} _ => contents.push(self.get_expression(end).with_context(|| "Error getting contents for if expression")?) }; + self.inc(); + } + loop { + match self.get_current_token() { + Tokens::CommandEnd(_) => { self.inc(); }, + Tokens::Space => { self.inc(); }, + _ => break + } } let mut else_contents = Vec::new(); + if matches!(self.get_current_token(), Tokens::Else) { + self.inc(); + loop { + match self.get_current_token() { + Tokens::End => break, + Tokens::Space => {}, + Tokens::CommandEnd(_) => {} + Tokens::Else => break, + Tokens::If => { + else_contents.push(self.get_expression(end).with_context(|| "Error getting contents for if expression")?); + if else_contents.len() == 1 { break }; + } + _ => else_contents.push(self.get_expression(end).with_context(|| "Error getting contents for if expression")?) + }; + self.inc(); + } + } + if self.i < self.tokens.len() { + loop { + match self.get_current_token() { + Tokens::CommandEnd(_) => { self.inc(); }, + Tokens::Space => { self.inc(); }, + _ => break + } + if self.i >= self.tokens.len() - 1 { break } + } + self.inc(); + } Ok(IfExpression { condition: Box::new(condition), contents, else_contents }) } fn parse_while(&mut self, end: usize) -> Result { self.inc(); let condition = self.get_expression(end).with_context(|| "Error getting condition for while expression")?; - dbg!(&condition); - dbg!(self.i); let mut contents = Vec::new(); + self.inc(); loop { - let token = self.get_next_token(); - dbg!(token, matches!(token, Tokens::End)); + let token = self.get_current_token(); match token { Tokens::End => break, + Tokens::Else => bail!("Unexpected ELSE. Support for ELSE statements after WHILE may come later."), + Tokens::CommandEnd(_) => { self.inc(); }, + Tokens::Space => { self.inc(); }, _ => contents.push(self.get_expression(end).with_context(|| "Error getting contents for while expression")?) }; - dbg!(&contents); } self.inc(); Ok(WhileExpression { condition: Box::new(condition), contents }) @@ -404,9 +441,10 @@ impl Tree { } fn get_expression(&mut self, end: usize) -> Result { - let mut token = self.get_current_token(); let mut expr: Option = None; + let mut token = self.get_current_token(); loop { + dbg!(token); match token { Tokens::Space => {self.inc();}, Tokens::CommandEnd(_) => { if matches!(expr, Some(_)) { break }; self.inc();}, @@ -460,14 +498,14 @@ impl Tree { _ => expr = Some(self.parse_call(end)?) }, Tokens::Else => bail!("Unexpected token ELSE"), - Tokens::End => bail!("Unexpected token END\nCurrent expression:{:?}", expr), + Tokens::End => { dbg!(expr); bail!("Unexpected token END"); }, Tokens::For => match expr { Some(_) => bail!("Commands must be ended properly"), None => expr = Some(Expression::ForExpression(self.parse_for(end)?)), }, Tokens::If => match expr { Some(_) => bail!("Commands must be ended properly"), - None => expr = Some(Expression::IfExpression(self.parse_if(end)?)), + None => {expr = Some(Expression::IfExpression(self.parse_if(end)?)); dbg!(&expr); }, } Tokens::Let => return Ok(self.parse_let(end)?), Tokens::While => return Ok(Expression::WhileExpression(self.parse_while(end)?)), @@ -501,6 +539,7 @@ impl Tree { Tokens::JobCommandEnd => bail!("Jobs not yet implemented") } if self.i >= end - 1 { break } + dbg!("finished loop", &expr); token = self.get_current_token(); } match expr { @@ -526,6 +565,7 @@ pub fn build_tree(tokens: Vec) -> Result> { match val { Ok(val) => expressions.push(val), Err(error) => { + if error.to_string() == "No expression found" { break } dbg!(tree); return Err(error); } diff --git a/src/parser/exec.rs b/src/parser/exec.rs index e40b075..863be9a 100644 --- a/src/parser/exec.rs +++ b/src/parser/exec.rs @@ -215,21 +215,20 @@ impl ExecExpression for IfExpression { None => bail!("Invalid IF expression"), Some(cmd) => cmd }; + ctx.add_scope(); let res = match condition.spawn() { Result::Err(_) => { - Some(condition) + self.else_contents.exec(ctx)? }, Result::Ok(mut res) => { if !res.wait()?.success() { - Some(condition) + self.else_contents.exec(ctx)? } else { - ctx.add_scope(); - let res = self.contents.exec(ctx)?; - ctx.pop_scope(); - res + self.contents.exec(ctx)? } } }; + ctx.pop_scope(); Ok(res) } diff --git a/src/parser/tokens.rs b/src/parser/tokens.rs index 3eb0657..c7e2872 100644 --- a/src/parser/tokens.rs +++ b/src/parser/tokens.rs @@ -175,11 +175,13 @@ pub fn tokenize(reader: &mut dyn std::io::BufRead) -> Result> { ';' | '\r' | '\n' => if !escape_active && !quote_active && !double_quote_active { save_buf(&mut buf, &mut tokens); tokens.push(Tokens::CommandEnd(letter.clone())); - let mut x = i; + let mut x = 0; while x < text.len() - 1 && matches!(text.chars().nth(x).unwrap(), '\n' | '\r' | ';' | ' ') { x += 1; } - skipper = x - i - 1; + if x > 0 { + skipper = x - 1; + } buf_add = false; }, '&' => if !escape_active && !quote_active && !double_quote_active { @@ -233,6 +235,15 @@ pub fn tokenize(reader: &mut dyn std::io::BufRead) -> Result> { tokens.push(Tokens::ExportSet); buf_add = false; }, + '#' => if !escape_active && !quote_active && !double_quote_active { + save_buf(&mut buf, &mut tokens); + buf_add = false; + let mut x = 0; + while x + i + 1 < text.len() && text.chars().nth(x + i + 1).unwrap() != '\n' { + x += 1; + } + skipper = x; + } _ => {} } if letter.clone() != '\\' { escape_active = false; } diff --git a/test/base_if.rush b/test/base_if.rush new file mode 100644 index 0000000..af4f3c2 --- /dev/null +++ b/test/base_if.rush @@ -0,0 +1,3 @@ +if true + echo condition true +end \ No newline at end of file diff --git a/test/if.rush b/test/if_else.rush similarity index 63% rename from test/if.rush rename to test/if_else.rush index 23be651..7d357fe 100644 --- a/test/if.rush +++ b/test/if_else.rush @@ -1,12 +1,3 @@ - -if true - echo condition true -end - -if false - echo condition false -end - if true echo condition true else