Majority of untested implementation of Statement; Some changes to parser structure and code style; Added .gitignore
This commit is contained in:
@@ -0,0 +1 @@
|
||||
target
|
||||
+249
-168
@@ -1,4 +1,4 @@
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone)]
|
||||
struct Reader<'a> {
|
||||
slice: &'a str,
|
||||
full: &'a str,
|
||||
@@ -8,13 +8,16 @@ struct Reader<'a> {
|
||||
struct Error(String);
|
||||
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
type Comment = String;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Piece<T> {
|
||||
comment: Comment,
|
||||
index: usize,
|
||||
width: usize,
|
||||
it: T,
|
||||
@@ -25,21 +28,24 @@ impl<T> Piece<T> {
|
||||
Piece {
|
||||
it,
|
||||
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 {
|
||||
it,
|
||||
index: begin.index,
|
||||
width: end.index + end.width - begin.index
|
||||
width: end.index + end.width - begin.index,
|
||||
comment: String::new()
|
||||
}
|
||||
}
|
||||
fn null(&self) -> Piece<()> {
|
||||
Piece {
|
||||
it: (),
|
||||
index: self.index,
|
||||
width: self.width
|
||||
width: self.width,
|
||||
comment: String::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,53 +57,63 @@ impl<'a> From<&'a str> for Reader<'a> {
|
||||
fn from(str: &'a str) -> Self {
|
||||
Reader {
|
||||
full: str,
|
||||
slice: str
|
||||
slice: str,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Reader<'a> {
|
||||
fn trim(&mut self) -> Result<&Self,Error> {
|
||||
fn trim(&mut self) -> Result<Comment, Error> {
|
||||
self.slice = self.slice.trim_start();
|
||||
if self.slice.starts_with("--") {
|
||||
if self.slice[2..].starts_with("[[") {
|
||||
let comment = if self.slice[2..].starts_with("[[") {
|
||||
match self.slice.find("]]") {
|
||||
Some(i) => {
|
||||
self.slice = &self.slice[i+2..].trim();
|
||||
Ok(self)
|
||||
}
|
||||
_ => {
|
||||
self.error("Unterminated multi-line comment")
|
||||
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();
|
||||
}
|
||||
Ok(self)
|
||||
}
|
||||
self.slice = &self.slice[i + 1..].trim();
|
||||
comment = &self.slice[2..i+1];
|
||||
} 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> {
|
||||
self.trim()?;
|
||||
if self.slice.starts_with(start) {
|
||||
self.slice = &self.slice[start.len()..];
|
||||
Ok(self)
|
||||
} else {
|
||||
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()?;
|
||||
T::consume(self)
|
||||
}
|
||||
fn error<T>(&self, message: &str) -> Result<T,Error> {
|
||||
Error::new(message,self)
|
||||
fn error<T>(&self, message: &str) -> Result<T, Error> {
|
||||
Error::new(message, self)
|
||||
}
|
||||
fn marker(&self) -> Piece<()> {
|
||||
Piece::of((),self,0)
|
||||
Piece::of((), self, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,12 +127,13 @@ struct Name(String);
|
||||
// - The reader may have not been trimmed
|
||||
trait Parse {
|
||||
fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error>
|
||||
where Self: Sized;
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
impl Parse for Name {
|
||||
fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error>
|
||||
where
|
||||
Self: Sized
|
||||
Self: Sized,
|
||||
{
|
||||
reader.trim()?;
|
||||
let mut chars = reader.slice.chars();
|
||||
@@ -127,12 +144,18 @@ impl Parse for Name {
|
||||
}
|
||||
Some(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();
|
||||
let result = Ok(Piece::of(Name(reader.slice[..end].to_string()),reader,end));
|
||||
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
|
||||
}
|
||||
@@ -140,21 +163,35 @@ impl Parse for Name {
|
||||
impl Parse for Number {
|
||||
fn consume(reader: &mut Reader) -> Result<Piece<Number>, Error>
|
||||
where
|
||||
Self: Sized
|
||||
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 }
|
||||
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();
|
||||
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))
|
||||
Ok(Piece::of(
|
||||
Number(reader.slice[..end].to_string()),
|
||||
reader,
|
||||
end,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -173,7 +210,7 @@ impl Parse for String {
|
||||
Some('"') => {
|
||||
term1 = '"';
|
||||
term2 = None;
|
||||
},
|
||||
}
|
||||
Some('\'') => {
|
||||
term1 = '\'';
|
||||
term2 = None;
|
||||
@@ -190,10 +227,8 @@ impl Parse for String {
|
||||
match chars.next() {
|
||||
Some(c) => {
|
||||
match c {
|
||||
'\\' => {
|
||||
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'),
|
||||
@@ -203,21 +238,21 @@ impl Parse for String {
|
||||
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()) {
|
||||
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))
|
||||
return Ok(Piece::of(string, reader, length));
|
||||
// There is a second terminator and it wasn't the next char
|
||||
} else {
|
||||
string.push(term)
|
||||
@@ -238,31 +273,36 @@ impl Parse for String {
|
||||
|
||||
// AST
|
||||
#[derive(Debug)]
|
||||
struct Block(Vec<Piece<Statement>>);
|
||||
struct Block(Vec<Piece<Statement>>, Vec<Piece<Expression>>);
|
||||
#[derive(Debug)]
|
||||
enum Statement {
|
||||
Semicolon,
|
||||
Assignment(Vec<Piece<Variable>>,Vec<Piece<Expression>>),
|
||||
Assignment(Vec<Piece<Variable>>, Vec<Piece<Expression>>),
|
||||
Call(Call),
|
||||
Label(Piece<Name>),
|
||||
Break,
|
||||
Continue,
|
||||
Return(Vec<Piece<Expression>>),
|
||||
Goto(Piece<Name>),
|
||||
Do(Block),
|
||||
While(Piece<Expression>,Block),
|
||||
Repeat(Block,Piece<Expression>),
|
||||
If(Vec<Piece<Expression>>,Vec<Block>,Option<Block>),
|
||||
Range(Piece<Name>,Piece<Expression>,Piece<Expression>,Option<Piece<Expression>>,Block),
|
||||
Iterator(Vec<Piece<Name>>,Vec<Piece<Expression>>,Block),
|
||||
Function(Vec<Piece<Name>>,Option<Piece<Name>>,Function),
|
||||
LocalFunction(Piece<Name>,Function),
|
||||
Declaration(Vec<Piece<Name>>,Vec<Piece<Expression>>)
|
||||
While(Piece<Expression>, Block),
|
||||
Repeat(Block, Piece<Expression>),
|
||||
If(Vec<Piece<Expression>>, Vec<Block>, Option<Block>),
|
||||
Range(
|
||||
Piece<Name>,
|
||||
Piece<Expression>,
|
||||
Piece<Expression>,
|
||||
Option<Piece<Expression>>,
|
||||
Block,
|
||||
),
|
||||
Iterator(Vec<Piece<Name>>, Vec<Piece<Expression>>, Block),
|
||||
Function(Vec<Piece<Name>>, Option<Piece<Name>>, Function),
|
||||
LocalFunction(Piece<Name>, Function),
|
||||
Declaration(Vec<Piece<Name>>, Vec<Piece<Expression>>),
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum Variable {
|
||||
Name(Name),
|
||||
Index(Box<Prefix>,Box<Expression>)
|
||||
Index(Box<Prefix>, Box<Expression>),
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum Expression {
|
||||
@@ -275,8 +315,8 @@ enum Expression {
|
||||
Function(Function),
|
||||
Prefix(Box<Prefix>),
|
||||
Table(Vec<Field>),
|
||||
Binary(Box<Expression>,BinaryOp,Box<Expression>),
|
||||
Unary(UnaryOp,Box<Expression>)
|
||||
Binary(Box<Expression>, BinaryOp, Box<Expression>),
|
||||
Unary(UnaryOp, Box<Expression>),
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum Prefix {
|
||||
@@ -287,15 +327,15 @@ enum Prefix {
|
||||
#[derive(Debug)]
|
||||
struct VarArg(Option<Name>);
|
||||
#[derive(Debug)]
|
||||
struct Call(Option<Name>,Vec<Expression>);
|
||||
struct Call(Option<Name>, Vec<Expression>);
|
||||
#[derive(Debug)]
|
||||
struct Function(Vec<Piece<Name>>,Option<Piece<VarArg>>,Piece<Block>);
|
||||
struct Function(Vec<Piece<Name>>, Option<Piece<VarArg>>, Piece<Block>);
|
||||
#[derive(Debug)]
|
||||
struct Field(Option<Expression>,Expression);
|
||||
struct Field(Option<Expression>, Expression);
|
||||
#[derive(Debug)]
|
||||
enum FieldSep {
|
||||
Comma,
|
||||
Semicolon
|
||||
Semicolon,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum BinaryOp {
|
||||
@@ -319,14 +359,14 @@ enum BinaryOp {
|
||||
Equivalent,
|
||||
NotEqual,
|
||||
And,
|
||||
Or
|
||||
Or,
|
||||
}
|
||||
#[derive(Debug)]
|
||||
enum UnaryOp {
|
||||
Negate,
|
||||
Not,
|
||||
Ampersand,
|
||||
Tilde
|
||||
Tilde,
|
||||
}
|
||||
|
||||
impl<T: Parse> Parse for Vec<Piece<T>> {
|
||||
@@ -334,22 +374,23 @@ impl<T: Parse> Parse for Vec<Piece<T>> {
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
let result: Vec<Piece<T>> = Vec::new();
|
||||
let mut result: Vec<Piece<T>> = Vec::new();
|
||||
reader.trim()?;
|
||||
loop {
|
||||
if let Ok(it) = reader.take::<T>() {
|
||||
result.push(it);
|
||||
reader.trim()?;
|
||||
if !reader.consume(",").is_ok() {
|
||||
break
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if result.is_empty() {
|
||||
return reader.error(format!("Expected {}s",std::any::type_name::<T>()).as_str());
|
||||
return reader.error(format!("Expected {}s", std::any::type_name::<T>()).as_str());
|
||||
}
|
||||
let first = result.first().unwrap().null();
|
||||
let last = result.last().unwrap().null();
|
||||
Ok(Piece::from(result,&first,&last))
|
||||
Ok(Piece::from(result, &first, &last))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -361,25 +402,25 @@ impl Parse for Function {
|
||||
let mut parameters: Vec<Piece<Name>> = Vec::new();
|
||||
let mut vararg = None;
|
||||
loop {
|
||||
reader.trim()?;
|
||||
if let Ok(name) = reader.take::<Name>() {
|
||||
parameters.push(name);
|
||||
reader.trim()?;
|
||||
if vararg.is_some() {
|
||||
return reader.error("Unexpected argument after vararg '...'")
|
||||
return reader.error("Unexpected argument after vararg '...'");
|
||||
}
|
||||
if !reader.consume(",").is_ok() {
|
||||
break
|
||||
break;
|
||||
}
|
||||
}
|
||||
vararg = reader.take::<VarArg>().ok()
|
||||
}
|
||||
reader.trim()?;
|
||||
reader.consume(")")?;
|
||||
reader.trim()?;
|
||||
let end = reader.marker();
|
||||
let block = reader.take::<Block>()?;
|
||||
Ok(Piece::from(Function(parameters,vararg,block),&start,&end))
|
||||
Ok(Piece::from(
|
||||
Function(parameters, vararg, block),
|
||||
&start,
|
||||
&end,
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -395,177 +436,217 @@ impl Parse for VarArg {
|
||||
Ok(Piece::from(VarArg(Some(name.it)), &start, &end))
|
||||
} else {
|
||||
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 {
|
||||
fn consume(reader: &mut Reader) -> Result<Piece<Self>, Error> {
|
||||
reader.trim()?;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Call {
|
||||
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 {
|
||||
fn consume(mut reader: &mut Reader) -> Result<Piece<Statement>, 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()?;
|
||||
fn consume(initial: &mut Reader) -> Result<Piece<Statement>, 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() {
|
||||
reader.trim()?;
|
||||
let name = reader.take::<Name>()?;
|
||||
reader.trim()?;
|
||||
let function = reader.take::<Function>()?;
|
||||
restore(&mut reader);
|
||||
Ok(Piece::from(Statement::LocalFunction(name, function.it), &start, &function.null()))
|
||||
*initial = *reader;
|
||||
Ok(Piece::from(
|
||||
Statement::LocalFunction(name, function.it),
|
||||
&start,
|
||||
&function.null(),
|
||||
))
|
||||
} else {
|
||||
let names = reader.take::<Vec<Piece<Name>>>()?.it;
|
||||
reader.trim()?;
|
||||
reader.consume("=")?;
|
||||
reader.trim()?;
|
||||
let expressions = reader.take::<Vec<Piece<Expression>>>()?.it;
|
||||
restore(&mut reader);
|
||||
Ok(Piece::from(Statement::Declaration(names,expressions),&start,&reader.marker()))
|
||||
*initial = *reader;
|
||||
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();
|
||||
loop {
|
||||
reader.trim()?;
|
||||
if let Ok(name) = reader.take::<Name>() {
|
||||
names.push(name);
|
||||
reader.trim()?;
|
||||
if !reader.consume(".").is_ok() {
|
||||
break
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut member = None;
|
||||
if reader.consume(":").is_ok() {
|
||||
reader.trim()?;
|
||||
member = Some(reader.take::<Name>()?);
|
||||
}
|
||||
let function = reader.take::<Function>()?;
|
||||
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::<Vec<Piece<Name>>>()?.it; reader.trim()?;
|
||||
*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::<Vec<Piece<Name>>>()?.it;
|
||||
let result = if names.len() > 1 {
|
||||
let name = *names.first().unwrap().clone();
|
||||
reader.consume("=")?; reader.trim()?;
|
||||
let begin = reader.take::<Expression>()?; reader.trim()?;
|
||||
reader.consume(",")?; reader.trim()?;
|
||||
let finish = reader.take::<Expression>()?; reader.trim()?;
|
||||
reader.consume("=")?;
|
||||
let begin = reader.take::<Expression>()?;
|
||||
reader.consume(",")?;
|
||||
let finish = reader.take::<Expression>()?;
|
||||
let delta = if reader.consume(",").is_ok() {
|
||||
reader.trim()?;
|
||||
Some(reader.take::<Expression>()?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
reader.consume("do")?; reader.trim()?;
|
||||
let block = reader.take::<Block>()?; reader.trim()?;
|
||||
reader.consume("do")?;
|
||||
let block = reader.take::<Block>()?;
|
||||
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 {
|
||||
reader.consume("in")?; reader.trim()?;
|
||||
let expressions = reader.take::<Vec<Piece<Expression>>>()?.it; reader.trim()?;
|
||||
reader.consume("do")?; reader.trim()?;
|
||||
let block = reader.take::<Block>()?; reader.trim()?;
|
||||
reader.consume("in")?;
|
||||
let expressions = reader.take::<Vec<Piece<Expression>>>()?.it;
|
||||
reader.consume("do")?;
|
||||
let block = reader.take::<Block>()?;
|
||||
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
|
||||
} else if let Ok(mut reader) = reader.consume("while") {
|
||||
reader.trim()?;
|
||||
} else if let Ok(mut reader) = initial.clone().consume("while") {
|
||||
let condition = reader.take::<Expression>()?;
|
||||
reader.consume("do")?; reader.trim()?;
|
||||
let block = reader.take::<Block>()?; reader.trim()?;
|
||||
reader.consume("do")?;
|
||||
let block = reader.take::<Block>()?;
|
||||
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()?;
|
||||
*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::<Expression>()?); reader.trim()?;
|
||||
reader.consume("then")?; reader.trim()?;
|
||||
let branch = || -> Result<(), Error> {
|
||||
conditions.push(reader.take::<Expression>()?);
|
||||
reader.consume("then")?;
|
||||
blocks.push(reader.take::<Block>()?.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::<Block>()?.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()?;
|
||||
*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::<Name>()?;
|
||||
restore(&mut reader);
|
||||
Ok(Piece::from(Statement::Goto(name),&start,&reader.marker()))
|
||||
} else if let Ok(mut reader) = reader.consume("do") {
|
||||
reader.trim()?;
|
||||
*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::<Block>()?;
|
||||
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::<Block>()?; reader.trim()?;
|
||||
reader.consume("until")?; reader.trim()?;
|
||||
*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::<Block>()?;
|
||||
reader.consume("until")?;
|
||||
let condition = reader.take::<Expression>()?;
|
||||
restore(&mut reader);
|
||||
Ok(Piece::from(Statement::Repeat(block.it,condition),&start,&reader.marker()))
|
||||
} else if let Ok(mut reader) = reader.consume("::") {
|
||||
*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::<Name>()?;
|
||||
reader.consume("::")?;
|
||||
restore(&mut reader);
|
||||
Ok(Piece::from(Statement::Label(name),&start,&reader.marker()))
|
||||
} else if let Ok(mut reader) =
|
||||
*initial = *reader;
|
||||
Ok(Piece::from(
|
||||
Statement::Label(name),
|
||||
&start,
|
||||
&reader.marker(),
|
||||
))
|
||||
} else {
|
||||
reader.take::<Call>().map(|call| Statement::Call(call)).or_else(|| reader.take::)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Block {
|
||||
fn consume(reader: &mut Reader) -> Result<Piece<Block>, Error>
|
||||
where
|
||||
Self: Sized
|
||||
Self: Sized,
|
||||
{
|
||||
let mut statements = Vec::new();
|
||||
let start = reader.marker();
|
||||
while let Ok(statement) = reader.take::<Statement>() {
|
||||
statements.push(statement);
|
||||
}
|
||||
if statements.is_empty() {
|
||||
Ok(Piece::of(Block(statements),reader,0))
|
||||
let expressions = if reader.consume("return").is_ok() {
|
||||
let result = reader.take::<Vec<Piece<Expression>>>()?;
|
||||
reader.consume(";").ok();
|
||||
result.it
|
||||
} else {
|
||||
let first = statements.first().unwrap().null();
|
||||
let last = statements.last().unwrap().null();
|
||||
Ok(Piece::from(Block(statements),&first,&last))
|
||||
}
|
||||
Vec::new()
|
||||
};
|
||||
Ok(Piece::from(
|
||||
Block(statements, expressions),
|
||||
&start,
|
||||
&reader.marker(),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse(str: &str) -> Result<Block,Error> {
|
||||
fn parse(str: &str) -> Result<Block, Error> {
|
||||
Reader::from(str).take::<Block>().map(|piece| piece.it)
|
||||
}
|
||||
|
||||
@@ -574,6 +655,6 @@ mod tests {
|
||||
use super::*;
|
||||
#[test]
|
||||
fn simple() {
|
||||
println!("{:?}",parse(include_str!("assets/script.lua")).unwrap());
|
||||
println!("{:?}", parse(include_str!("assets/script.lua")).unwrap());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user