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> {
|
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,53 +57,63 @@ 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) => {
|
||||||
self.slice = &self.slice[i+2..].trim();
|
let comment = &self.slice[4..i + 2];
|
||||||
Ok(self)
|
self.slice = &self.slice[i + 2..].trim();
|
||||||
}
|
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> {
|
||||||
self.trim()?;
|
self.trim()?;
|
||||||
if self.slice.starts_with(start) {
|
if self.slice.starts_with(start) {
|
||||||
self.slice = &self.slice[start.len()..];
|
self.slice = &self.slice[start.len()..];
|
||||||
Ok(self)
|
Ok(self)
|
||||||
} else {
|
} 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()?;
|
self.trim()?;
|
||||||
T::consume(self)
|
T::consume(self)
|
||||||
}
|
}
|
||||||
fn error<T>(&self, message: &str) -> Result<T,Error> {
|
fn error<T>(&self, message: &str) -> Result<T, Error> {
|
||||||
Error::new(message,self)
|
Error::new(message, self)
|
||||||
}
|
}
|
||||||
fn marker(&self) -> Piece<()> {
|
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
|
// - 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,31 +273,36 @@ 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,
|
||||||
Assignment(Vec<Piece<Variable>>,Vec<Piece<Expression>>),
|
Assignment(Vec<Piece<Variable>>, Vec<Piece<Expression>>),
|
||||||
Call(Call),
|
Call(Call),
|
||||||
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(
|
||||||
Iterator(Vec<Piece<Name>>,Vec<Piece<Expression>>,Block),
|
Piece<Name>,
|
||||||
Function(Vec<Piece<Name>>,Option<Piece<Name>>,Function),
|
Piece<Expression>,
|
||||||
LocalFunction(Piece<Name>,Function),
|
Piece<Expression>,
|
||||||
Declaration(Vec<Piece<Name>>,Vec<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)]
|
#[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 {
|
||||||
@@ -275,8 +315,8 @@ enum Expression {
|
|||||||
Function(Function),
|
Function(Function),
|
||||||
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 {
|
||||||
@@ -287,15 +327,15 @@ enum Prefix {
|
|||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct VarArg(Option<Name>);
|
struct VarArg(Option<Name>);
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Call(Option<Name>,Vec<Expression>);
|
struct Call(Option<Name>, Vec<Expression>);
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Function(Vec<Piece<Name>>,Option<Piece<VarArg>>,Piece<Block>);
|
struct Function(Vec<Piece<Name>>, Option<Piece<VarArg>>, Piece<Block>);
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Field(Option<Expression>,Expression);
|
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,22 +374,23 @@ 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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if result.is_empty() {
|
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 first = result.first().unwrap().null();
|
||||||
let last = result.last().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 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,177 +436,217 @@ 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(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse(str: &str) -> Result<Block,Error> {
|
fn parse(str: &str) -> Result<Block, Error> {
|
||||||
Reader::from(str).take::<Block>().map(|piece| piece.it)
|
Reader::from(str).take::<Block>().map(|piece| piece.it)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,6 +655,6 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
#[test]
|
#[test]
|
||||||
fn simple() {
|
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