diff --git a/src/parser/ast.rs b/src/parser/ast.rs index aa22e7b..68c056b 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -296,14 +296,14 @@ impl Tree { let mut contents = Vec::new(); loop { let token = self.get_next_token(); - dbg!(token); + dbg!(token, matches!(token, Tokens::End)); match token { Tokens::End => break, - 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 }) } @@ -411,6 +411,7 @@ impl Tree { Tokens::Space => {self.inc();}, Tokens::CommandEnd(_) => { if matches!(expr, Some(_)) { break }; self.inc();}, Tokens::Literal(_) => if matches!(expr, Some(_)) { + dbg!(expr); bail!("Unexpected literal. After file redirect, you need to use a semicolon or newline."); } else { expr = Some(self.parse_call(end)?); @@ -492,6 +493,7 @@ impl Tree { }, Tokens::Break => match expr { None => { + self.inc(); expr = Some(Expression::BreakExpression(BreakExpression { num: Box::new(self.get_value(end)?)})); }, Some(_) => bail!("Unexpected break") diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 56f6205..179e759 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -9,9 +9,7 @@ use crate::parser::tokens::{tokenize}; use anyhow::Result; pub fn exec(reader: &mut dyn std::io::BufRead, ctx: &mut vars::Context) -> Result<()> { - let tokens = tokenize(reader).unwrap(); - - dbg!(&tokens); + let tokens = tokenize(reader)?; let expressions = build_tree(tokens)?; diff --git a/src/parser/tokens.rs b/src/parser/tokens.rs index 527895a..3eb0657 100644 --- a/src/parser/tokens.rs +++ b/src/parser/tokens.rs @@ -1,4 +1,4 @@ -use std::io; +use anyhow::{Result, bail}; #[derive(Debug)] pub enum Tokens { @@ -46,6 +46,8 @@ impl Tokens { "<" => Tokens::FileRead, "|" => Tokens::RedirectInto, "\r\n" | "\n" | ";" => Tokens::CommandEnd(str.chars().nth(0).unwrap()), + "&&" => Tokens::And, + "||" => Tokens::Or, "=" => Tokens::ExportSet, "break" => Tokens::Break, _ => Tokens::Literal(str) @@ -88,6 +90,7 @@ fn read_var_ahead(i: usize, text: &String) -> (usize, Tokens) { let mut x = i; let mut buf = String::new(); let parens_mode = text.chars().nth(x + 1).unwrap() == '{'; + if parens_mode { x += 1 } loop { x += 1; let letter: char = text.chars().nth(x).unwrap(); @@ -106,7 +109,7 @@ fn read_var_ahead(i: usize, text: &String) -> (usize, Tokens) { x += 1; break; } - _ => { if !parens_mode { break } else { panic!("Invalid variable name") } } + l => { if !parens_mode { break } else { panic!("Invalid variable name (starting with '{:?}{:?}')", buf, l) } } } } let token = match text.chars().nth(i).unwrap() { @@ -117,12 +120,12 @@ fn read_var_ahead(i: usize, text: &String) -> (usize, Tokens) { (x - i - 1, token) } -pub fn tokenize(reader: &mut dyn std::io::BufRead) -> io::Result> { +pub fn tokenize(reader: &mut dyn std::io::BufRead) -> Result> { let mut quote_active = false; let mut double_quote_active = false; let mut escape_active = false; let mut text = String::new(); - reader.read_to_string(&mut text); + reader.read_to_string(&mut text)?; let mut text_length = text.len(); let mut tokens: Vec = Vec::new(); @@ -162,13 +165,43 @@ pub fn tokenize(reader: &mut dyn std::io::BufRead) -> io::Result> { token = Tokens::ArrayFunction(str.clone()); } } - _ => panic!("Cannot happen") + _ => bail!("Cannot happen") } tokens.push(token); skipper = skippers; buf_add = false; } }, + ';' | '\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; + while x < text.len() - 1 && matches!(text.chars().nth(x).unwrap(), '\n' | '\r' | ';' | ' ') { + x += 1; + } + skipper = x - i - 1; + buf_add = false; + }, + '&' => if !escape_active && !quote_active && !double_quote_active { + save_buf(&mut buf, &mut tokens); + if i + 1 < text.len() && text.chars().nth(i+1).unwrap() == '&' { + tokens.push(Tokens::And); + skipper = 1; + } else { + tokens.push(Tokens::JobCommandEnd); + } + buf_add = false; + }, + '|' => if !escape_active && !quote_active && !double_quote_active { + save_buf(&mut buf, &mut tokens); + if i + 1 < text.len() && text.chars().nth(i+1).unwrap() == '|' { + tokens.push(Tokens::Or); + skipper = 1; + } else { + tokens.push(Tokens::RedirectInto); + } + buf_add = false; + }, ' ' => if !escape_active && !quote_active && !double_quote_active { save_buf(&mut buf, &mut tokens); tokens.push(Tokens::Space); @@ -207,9 +240,7 @@ pub fn tokenize(reader: &mut dyn std::io::BufRead) -> io::Result> { buf.push(*letter); } } - if buf.len() > 0 { - tokens.push(Tokens::Literal(buf)); - } + save_buf(&mut buf, &mut tokens); Ok(tokens) } diff --git a/test/simple.rush b/test/simple.rush index d846d06..3f585c6 100644 --- a/test/simple.rush +++ b/test/simple.rush @@ -1,4 +1,3 @@ - echo test echo single; echo line