diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eb5a316 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +target diff --git a/src/lang.rs b/src/lang.rs index 4bce7c7..c01d8f7 100644 --- a/src/lang.rs +++ b/src/lang.rs @@ -1,104 +1,120 @@ -#[derive(Debug, Clone)] +#[derive(Clone)] struct Reader<'a> { - slice: &'a str, - full: &'a str, + slice: &'a str, + full: &'a str, } #[derive(Debug)] struct Error(String); impl Error { - fn new(message: &str, reader: &Reader) -> Result { - Err(Error(message.to_string())) - } + fn new(message: &str, _reader: &Reader) -> Result { + Err(Error(message.to_string())) + } } +type Comment = String; + #[derive(Debug)] struct Piece { - index: usize, - width: usize, - it: T, + comment: Comment, + index: usize, + width: usize, + it: T, } impl Piece { - fn of(it: T, reader: &Reader, width: usize) -> Piece { - Piece { - it, - index: reader.slice.as_ptr() as usize - reader.full.as_ptr() as usize, - width + fn of(it: T, reader: &Reader, width: usize) -> Piece { + Piece { + it, + index: reader.slice.as_ptr() as usize - reader.full.as_ptr() as usize, + width, + comment: String::new() + } } - } - fn from(it: T, begin: &Piece, end: &Piece) -> Piece { - Piece { - it, - index: begin.index, - width: end.index + end.width - begin.index + fn from(it: T, begin: &Piece, end: &Piece) -> Piece { + Piece { + it, + index: begin.index, + width: end.index + end.width - begin.index, + comment: String::new() + } } - } - fn null(&self) -> Piece<()> { - Piece { - it: (), - index: self.index, - width: self.width + fn null(&self) -> Piece<()> { + Piece { + it: (), + index: self.index, + width: self.width, + comment: String::new() + } } - } } // Strips comments and whitespace // todo: implement comments returning for debugging. impl<'a> From<&'a str> for Reader<'a> { - fn from(str: &'a str) -> Self { - Reader { - full: str, - slice: str + fn from(str: &'a str) -> Self { + Reader { + full: str, + slice: str, + } } - } } impl<'a> Reader<'a> { - fn trim(&mut self) -> Result<&Self,Error> { - self.slice = self.slice.trim_start(); - if self.slice.starts_with("--") { - if self.slice[2..].starts_with("[[") { - match self.slice.find("]]") { - Some(i) => { - self.slice = &self.slice[i+2..].trim(); + fn trim(&mut self) -> Result { + self.slice = self.slice.trim_start(); + if self.slice.starts_with("--") { + let comment = if self.slice[2..].starts_with("[[") { + match self.slice.find("]]") { + Some(i) => { + let comment = &self.slice[4..i + 2]; + self.slice = &self.slice[i + 2..].trim(); + Ok(comment) + } + _ => self.error("Unterminated multi-line comment"), + } + } else { + let comment; + if let Some(i) = self.slice.find("\n") { + self.slice = &self.slice[i + 1..].trim(); + comment = &self.slice[2..i+1]; + } else { + self.slice = &self.slice[..self.slice.len() - 1]; + comment = &self.slice[2..]; + } + Ok(comment) + }?; + self.trim().map(|it| { + it + comment + }) + } else { + Ok(String::new()) + } + } + fn consume(&mut self, start: &str) -> Result<&Self, Error> { + self.trim()?; + if self.slice.starts_with(start) { + self.slice = &self.slice[start.len()..]; Ok(self) - } - _ => { - self.error("Unterminated multi-line comment") - } + } else { + self.error(format!("Expected '{}'", start).as_str()) } - } else { - if let Some(i) = self.slice.find("\n") { - self.slice = &self.slice[i+1..].trim(); - } - Ok(self) - } - } else { - Ok(self) } - } - fn consume(&mut self, start: &str) -> Result<&Self,Error> { - self.trim()?; - if self.slice.starts_with(start) { - self.slice = &self.slice[start.len()..]; - Ok(self) - } else { - self.error(format!("Expected '{}'",start).as_str()) + fn take(&mut self) -> Result, Error> + where + T: Parse, + { + self.trim()?; + T::consume(self) + } + fn error(&self, message: &str) -> Result { + Error::new(message, self) + } + fn marker(&self) -> Piece<()> { + Piece::of((), self, 0) } - } - fn take(&mut self) -> Result,Error> where T: Parse { - self.trim()?; - T::consume(self) - } - fn error(&self, message: &str) -> Result { - Error::new(message,self) - } - fn marker(&self) -> Piece<()> { - Piece::of((),self,0) - } } #[derive(Debug)] @@ -110,470 +126,535 @@ struct Name(String); // - ??? // - The reader may have not been trimmed trait Parse { - fn consume(reader: &mut Reader) -> Result, Error> - where Self: Sized; + fn consume(reader: &mut Reader) -> Result, Error> + where + Self: Sized; } impl Parse for Name { - fn consume(reader: &mut Reader) -> Result, Error> - where - Self: Sized - { - reader.trim()?; - let mut chars = reader.slice.chars(); - let mut end = 1; - match chars.next() { - None => { - return reader.error("Expected identifier"); - } - Some(c) => { - if !(c.is_alphabetic() || c == '_') { - return reader.error("Identifier must begin with alphabetic character") - } - } - }; - end += chars.take_while(|c| { c.is_alphanumeric() || *c == '_' }).count(); - let result = Ok(Piece::of(Name(reader.slice[..end].to_string()),reader,end)); - reader.slice = &reader.slice[end..]; - result - } + fn consume(reader: &mut Reader) -> Result, Error> + where + Self: Sized, + { + reader.trim()?; + let mut chars = reader.slice.chars(); + let mut end = 1; + match chars.next() { + None => { + return reader.error("Expected identifier"); + } + Some(c) => { + if !(c.is_alphabetic() || c == '_') { + return reader.error("Identifier must begin with alphabetic character"); + } + } + }; + end += chars + .take_while(|c| c.is_alphanumeric() || *c == '_') + .count(); + let result = Ok(Piece::of( + Name(reader.slice[..end].to_string()), + reader, + end, + )); + reader.slice = &reader.slice[end..]; + result + } } impl Parse for Number { - fn consume(reader: &mut Reader) -> Result, Error> - where - Self: Sized - { - reader.trim()?; - let mut end; - if reader.slice.starts_with("0x") { - end = reader.slice[2..].chars().take_while(|c| c.is_digit(16)).count()+2; - if end == 2 { end = 0 } - } else { - end = reader.slice.chars().take_while(|c| c.is_digit(10) || *c == '.').count(); + fn consume(reader: &mut Reader) -> Result, Error> + where + Self: Sized, + { + reader.trim()?; + let mut end; + if reader.slice.starts_with("0x") { + end = reader.slice[2..] + .chars() + .take_while(|c| c.is_digit(16)) + .count() + + 2; + if end == 2 { + end = 0 + } + } else { + end = reader + .slice + .chars() + .take_while(|c| c.is_digit(10) || *c == '.') + .count(); + } + if end == 0 { + reader.error("Could not parse number".into()) + } else { + reader.slice = &reader.slice[end..]; + Ok(Piece::of( + Number(reader.slice[..end].to_string()), + reader, + end, + )) + } } - if end == 0 { - reader.error("Could not parse number".into()) - } else { - reader.slice = &reader.slice[end..]; - Ok(Piece::of(Number(reader.slice[..end].to_string()),reader,end)) - } - } } impl Parse for String { - fn consume(reader: &mut Reader) -> Result, Error> - where - Self: Sized, - { - reader.trim()?; - let chars: &mut std::str::Chars = &mut reader.slice.chars(); - let mut string = String::new(); - let term1: char; - let term2: Option; - match chars.next() { - Some('"') => { - term1 = '"'; - term2 = None; - }, - Some('\'') => { - term1 = '\''; - term2 = None; - } - Some('[') if chars.next().is_some_and(|it| it == '[') => { - term1 = ']'; - term2 = Some(']'); - } - _ => { - return reader.error("Could not parse string"); - } - } - loop { - match chars.next() { - Some(c) => { - match c { - '\\' => { - match chars.next() { - Some(c) => { - match c { - 'n' => string.push('\n'), - 'r' => string.push('\r'), - 't' => string.push('\t'), - '"' => string.push('"'), - '\'' => string.push('\''), - '\\' => string.push('\\'), - it => { - string.push(it); - } - } - } - None => {} - } + fn consume(reader: &mut Reader) -> Result, Error> + where + Self: Sized, + { + reader.trim()?; + let chars: &mut std::str::Chars = &mut reader.slice.chars(); + let mut string = String::new(); + let term1: char; + let term2: Option; + match chars.next() { + Some('"') => { + term1 = '"'; + term2 = None; } - '\r' => {} // todo: ? - '\n' if term2.is_none() => { - return reader.error("Found newline while parsing string"); + Some('\'') => { + term1 = '\''; + term2 = None; } - term if term == term1 => { - // If the second terminator exists and is the next char, or there is no second terminator - if !term2.is_some() || chars.next().is_some_and(|it| it == term2.unwrap()) { - let length = string.len(); - reader.slice = &reader.slice[length..]; - return Ok(Piece::of(string,reader,length)) - // There is a second terminator and it wasn't the next char - } else { - string.push(term) - } + Some('[') if chars.next().is_some_and(|it| it == '[') => { + term1 = ']'; + term2 = Some(']'); } _ => { - string.push(c); + return reader.error("Could not parse string"); } - } } - None => { - return reader.error("Found EOF while parsing string"); + loop { + match chars.next() { + Some(c) => { + match c { + '\\' => match chars.next() { + Some(c) => match c { + 'n' => string.push('\n'), + 'r' => string.push('\r'), + 't' => string.push('\t'), + '"' => string.push('"'), + '\'' => string.push('\''), + '\\' => string.push('\\'), + it => { + string.push(it); + } + }, + None => {} + }, + '\r' => {} // todo: ? + '\n' if term2.is_none() => { + return reader.error("Found newline while parsing string"); + } + term if term == term1 => { + // If the second terminator exists and is the next char, or there is no second terminator + if !term2.is_some() + || chars.next().is_some_and(|it| it == term2.unwrap()) + { + let length = string.len(); + reader.slice = &reader.slice[length..]; + return Ok(Piece::of(string, reader, length)); + // There is a second terminator and it wasn't the next char + } else { + string.push(term) + } + } + _ => { + string.push(c); + } + } + } + None => { + return reader.error("Found EOF while parsing string"); + } + } } - } } - } } // AST #[derive(Debug)] -struct Block(Vec>); +struct Block(Vec>, Vec>); #[derive(Debug)] enum Statement { - Semicolon, - Assignment(Vec>,Vec>), - Call(Call), - Label(Piece), - Break, - Continue, - Return(Vec>), - Goto(Piece), - Do(Block), - While(Piece,Block), - Repeat(Block,Piece), - If(Vec>,Vec,Option), - Range(Piece,Piece,Piece,Option>,Block), - Iterator(Vec>,Vec>,Block), - Function(Vec>,Option>,Function), - LocalFunction(Piece,Function), - Declaration(Vec>,Vec>) + Semicolon, + Assignment(Vec>, Vec>), + Call(Call), + Label(Piece), + Break, + Continue, + Goto(Piece), + Do(Block), + While(Piece, Block), + Repeat(Block, Piece), + If(Vec>, Vec, Option), + Range( + Piece, + Piece, + Piece, + Option>, + Block, + ), + Iterator(Vec>, Vec>, Block), + Function(Vec>, Option>, Function), + LocalFunction(Piece, Function), + Declaration(Vec>, Vec>), } #[derive(Debug)] enum Variable { - Name(Name), - Index(Box,Box) + Name(Name), + Index(Box, Box), } #[derive(Debug)] enum Expression { - Nil, - True, - False, - Number(Number), - String(String), - VarArg(VarArg), - Function(Function), - Prefix(Box), - Table(Vec), - Binary(Box,BinaryOp,Box), - Unary(UnaryOp,Box) + Nil, + True, + False, + Number(Number), + String(String), + VarArg(VarArg), + Function(Function), + Prefix(Box), + Table(Vec), + Binary(Box, BinaryOp, Box), + Unary(UnaryOp, Box), } #[derive(Debug)] enum Prefix { - Variable(Variable), - Call(Call), - Expression(Expression), + Variable(Variable), + Call(Call), + Expression(Expression), } #[derive(Debug)] struct VarArg(Option); #[derive(Debug)] -struct Call(Option,Vec); +struct Call(Option, Vec); #[derive(Debug)] -struct Function(Vec>,Option>,Piece); +struct Function(Vec>, Option>, Piece); #[derive(Debug)] -struct Field(Option,Expression); +struct Field(Option, Expression); #[derive(Debug)] enum FieldSep { - Comma, - Semicolon + Comma, + Semicolon, } #[derive(Debug)] enum BinaryOp { - Plus, - Minus, - Mul, - Divide, - DivFloor, - Caret, - Modulo, - Ampersand, - Tilde, - Pipe, - ShiftRight, - ShiftLeft, - Concat, - Less, - LessEqual, - Greater, - GreatEqual, - Equivalent, - NotEqual, - And, - Or + Plus, + Minus, + Mul, + Divide, + DivFloor, + Caret, + Modulo, + Ampersand, + Tilde, + Pipe, + ShiftRight, + ShiftLeft, + Concat, + Less, + LessEqual, + Greater, + GreatEqual, + Equivalent, + NotEqual, + And, + Or, } #[derive(Debug)] enum UnaryOp { - Negate, - Not, - Ampersand, - Tilde + Negate, + Not, + Ampersand, + Tilde, } impl Parse for Vec> { - fn consume(reader: &mut Reader) -> Result>>, Error> - where - Self: Sized, - { - let result: Vec> = Vec::new(); - reader.trim()?; - loop { - if let Ok(it) = reader.take::() { + fn consume(reader: &mut Reader) -> Result>>, Error> + where + Self: Sized, + { + let mut result: Vec> = Vec::new(); reader.trim()?; - if !reader.consume(",").is_ok() { - break + loop { + if let Ok(it) = reader.take::() { + result.push(it); + reader.trim()?; + if !reader.consume(",").is_ok() { + break; + } + } } - } + if result.is_empty() { + return reader.error(format!("Expected {}s", std::any::type_name::()).as_str()); + } + let first = result.first().unwrap().null(); + let last = result.last().unwrap().null(); + Ok(Piece::from(result, &first, &last)) } - if result.is_empty() { - return reader.error(format!("Expected {}s",std::any::type_name::()).as_str()); - } - let first = result.first().unwrap().null(); - let last = result.last().unwrap().null(); - Ok(Piece::from(result,&first,&last)) - } } impl Parse for Function { - fn consume(reader: &mut Reader) -> Result, Error> { - reader.trim()?; - let start = reader.marker(); - reader.consume("(")?; - let mut parameters: Vec> = Vec::new(); - let mut vararg = None; - loop { - reader.trim()?; - if let Ok(name) = reader.take::() { - parameters.push(name); + fn consume(reader: &mut Reader) -> Result, Error> { reader.trim()?; - if vararg.is_some() { - return reader.error("Unexpected argument after vararg '...'") + let start = reader.marker(); + reader.consume("(")?; + let mut parameters: Vec> = Vec::new(); + let mut vararg = None; + loop { + if let Ok(name) = reader.take::() { + parameters.push(name); + if vararg.is_some() { + return reader.error("Unexpected argument after vararg '...'"); + } + if !reader.consume(",").is_ok() { + break; + } + } + vararg = reader.take::().ok() } - if !reader.consume(",").is_ok() { - break - } - } - vararg = reader.take::().ok() + reader.consume(")")?; + let end = reader.marker(); + let block = reader.take::()?; + Ok(Piece::from( + Function(parameters, vararg, block), + &start, + &end, + )) } - reader.trim()?; - reader.consume(")")?; - reader.trim()?; - let end = reader.marker(); - let block = reader.take::()?; - Ok(Piece::from(Function(parameters,vararg,block),&start,&end)) - } } impl Parse for VarArg { - fn consume(reader: &mut Reader) -> Result, Error> { - reader.trim()?; - let start = reader.marker(); - reader.consume("...")?; - let name = reader.take::().ok(); - let end; - if let Some(name) = name { - let end = name.null(); - Ok(Piece::from(VarArg(Some(name.it)), &start, &end)) - } else { - end = reader.marker(); - Ok(Piece::from(VarArg(name.map(|piece| piece.it)), &start, &end)) + fn consume(reader: &mut Reader) -> Result, Error> { + reader.trim()?; + let start = reader.marker(); + reader.consume("...")?; + let name = reader.take::().ok(); + let end; + if let Some(name) = name { + let end = name.null(); + Ok(Piece::from(VarArg(Some(name.it)), &start, &end)) + } else { + end = reader.marker(); + Ok(Piece::from( + VarArg(name.map(|piece| piece.it)), + &start, + &end, + )) + } } - } } impl Parse for Expression { - fn consume(reader: &mut Reader) -> Result, Error> { - - } + fn consume(reader: &mut Reader) -> Result, Error> { + reader.trim()?; + + } +} + +impl Parse for Call { + fn consume(reader: &mut Reader) -> Result, Error> { + + } } -// todo: WHY am i trimming everywhere... fix ts; its handled in take and consume already, comments can be stored in piece impl Parse for Statement { - fn consume(mut reader: &mut Reader) -> Result, Error> { - reader.trim()?; - let start = reader.marker(); - let restore = |new: &mut Reader| { - reader = new - }; - if reader.consume("break").is_ok() { - Ok(Piece::from(Statement::Break,&start,&reader.marker())) - } else if reader.consume("continue").is_ok() { - Ok(Piece::from(Statement::Continue,&start,&reader.marker())) - } else if reader.consume(";").is_ok() { - Ok(Piece::from(Statement::Semicolon,&start,&reader.marker())) - } else if let Ok(mut reader) = reader.consume("local").cloned() { - reader.trim()?; - if reader.consume("function").is_ok() { - reader.trim()?; - let name = reader.take::()?; - reader.trim()?; - let function = reader.take::()?; - restore(&mut reader); - Ok(Piece::from(Statement::LocalFunction(name, function.it), &start, &function.null())) - } else { - let names = reader.take::>>()?.it; - reader.trim()?; - reader.consume("=")?; - reader.trim()?; - let expressions = reader.take::>>()?.it; - restore(&mut reader); - Ok(Piece::from(Statement::Declaration(names,expressions),&start,&reader.marker())) - } - } else if let Ok(mut reader) = reader.consume("function") { - let mut names = Vec::new(); - loop { - reader.trim()?; - if let Ok(name) = reader.take::() { - names.push(name); - reader.trim()?; - if !reader.consume(".").is_ok() { - break - } - } - } - let mut member = None; - if reader.consume(":").is_ok() { - reader.trim()?; - member = Some(reader.take::()?); - } - let function = reader.take::()?; - restore(&mut reader); - Ok(Piece::from(Statement::Function(names,member,function.it),&start,&reader.marker())) - } else if let Ok(mut reader) = reader.consume("for") { - reader.trim()?; - let names = reader.take::>>()?.it; reader.trim()?; - let result = if names.len() > 1 { - let name = *names.first().unwrap().clone(); - reader.consume("=")?; reader.trim()?; - let begin = reader.take::()?; reader.trim()?; - reader.consume(",")?; reader.trim()?; - let finish = reader.take::()?; reader.trim()?; - let delta = if reader.consume(",").is_ok() { - reader.trim()?; - Some(reader.take::()?) + fn consume(initial: &mut Reader) -> Result, Error> { + initial.trim()?; + let start = initial.marker(); + // todo: it is safer to pass back the new reader in the Ok, and then map it out + if initial.consume("break").is_ok() { + Ok(Piece::from(Statement::Break, &start, &initial.marker())) + } else if initial.consume("continue").is_ok() { + Ok(Piece::from(Statement::Continue, &start, &initial.marker())) + } else if initial.consume(";").is_ok() { + Ok(Piece::from(Statement::Semicolon, &start, &initial.marker())) + } else if let Ok(mut reader) = initial.clone().consume("local") { + if reader.consume("function").is_ok() { + let name = reader.take::()?; + let function = reader.take::()?; + *initial = *reader; + Ok(Piece::from( + Statement::LocalFunction(name, function.it), + &start, + &function.null(), + )) + } else { + let names = reader.take::>>()?.it; + reader.consume("=")?; + let expressions = reader.take::>>()?.it; + *initial = *reader; + Ok(Piece::from( + Statement::Declaration(names, expressions), + &start, + &reader.marker(), + )) + } + } else if let Ok(mut reader) = initial.clone().consume("function") { + let mut names = Vec::new(); + loop { + if let Ok(name) = reader.take::() { + names.push(name); + if !reader.consume(".").is_ok() { + break; + } + } + } + let mut member = None; + if reader.consume(":").is_ok() { + member = Some(reader.take::()?); + } + let function = reader.take::()?; + *initial = *reader; + Ok(Piece::from( + Statement::Function(names, member, function.it), + &start, + &reader.marker(), + )) + } else if let Ok(mut reader) = initial.clone().consume("for") { + let names = reader.take::>>()?.it; + let result = if names.len() > 1 { + let name = *names.first().unwrap().clone(); + reader.consume("=")?; + let begin = reader.take::()?; + reader.consume(",")?; + let finish = reader.take::()?; + let delta = if reader.consume(",").is_ok() { + Some(reader.take::()?) + } else { + None + }; + reader.consume("do")?; + let block = reader.take::()?; + reader.consume("end")?; + Ok(Piece::from( + Statement::Range(name, begin, finish, delta, block.it), + &start, + &reader.marker(), + )) + } else { + reader.consume("in")?; + let expressions = reader.take::>>()?.it; + reader.consume("do")?; + let block = reader.take::()?; + reader.consume("end")?; + Ok(Piece::from( + Statement::Iterator(names, expressions, block.it), + &start, + &reader.marker(), + )) + }; + *initial = *reader; + result + } else if let Ok(mut reader) = initial.clone().consume("while") { + let condition = reader.take::()?; + reader.consume("do")?; + let block = reader.take::()?; + reader.consume("end")?; + *initial = *reader; + Ok(Piece::from( + Statement::While(condition, block.it), + &start, + &reader.marker(), + )) + } else if let Ok(mut reader) = initial.clone().consume("if") { + let mut conditions = Vec::new(); + let mut blocks = Vec::new(); + let branch = || -> Result<(), Error> { + conditions.push(reader.take::()?); + reader.consume("then")?; + blocks.push(reader.take::()?.it); + Ok(()) + }; + branch()?; + while reader.consume("elseif").is_ok() { + branch()?; + } + let block = if reader.consume("else").is_ok() { + Some(reader.take::()?.it) + } else { + None + }; + reader.consume("end")?; + *initial = *reader; + Ok(Piece::from( + Statement::If(conditions, blocks, block), + &start, + &reader.marker(), + )) + } else if let Ok(mut reader) = initial.clone().consume("goto") { + let name = reader.take::()?; + *initial = *reader; + Ok(Piece::from(Statement::Goto(name), &start, &reader.marker())) + } else if let Ok(mut reader) = initial.clone().consume("do") { + let block = reader.take::()?; + *initial = *reader; + Ok(Piece::from( + Statement::Do(block.it), + &start, + &reader.marker(), + )) + } else if let Ok(mut reader) = initial.clone().consume("repeat") { + reader.consume("repeat")?; + let block = reader.take::()?; + reader.consume("until")?; + let condition = reader.take::()?; + *initial = *reader; + Ok(Piece::from( + Statement::Repeat(block.it, condition), + &start, + &reader.marker(), + )) + } else if let Ok(mut reader) = initial.clone().consume("::") { + let name = reader.take::()?; + reader.consume("::")?; + *initial = *reader; + Ok(Piece::from( + Statement::Label(name), + &start, + &reader.marker(), + )) } else { - None - }; - reader.consume("do")?; reader.trim()?; - let block = reader.take::()?; reader.trim()?; - reader.consume("end")?; - Ok(Piece::from(Statement::Range(name,begin,finish,delta,block.it),&start,&reader.marker())) - } else { - reader.consume("in")?; reader.trim()?; - let expressions = reader.take::>>()?.it; reader.trim()?; - reader.consume("do")?; reader.trim()?; - let block = reader.take::()?; reader.trim()?; - reader.consume("end")?; - Ok(Piece::from(Statement::Iterator(names,expressions,block.it),&start,&reader.marker())) - }; - restore(&mut reader); - result - } else if let Ok(mut reader) = reader.consume("while") { - reader.trim()?; - let condition = reader.take::()?; - reader.consume("do")?; reader.trim()?; - let block = reader.take::()?; reader.trim()?; - reader.consume("end")?; - restore(&mut reader); - Ok(Piece::from(Statement::While(condition,block.it),&start,&reader.marker())) - } else if let Ok(mut reader) = reader.consume("if") { - reader.trim()?; - let mut conditions = Vec::new(); - let mut blocks = Vec::new(); - let branch = || -> Result<(),Error> { - conditions.push(reader.take::()?); reader.trim()?; - reader.consume("then")?; reader.trim()?; - blocks.push(reader.take::()?.it); - Ok(()) - }; - branch()?; - while reader.consume("elseif").is_ok() { - reader.trim()?; - branch()?; - } - let block = if reader.consume("else").is_ok() { - reader.trim()?; - Some(reader.take::()?.it) - } else { - None - }; - reader.consume("end")?; - restore(&mut reader); - Ok(Piece::from(Statement::If(conditions,blocks,block),&start,&reader.marker())) - } else if let Ok(mut reader) = reader.consume("goto") { - reader.trim()?; - let name = reader.take::()?; - restore(&mut reader); - Ok(Piece::from(Statement::Goto(name),&start,&reader.marker())) - } else if let Ok(mut reader) = reader.consume("do") { - reader.trim()?; - let block = reader.take::()?; - restore(&mut reader); - Ok(Piece::from(Statement::Do(block.it),&start,&reader.marker())) - } else if let Ok(mut reader) = reader.consume("repeat") { - reader.trim()?; - reader.consume("repeat")?; reader.trim()?; - let block = reader.take::()?; reader.trim()?; - reader.consume("until")?; reader.trim()?; - let condition = reader.take::()?; - restore(&mut reader); - Ok(Piece::from(Statement::Repeat(block.it,condition),&start,&reader.marker())) - } else if let Ok(mut reader) = reader.consume("::") { - let name = reader.take::()?; - reader.consume("::")?; - restore(&mut reader); - Ok(Piece::from(Statement::Label(name),&start,&reader.marker())) - } else if let Ok(mut reader) = - } + reader.take::().map(|call| Statement::Call(call)).or_else(|| reader.take::) + } + + } } impl Parse for Block { - fn consume(reader: &mut Reader) -> Result, Error> - where - Self: Sized - { - let mut statements = Vec::new(); - while let Ok(statement) = reader.take::() { - statements.push(statement); + fn consume(reader: &mut Reader) -> Result, Error> + where + Self: Sized, + { + let mut statements = Vec::new(); + let start = reader.marker(); + while let Ok(statement) = reader.take::() { + statements.push(statement); + } + let expressions = if reader.consume("return").is_ok() { + let result = reader.take::>>()?; + reader.consume(";").ok(); + result.it + } else { + Vec::new() + }; + Ok(Piece::from( + Block(statements, expressions), + &start, + &reader.marker(), + )) } - if statements.is_empty() { - Ok(Piece::of(Block(statements),reader,0)) - } else { - let first = statements.first().unwrap().null(); - let last = statements.last().unwrap().null(); - Ok(Piece::from(Block(statements),&first,&last)) - } - } } -fn parse(str: &str) -> Result { - Reader::from(str).take::().map(|piece| piece.it) +fn parse(str: &str) -> Result { + Reader::from(str).take::().map(|piece| piece.it) } #[cfg(test)] mod tests { - use super::*; - #[test] - fn simple() { - println!("{:?}",parse(include_str!("assets/script.lua")).unwrap()); - } -} \ No newline at end of file + use super::*; + #[test] + fn simple() { + println!("{:?}", parse(include_str!("assets/script.lua")).unwrap()); + } +}