|
|
@ -16,7 +16,7 @@ pub enum Value {
|
|
|
|
|
|
|
|
|
|
|
|
/// The children of a statement symbol make up the components of what will become a statement
|
|
|
|
/// The children of a statement symbol make up the components of what will become a statement
|
|
|
|
/// in our ast
|
|
|
|
/// in our ast
|
|
|
|
Statement,
|
|
|
|
Command,
|
|
|
|
|
|
|
|
|
|
|
|
/// Each of the tokens from the lex stage becomes a terminal node on our tree
|
|
|
|
/// Each of the tokens from the lex stage becomes a terminal node on our tree
|
|
|
|
Terminal(Token),
|
|
|
|
Terminal(Token),
|
|
|
@ -220,7 +220,7 @@ impl<'text> Parser<'text> {
|
|
|
|
fn step(&mut self) -> Result<bool, ParseError> {
|
|
|
|
fn step(&mut self) -> Result<bool, ParseError> {
|
|
|
|
match self.output.value() {
|
|
|
|
match self.output.value() {
|
|
|
|
Value::Start => self.step_start(),
|
|
|
|
Value::Start => self.step_start(),
|
|
|
|
Value::Statement => self.step_statement(),
|
|
|
|
Value::Command => self.step_statement(),
|
|
|
|
Value::Terminal(_) => panic!(),
|
|
|
|
Value::Terminal(_) => panic!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -229,7 +229,7 @@ impl<'text> Parser<'text> {
|
|
|
|
assert!(matches!(self.output.value(), Value::Start));
|
|
|
|
assert!(matches!(self.output.value(), Value::Start));
|
|
|
|
match self.input.peek()? {
|
|
|
|
match self.input.peek()? {
|
|
|
|
Some(Token::Word(_)) => {
|
|
|
|
Some(Token::Word(_)) => {
|
|
|
|
self.output.push(Value::Statement)?;
|
|
|
|
self.output.push(Value::Command)?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
self.output.up()?;
|
|
|
|
self.output.up()?;
|
|
|
@ -240,19 +240,23 @@ impl<'text> Parser<'text> {
|
|
|
|
Err(ParseError::UnexpectedToken(token))
|
|
|
|
Err(ParseError::UnexpectedToken(token))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Some(Token::Semi(_)) => {
|
|
|
|
Some(Token::Semi(_)) => {
|
|
|
|
self.output.push(Value::Statement)?;
|
|
|
|
self.output.push(Value::Command)?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
self.output.up()?;
|
|
|
|
self.output.up()?;
|
|
|
|
self.output.up()?;
|
|
|
|
self.output.up()?;
|
|
|
|
Ok(true)
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(Token::Pipe(_)) => {
|
|
|
|
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
|
|
|
|
Err(ParseError::UnexpectedToken(token))
|
|
|
|
|
|
|
|
}
|
|
|
|
None => Ok(false),
|
|
|
|
None => Ok(false),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn step_statement(&mut self) -> Result<bool, ParseError> {
|
|
|
|
fn step_statement(&mut self) -> Result<bool, ParseError> {
|
|
|
|
assert!(matches!(self.output.value(), Value::Statement));
|
|
|
|
assert!(matches!(self.output.value(), Value::Command));
|
|
|
|
match self.input.peek()? {
|
|
|
|
match self.input.peek()? {
|
|
|
|
Some(Token::Word(_) | Token::Glob(_)) => {
|
|
|
|
Some(Token::Word(_) | Token::Glob(_)) => {
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
@ -260,6 +264,9 @@ impl<'text> Parser<'text> {
|
|
|
|
self.output.up()?;
|
|
|
|
self.output.up()?;
|
|
|
|
Ok(true)
|
|
|
|
Ok(true)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(Token::Pipe(_)) => {
|
|
|
|
|
|
|
|
todo!()
|
|
|
|
|
|
|
|
}
|
|
|
|
Some(Token::Semi(_)) => {
|
|
|
|
Some(Token::Semi(_)) => {
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
let token = self.input.next().unwrap()?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
|
self.output.push(Value::Terminal(token))?;
|
|
|
@ -272,6 +279,29 @@ impl<'text> Parser<'text> {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a b
|
|
|
|
|
|
|
|
command
|
|
|
|
|
|
|
|
terminal
|
|
|
|
|
|
|
|
a
|
|
|
|
|
|
|
|
terminal
|
|
|
|
|
|
|
|
b
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a | b
|
|
|
|
|
|
|
|
pipeline
|
|
|
|
|
|
|
|
command
|
|
|
|
|
|
|
|
terminal
|
|
|
|
|
|
|
|
a
|
|
|
|
|
|
|
|
terminal
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
command
|
|
|
|
|
|
|
|
terminal
|
|
|
|
|
|
|
|
b
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
|
|
|
use super::*;
|
|
|
@ -297,7 +327,7 @@ mod test {
|
|
|
|
|
|
|
|
|
|
|
|
let mut tokens = lex(" ls ").unwrap();
|
|
|
|
let mut tokens = lex(" ls ").unwrap();
|
|
|
|
let ls = tokens.pop().unwrap();
|
|
|
|
let ls = tokens.pop().unwrap();
|
|
|
|
assert!(cursor.push(Value::Statement).is_ok());
|
|
|
|
assert!(cursor.push(Value::Command).is_ok());
|
|
|
|
assert!(cursor.push(Value::Terminal(ls.clone())).is_ok());
|
|
|
|
assert!(cursor.push(Value::Terminal(ls.clone())).is_ok());
|
|
|
|
assert!(cursor.push(Value::Terminal(ls.clone())).is_err());
|
|
|
|
assert!(cursor.push(Value::Terminal(ls.clone())).is_err());
|
|
|
|
assert!(cursor.target.value == Value::Terminal(ls));
|
|
|
|
assert!(cursor.target.value == Value::Terminal(ls));
|
|
|
|