Majority of untested implementation of Statement; Some changes to parser structure and code style; Added .gitignore

This commit is contained in:
Adebimpe Lincoln
2026-07-10 20:59:17 +01:00
parent f91d5a5091
commit a894fc6689
2 changed files with 541 additions and 459 deletions
+1
View File
@@ -0,0 +1 @@
target
+224 -143
View File
@@ -1,4 +1,4 @@
#[derive(Debug, Clone)] #[derive(Clone)]
struct Reader<'a> { struct Reader<'a> {
slice: &'a str, slice: &'a str,
full: &'a str, full: &'a str,
@@ -8,13 +8,16 @@ struct Reader<'a> {
struct Error(String); struct Error(String);
impl Error { impl Error {
fn new<T>(message: &str, reader: &Reader) -> Result<T,Error> { fn new<T>(message: &str, _reader: &Reader) -> Result<T, Error> {
Err(Error(message.to_string())) Err(Error(message.to_string()))
} }
} }
type Comment = String;
#[derive(Debug)] #[derive(Debug)]
struct Piece<T> { struct Piece<T> {
comment: Comment,
index: usize, index: usize,
width: usize, width: usize,
it: T, it: T,
@@ -25,21 +28,24 @@ impl<T> Piece<T> {
Piece { Piece {
it, it,
index: reader.slice.as_ptr() as usize - reader.full.as_ptr() as usize, index: reader.slice.as_ptr() as usize - reader.full.as_ptr() as usize,
width width,
comment: String::new()
} }
} }
fn from<A, B>(it: T, begin: &Piece<A>, end: &Piece<B>) -> Piece<T> { fn from<A, B>(it: T, begin: &Piece<A>, end: &Piece<B>) -> Piece<T> {
Piece { Piece {
it, it,
index: begin.index, index: begin.index,
width: end.index + end.width - begin.index width: end.index + end.width - begin.index,
comment: String::new()
} }
} }
fn null(&self) -> Piece<()> { fn null(&self) -> Piece<()> {
Piece { Piece {
it: (), it: (),
index: self.index, index: self.index,
width: self.width width: self.width,
comment: String::new()
} }
} }
} }
@@ -51,33 +57,40 @@ impl<'a> From<&'a str> for Reader<'a> {
fn from(str: &'a str) -> Self { fn from(str: &'a str) -> Self {
Reader { Reader {
full: str, full: str,
slice: str slice: str,
} }
} }
} }
impl<'a> Reader<'a> { impl<'a> Reader<'a> {
fn trim(&mut self) -> Result<&Self,Error> { fn trim(&mut self) -> Result<Comment, Error> {
self.slice = self.slice.trim_start(); self.slice = self.slice.trim_start();
if self.slice.starts_with("--") { if self.slice.starts_with("--") {
if self.slice[2..].starts_with("[[") { let comment = if self.slice[2..].starts_with("[[") {
match self.slice.find("]]") { match self.slice.find("]]") {
Some(i) => { Some(i) => {
let comment = &self.slice[4..i + 2];
self.slice = &self.slice[i + 2..].trim(); self.slice = &self.slice[i + 2..].trim();
Ok(self) Ok(comment)
}
_ => {
self.error("Unterminated multi-line comment")
} }
_ => self.error("Unterminated multi-line comment"),
} }
} else { } else {
let comment;
if let Some(i) = self.slice.find("\n") { if let Some(i) = self.slice.find("\n") {
self.slice = &self.slice[i + 1..].trim(); self.slice = &self.slice[i + 1..].trim();
} comment = &self.slice[2..i+1];
Ok(self)
}
} else { } else {
Ok(self) 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> { fn consume(&mut self, start: &str) -> Result<&Self, Error> {
@@ -89,7 +102,10 @@ impl<'a> Reader<'a> {
self.error(format!("Expected '{}'", start).as_str()) self.error(format!("Expected '{}'", start).as_str())
} }
} }
fn take<T>(&mut self) -> Result<Piece<T>,Error> where T: Parse { fn take<T>(&mut self) -> Result<Piece<T>, Error>
where
T: Parse,
{
self.trim()?; self.trim()?;
T::consume(self) T::consume(self)
} }
@@ -111,12 +127,13 @@ struct Name(String);
// - The reader may have not been trimmed // - The reader may have not been trimmed
trait Parse { trait Parse {
fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error> fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error>
where Self: Sized; where
Self: Sized;
} }
impl Parse for Name { impl Parse for Name {
fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error> fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error>
where where
Self: Sized Self: Sized,
{ {
reader.trim()?; reader.trim()?;
let mut chars = reader.slice.chars(); let mut chars = reader.slice.chars();
@@ -127,12 +144,18 @@ impl Parse for Name {
} }
Some(c) => { Some(c) => {
if !(c.is_alphabetic() || c == '_') { if !(c.is_alphabetic() || c == '_') {
return reader.error("Identifier must begin with alphabetic character") return reader.error("Identifier must begin with alphabetic character");
} }
} }
}; };
end += chars.take_while(|c| { c.is_alphanumeric() || *c == '_' }).count(); end += chars
let result = Ok(Piece::of(Name(reader.slice[..end].to_string()),reader,end)); .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..]; reader.slice = &reader.slice[end..];
result result
} }
@@ -140,21 +163,35 @@ impl Parse for Name {
impl Parse for Number { impl Parse for Number {
fn consume(reader: &mut Reader) -> Result<Piece<Number>, Error> fn consume(reader: &mut Reader) -> Result<Piece<Number>, Error>
where where
Self: Sized Self: Sized,
{ {
reader.trim()?; reader.trim()?;
let mut end; let mut end;
if reader.slice.starts_with("0x") { if reader.slice.starts_with("0x") {
end = reader.slice[2..].chars().take_while(|c| c.is_digit(16)).count()+2; end = reader.slice[2..]
if end == 2 { end = 0 } .chars()
.take_while(|c| c.is_digit(16))
.count()
+ 2;
if end == 2 {
end = 0
}
} else { } else {
end = reader.slice.chars().take_while(|c| c.is_digit(10) || *c == '.').count(); end = reader
.slice
.chars()
.take_while(|c| c.is_digit(10) || *c == '.')
.count();
} }
if end == 0 { if end == 0 {
reader.error("Could not parse number".into()) reader.error("Could not parse number".into())
} else { } else {
reader.slice = &reader.slice[end..]; reader.slice = &reader.slice[end..];
Ok(Piece::of(Number(reader.slice[..end].to_string()),reader,end)) Ok(Piece::of(
Number(reader.slice[..end].to_string()),
reader,
end,
))
} }
} }
} }
@@ -173,7 +210,7 @@ impl Parse for String {
Some('"') => { Some('"') => {
term1 = '"'; term1 = '"';
term2 = None; term2 = None;
}, }
Some('\'') => { Some('\'') => {
term1 = '\''; term1 = '\'';
term2 = None; term2 = None;
@@ -190,10 +227,8 @@ impl Parse for String {
match chars.next() { match chars.next() {
Some(c) => { Some(c) => {
match c { match c {
'\\' => { '\\' => match chars.next() {
match chars.next() { Some(c) => match c {
Some(c) => {
match c {
'n' => string.push('\n'), 'n' => string.push('\n'),
'r' => string.push('\r'), 'r' => string.push('\r'),
't' => string.push('\t'), 't' => string.push('\t'),
@@ -203,21 +238,21 @@ impl Parse for String {
it => { it => {
string.push(it); string.push(it);
} }
} },
}
None => {} None => {}
} },
}
'\r' => {} // todo: ? '\r' => {} // todo: ?
'\n' if term2.is_none() => { '\n' if term2.is_none() => {
return reader.error("Found newline while parsing string"); return reader.error("Found newline while parsing string");
} }
term if term == term1 => { term if term == term1 => {
// If the second terminator exists and is the next char, or there is no second terminator // 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()) { if !term2.is_some()
|| chars.next().is_some_and(|it| it == term2.unwrap())
{
let length = string.len(); let length = string.len();
reader.slice = &reader.slice[length..]; reader.slice = &reader.slice[length..];
return Ok(Piece::of(string,reader,length)) return Ok(Piece::of(string, reader, length));
// There is a second terminator and it wasn't the next char // There is a second terminator and it wasn't the next char
} else { } else {
string.push(term) string.push(term)
@@ -238,7 +273,7 @@ impl Parse for String {
// AST // AST
#[derive(Debug)] #[derive(Debug)]
struct Block(Vec<Piece<Statement>>); struct Block(Vec<Piece<Statement>>, Vec<Piece<Expression>>);
#[derive(Debug)] #[derive(Debug)]
enum Statement { enum Statement {
Semicolon, Semicolon,
@@ -247,22 +282,27 @@ enum Statement {
Label(Piece<Name>), Label(Piece<Name>),
Break, Break,
Continue, Continue,
Return(Vec<Piece<Expression>>),
Goto(Piece<Name>), Goto(Piece<Name>),
Do(Block), Do(Block),
While(Piece<Expression>, Block), While(Piece<Expression>, Block),
Repeat(Block, Piece<Expression>), Repeat(Block, Piece<Expression>),
If(Vec<Piece<Expression>>, Vec<Block>, Option<Block>), If(Vec<Piece<Expression>>, Vec<Block>, Option<Block>),
Range(Piece<Name>,Piece<Expression>,Piece<Expression>,Option<Piece<Expression>>,Block), Range(
Piece<Name>,
Piece<Expression>,
Piece<Expression>,
Option<Piece<Expression>>,
Block,
),
Iterator(Vec<Piece<Name>>, Vec<Piece<Expression>>, Block), Iterator(Vec<Piece<Name>>, Vec<Piece<Expression>>, Block),
Function(Vec<Piece<Name>>, Option<Piece<Name>>, Function), Function(Vec<Piece<Name>>, Option<Piece<Name>>, Function),
LocalFunction(Piece<Name>, Function), LocalFunction(Piece<Name>, Function),
Declaration(Vec<Piece<Name>>,Vec<Piece<Expression>>) Declaration(Vec<Piece<Name>>, Vec<Piece<Expression>>),
} }
#[derive(Debug)] #[derive(Debug)]
enum Variable { enum Variable {
Name(Name), Name(Name),
Index(Box<Prefix>,Box<Expression>) Index(Box<Prefix>, Box<Expression>),
} }
#[derive(Debug)] #[derive(Debug)]
enum Expression { enum Expression {
@@ -276,7 +316,7 @@ enum Expression {
Prefix(Box<Prefix>), Prefix(Box<Prefix>),
Table(Vec<Field>), Table(Vec<Field>),
Binary(Box<Expression>, BinaryOp, Box<Expression>), Binary(Box<Expression>, BinaryOp, Box<Expression>),
Unary(UnaryOp,Box<Expression>) Unary(UnaryOp, Box<Expression>),
} }
#[derive(Debug)] #[derive(Debug)]
enum Prefix { enum Prefix {
@@ -295,7 +335,7 @@ struct Field(Option<Expression>,Expression);
#[derive(Debug)] #[derive(Debug)]
enum FieldSep { enum FieldSep {
Comma, Comma,
Semicolon Semicolon,
} }
#[derive(Debug)] #[derive(Debug)]
enum BinaryOp { enum BinaryOp {
@@ -319,14 +359,14 @@ enum BinaryOp {
Equivalent, Equivalent,
NotEqual, NotEqual,
And, And,
Or Or,
} }
#[derive(Debug)] #[derive(Debug)]
enum UnaryOp { enum UnaryOp {
Negate, Negate,
Not, Not,
Ampersand, Ampersand,
Tilde Tilde,
} }
impl<T: Parse> Parse for Vec<Piece<T>> { impl<T: Parse> Parse for Vec<Piece<T>> {
@@ -334,13 +374,14 @@ impl<T: Parse> Parse for Vec<Piece<T>> {
where where
Self: Sized, Self: Sized,
{ {
let result: Vec<Piece<T>> = Vec::new(); let mut result: Vec<Piece<T>> = Vec::new();
reader.trim()?; reader.trim()?;
loop { loop {
if let Ok(it) = reader.take::<T>() { if let Ok(it) = reader.take::<T>() {
result.push(it);
reader.trim()?; reader.trim()?;
if !reader.consume(",").is_ok() { if !reader.consume(",").is_ok() {
break break;
} }
} }
} }
@@ -361,25 +402,25 @@ impl Parse for Function {
let mut parameters: Vec<Piece<Name>> = Vec::new(); let mut parameters: Vec<Piece<Name>> = Vec::new();
let mut vararg = None; let mut vararg = None;
loop { loop {
reader.trim()?;
if let Ok(name) = reader.take::<Name>() { if let Ok(name) = reader.take::<Name>() {
parameters.push(name); parameters.push(name);
reader.trim()?;
if vararg.is_some() { if vararg.is_some() {
return reader.error("Unexpected argument after vararg '...'") return reader.error("Unexpected argument after vararg '...'");
} }
if !reader.consume(",").is_ok() { if !reader.consume(",").is_ok() {
break break;
} }
} }
vararg = reader.take::<VarArg>().ok() vararg = reader.take::<VarArg>().ok()
} }
reader.trim()?;
reader.consume(")")?; reader.consume(")")?;
reader.trim()?;
let end = reader.marker(); let end = reader.marker();
let block = reader.take::<Block>()?; let block = reader.take::<Block>()?;
Ok(Piece::from(Function(parameters,vararg,block),&start,&end)) Ok(Piece::from(
Function(parameters, vararg, block),
&start,
&end,
))
} }
} }
@@ -395,173 +436,213 @@ impl Parse for VarArg {
Ok(Piece::from(VarArg(Some(name.it)), &start, &end)) Ok(Piece::from(VarArg(Some(name.it)), &start, &end))
} else { } else {
end = reader.marker(); end = reader.marker();
Ok(Piece::from(VarArg(name.map(|piece| piece.it)), &start, &end)) Ok(Piece::from(
VarArg(name.map(|piece| piece.it)),
&start,
&end,
))
} }
} }
} }
impl Parse for Expression { impl Parse for Expression {
fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error> {
reader.trim()?;
}
}
impl Parse for Call {
fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error> { fn consume(reader: &mut Reader) -> Result<Piece<Self>, 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 { impl Parse for Statement {
fn consume(mut reader: &mut Reader) -> Result<Piece<Statement>, Error> { fn consume(initial: &mut Reader) -> Result<Piece<Statement>, Error> {
reader.trim()?; initial.trim()?;
let start = reader.marker(); let start = initial.marker();
let restore = |new: &mut Reader| { // todo: it is safer to pass back the new reader in the Ok, and then map it out
reader = new if initial.consume("break").is_ok() {
}; Ok(Piece::from(Statement::Break, &start, &initial.marker()))
if reader.consume("break").is_ok() { } else if initial.consume("continue").is_ok() {
Ok(Piece::from(Statement::Break,&start,&reader.marker())) Ok(Piece::from(Statement::Continue, &start, &initial.marker()))
} else if reader.consume("continue").is_ok() { } else if initial.consume(";").is_ok() {
Ok(Piece::from(Statement::Continue,&start,&reader.marker())) Ok(Piece::from(Statement::Semicolon, &start, &initial.marker()))
} else if reader.consume(";").is_ok() { } else if let Ok(mut reader) = initial.clone().consume("local") {
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() { if reader.consume("function").is_ok() {
reader.trim()?;
let name = reader.take::<Name>()?; let name = reader.take::<Name>()?;
reader.trim()?;
let function = reader.take::<Function>()?; let function = reader.take::<Function>()?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::LocalFunction(name, function.it), &start, &function.null())) Ok(Piece::from(
Statement::LocalFunction(name, function.it),
&start,
&function.null(),
))
} else { } else {
let names = reader.take::<Vec<Piece<Name>>>()?.it; let names = reader.take::<Vec<Piece<Name>>>()?.it;
reader.trim()?;
reader.consume("=")?; reader.consume("=")?;
reader.trim()?;
let expressions = reader.take::<Vec<Piece<Expression>>>()?.it; let expressions = reader.take::<Vec<Piece<Expression>>>()?.it;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::Declaration(names,expressions),&start,&reader.marker())) Ok(Piece::from(
Statement::Declaration(names, expressions),
&start,
&reader.marker(),
))
} }
} else if let Ok(mut reader) = reader.consume("function") { } else if let Ok(mut reader) = initial.clone().consume("function") {
let mut names = Vec::new(); let mut names = Vec::new();
loop { loop {
reader.trim()?;
if let Ok(name) = reader.take::<Name>() { if let Ok(name) = reader.take::<Name>() {
names.push(name); names.push(name);
reader.trim()?;
if !reader.consume(".").is_ok() { if !reader.consume(".").is_ok() {
break break;
} }
} }
} }
let mut member = None; let mut member = None;
if reader.consume(":").is_ok() { if reader.consume(":").is_ok() {
reader.trim()?;
member = Some(reader.take::<Name>()?); member = Some(reader.take::<Name>()?);
} }
let function = reader.take::<Function>()?; let function = reader.take::<Function>()?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::Function(names,member,function.it),&start,&reader.marker())) Ok(Piece::from(
} else if let Ok(mut reader) = reader.consume("for") { Statement::Function(names, member, function.it),
reader.trim()?; &start,
let names = reader.take::<Vec<Piece<Name>>>()?.it; reader.trim()?; &reader.marker(),
))
} else if let Ok(mut reader) = initial.clone().consume("for") {
let names = reader.take::<Vec<Piece<Name>>>()?.it;
let result = if names.len() > 1 { let result = if names.len() > 1 {
let name = *names.first().unwrap().clone(); let name = *names.first().unwrap().clone();
reader.consume("=")?; reader.trim()?; reader.consume("=")?;
let begin = reader.take::<Expression>()?; reader.trim()?; let begin = reader.take::<Expression>()?;
reader.consume(",")?; reader.trim()?; reader.consume(",")?;
let finish = reader.take::<Expression>()?; reader.trim()?; let finish = reader.take::<Expression>()?;
let delta = if reader.consume(",").is_ok() { let delta = if reader.consume(",").is_ok() {
reader.trim()?;
Some(reader.take::<Expression>()?) Some(reader.take::<Expression>()?)
} else { } else {
None None
}; };
reader.consume("do")?; reader.trim()?; reader.consume("do")?;
let block = reader.take::<Block>()?; reader.trim()?; let block = reader.take::<Block>()?;
reader.consume("end")?; reader.consume("end")?;
Ok(Piece::from(Statement::Range(name,begin,finish,delta,block.it),&start,&reader.marker())) Ok(Piece::from(
Statement::Range(name, begin, finish, delta, block.it),
&start,
&reader.marker(),
))
} else { } else {
reader.consume("in")?; reader.trim()?; reader.consume("in")?;
let expressions = reader.take::<Vec<Piece<Expression>>>()?.it; reader.trim()?; let expressions = reader.take::<Vec<Piece<Expression>>>()?.it;
reader.consume("do")?; reader.trim()?; reader.consume("do")?;
let block = reader.take::<Block>()?; reader.trim()?; let block = reader.take::<Block>()?;
reader.consume("end")?; reader.consume("end")?;
Ok(Piece::from(Statement::Iterator(names,expressions,block.it),&start,&reader.marker())) Ok(Piece::from(
Statement::Iterator(names, expressions, block.it),
&start,
&reader.marker(),
))
}; };
restore(&mut reader); *initial = *reader;
result result
} else if let Ok(mut reader) = reader.consume("while") { } else if let Ok(mut reader) = initial.clone().consume("while") {
reader.trim()?;
let condition = reader.take::<Expression>()?; let condition = reader.take::<Expression>()?;
reader.consume("do")?; reader.trim()?; reader.consume("do")?;
let block = reader.take::<Block>()?; reader.trim()?; let block = reader.take::<Block>()?;
reader.consume("end")?; reader.consume("end")?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::While(condition,block.it),&start,&reader.marker())) Ok(Piece::from(
} else if let Ok(mut reader) = reader.consume("if") { Statement::While(condition, block.it),
reader.trim()?; &start,
&reader.marker(),
))
} else if let Ok(mut reader) = initial.clone().consume("if") {
let mut conditions = Vec::new(); let mut conditions = Vec::new();
let mut blocks = Vec::new(); let mut blocks = Vec::new();
let branch = || -> Result<(), Error> { let branch = || -> Result<(), Error> {
conditions.push(reader.take::<Expression>()?); reader.trim()?; conditions.push(reader.take::<Expression>()?);
reader.consume("then")?; reader.trim()?; reader.consume("then")?;
blocks.push(reader.take::<Block>()?.it); blocks.push(reader.take::<Block>()?.it);
Ok(()) Ok(())
}; };
branch()?; branch()?;
while reader.consume("elseif").is_ok() { while reader.consume("elseif").is_ok() {
reader.trim()?;
branch()?; branch()?;
} }
let block = if reader.consume("else").is_ok() { let block = if reader.consume("else").is_ok() {
reader.trim()?;
Some(reader.take::<Block>()?.it) Some(reader.take::<Block>()?.it)
} else { } else {
None None
}; };
reader.consume("end")?; reader.consume("end")?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::If(conditions,blocks,block),&start,&reader.marker())) Ok(Piece::from(
} else if let Ok(mut reader) = reader.consume("goto") { Statement::If(conditions, blocks, block),
reader.trim()?; &start,
&reader.marker(),
))
} else if let Ok(mut reader) = initial.clone().consume("goto") {
let name = reader.take::<Name>()?; let name = reader.take::<Name>()?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::Goto(name), &start, &reader.marker())) Ok(Piece::from(Statement::Goto(name), &start, &reader.marker()))
} else if let Ok(mut reader) = reader.consume("do") { } else if let Ok(mut reader) = initial.clone().consume("do") {
reader.trim()?;
let block = reader.take::<Block>()?; let block = reader.take::<Block>()?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::Do(block.it),&start,&reader.marker())) Ok(Piece::from(
} else if let Ok(mut reader) = reader.consume("repeat") { Statement::Do(block.it),
reader.trim()?; &start,
reader.consume("repeat")?; reader.trim()?; &reader.marker(),
let block = reader.take::<Block>()?; reader.trim()?; ))
reader.consume("until")?; reader.trim()?; } else if let Ok(mut reader) = initial.clone().consume("repeat") {
reader.consume("repeat")?;
let block = reader.take::<Block>()?;
reader.consume("until")?;
let condition = reader.take::<Expression>()?; let condition = reader.take::<Expression>()?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::Repeat(block.it,condition),&start,&reader.marker())) Ok(Piece::from(
} else if let Ok(mut reader) = reader.consume("::") { Statement::Repeat(block.it, condition),
&start,
&reader.marker(),
))
} else if let Ok(mut reader) = initial.clone().consume("::") {
let name = reader.take::<Name>()?; let name = reader.take::<Name>()?;
reader.consume("::")?; reader.consume("::")?;
restore(&mut reader); *initial = *reader;
Ok(Piece::from(Statement::Label(name),&start,&reader.marker())) Ok(Piece::from(
} else if let Ok(mut reader) = Statement::Label(name),
&start,
&reader.marker(),
))
} else {
reader.take::<Call>().map(|call| Statement::Call(call)).or_else(|| reader.take::)
}
} }
} }
impl Parse for Block { impl Parse for Block {
fn consume(reader: &mut Reader) -> Result<Piece<Block>, Error> fn consume(reader: &mut Reader) -> Result<Piece<Block>, Error>
where where
Self: Sized Self: Sized,
{ {
let mut statements = Vec::new(); let mut statements = Vec::new();
let start = reader.marker();
while let Ok(statement) = reader.take::<Statement>() { while let Ok(statement) = reader.take::<Statement>() {
statements.push(statement); statements.push(statement);
} }
if statements.is_empty() { let expressions = if reader.consume("return").is_ok() {
Ok(Piece::of(Block(statements),reader,0)) let result = reader.take::<Vec<Piece<Expression>>>()?;
reader.consume(";").ok();
result.it
} else { } else {
let first = statements.first().unwrap().null(); Vec::new()
let last = statements.last().unwrap().null(); };
Ok(Piece::from(Block(statements),&first,&last)) Ok(Piece::from(
} Block(statements, expressions),
&start,
&reader.marker(),
))
} }
} }