use chomatter_commons::{
statements::{self as sts, SpeekProperty, Statement},
walker::{EGoto, EMover, Walker},
EGenericToken, GenericToken, Segment,
};
const EXPR_TERMINATORS: &[EGenericToken] = &[
EGenericToken::RightBrace,
EGenericToken::Comma,
EGenericToken::EndOfLine,
EGenericToken::Colon,
EGenericToken::Assign,
EGenericToken::RightParen,
];
pub trait Syntax {
fn parse(&mut self, data: &str, scope_level: usize) -> Vec<Statement>;
fn trim(&mut self) -> Walker<GenericToken>;
fn cook(raw: &str) -> String;
fn resolve_template_string(&mut self, data: &str) -> Statement;
fn resolve_props(&mut self, data: &str) -> Option<Vec<SpeekProperty>>;
fn resolve_expr(&mut self, data: &str, terminators: &[EGenericToken]) -> Statement;
}
fn is_empty_token(token: &GenericToken) -> bool {
match token.kind {
EGenericToken::Indent | EGenericToken::Space => true,
_ => false,
}
}
fn resolve_arguments(walker: &mut Walker<GenericToken>, data: &str) -> Vec<Statement> {
let mut args = Vec::new();
while !walker.is_eof() {
if walker.match_token(EGenericToken::RightParen) {
walker.next();
break;
}
if walker.match_token(EGenericToken::Comma) {
walker.next();
continue;
}
args.push(walker.resolve_expr(data, &[EGenericToken::RightParen]));
}
args
}
fn resolve_member(tester: &mut Walker<GenericToken>, data: &String) -> Statement {
let prop = tester.current();
let name = prop.segment.to_string(data);
if let Some(p) = tester.prev() {
if p.kind == EGenericToken::Dot {
tester.prev();
let obj = resolve_member(tester, data);
return sts::Statement::MemberExpression(sts::MemberExpression {
kind: sts::EStatatement::MemberExpression,
object: Box::new(obj),
property: Box::new(sts::Statement::Identifier(sts::Identifier {
kind: sts::EStatatement::Identifier,
name,
})),
});
}
}
return Statement::Identifier(sts::Identifier {
kind: sts::EStatatement::Identifier,
name,
});
}
fn do_resolver(
walker: &mut Walker<GenericToken>,
id: &str,
data: &str,
scope_level: usize,
) -> Statement {
match id {
"question" => {
walker.forward().expect("Expected colon after question");
walker.forward().expect("Expected end of line after colon");
let statements = walker.parse(data, scope_level + 1);
walker.advance_by(1);
let mut check_level = 0;
while !walker.is_end() && walker.current().kind == EGenericToken::Indent {
walker.forward();
check_level += 1;
}
if check_level != scope_level {
panic!(
"Expected indent level to be {} but was {}",
scope_level, check_level
);
}
if walker.match_token(EGenericToken::Arrow) {
walker.forward().expect("Expected end of line after arrow");
let mut answers = Vec::new();
let mut indent_level = 0;
let answers_scope = scope_level + 1;
let mut last_end_line = walker.position();
while !walker.is_eof() {
if walker.match_token(EGenericToken::EndOfLine) {
indent_level = 0;
last_end_line = walker.position();
walker.advance_by(1);
continue;
} else if walker.match_token(EGenericToken::Indent) {
indent_level += 1;
walker.advance_by(1);
continue;
} else if indent_level < answers_scope {
walker.goto(EGoto::Target(last_end_line));
break;
}
if walker.match_token(EGenericToken::StringLiteral)
|| walker.match_token(EGenericToken::BeginTemplateString)
|| walker.match_token(EGenericToken::Identifier)
{
let answer_text = walker.resolve_expr(data, &[]);
walker.forward().expect("Expected colon after answer");
walker.forward().expect("Expected end of line after colon");
let answer_statements = walker.parse(data, answers_scope + 1);
answers.push(sts::Answer {
kind: sts::EStatatement::Answer,
statements: answer_statements,
value: Box::new(answer_text),
});
} else {
panic!(
"Expected string or template string, got {:?}",
walker.current()
);
}
}
return Statement::Question(sts::Question {
kind: sts::EStatatement::Question,
answers,
statements,
});
}
panic!("Not implemented. Got {:?}", walker.current());
}
"random" => {
walker.forward().expect("Expected colon after question");
walker.forward().expect("Expected end of line after colon");
let mut options = Vec::new();
while !walker.is_eof() {
walker.advance_by(1);
let mut check_level = 0;
while !walker.is_end() && walker.current().kind == EGenericToken::Indent {
walker.forward();
check_level += 1;
}
if check_level != scope_level {
break;
}
if walker.match_token(EGenericToken::Arrow) {
let mut chance = None;
walker.forward().expect("Expected end of line after arrow");
if (walker.current().kind == EGenericToken::LeftParen) {
walker
.forward()
.expect("Expected expression after left paren");
let expr = walker.resolve_expr(data, &[EGenericToken::RightParen]);
chance = Some(Box::new(expr));
walker
.forward()
.expect("Expected end of line after right paren");
}
walker.forward().expect("Expected statement after arrow");
let statements = walker.parse(data, scope_level + 1);
options.push(sts::RandomOption {
kind: sts::EStatatement::RandomOption,
chance,
statements,
});
} else {
walker.backward(EMover::Until(|x| x.kind == EGenericToken::EndOfLine));
break;
}
}
return Statement::DoRandom(sts::DoRandom {
kind: sts::EStatatement::DoRandom,
options,
});
}
value => {
panic!("{} is not a valid statement", value);
}
}
}
impl Syntax for Walker<GenericToken> {
fn resolve_expr(&mut self, data: &str, terminators: &[EGenericToken]) -> Statement {
if self.match_token(EGenericToken::NumberLiteral) {
let number = self.current();
let raw = number.segment.to_string(&data.to_string());
let value;
if raw.contains(".") {
value = sts::Number::Float(
raw.parse::<f64>()
.expect(&format!("Unable to parse number {}", raw)),
);
} else {
value = sts::Number::Integer(
raw.parse::<i64>()
.expect(&format!("Unable to parse number {}", raw)),
);
};
self.advance_by(1);
if self.match_tokens(EXPR_TERMINATORS) || self.match_tokens(terminators) {
return sts::Statement::NumberLiteral(sts::NumberLiteral {
kind: sts::EStatatement::NumberLiteral,
raw,
value,
});
} else if self.match_token(EGenericToken::Operator) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(sts::Statement::NumberLiteral(sts::NumberLiteral {
kind: sts::EStatatement::NumberLiteral,
raw,
value,
})),
operator,
right: Box::new(right),
});
}
} else if self.match_token(EGenericToken::BooleanLiteral) {
let boolean = self.current();
let raw = boolean.segment.to_string(&data.to_string());
self.advance_by(1);
let value = match raw.as_str() {
"true" | "yes" | "on" => true,
_ => false,
};
if self.match_tokens(EXPR_TERMINATORS) || self.match_tokens(terminators) {
return sts::Statement::BooleanLiteral(sts::BooleanLiteral {
kind: sts::EStatatement::BooleanLiteral,
raw,
value,
});
} else if self.match_token(EGenericToken::Operator) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(sts::Statement::BooleanLiteral(sts::BooleanLiteral {
kind: sts::EStatatement::BooleanLiteral,
raw,
value,
})),
operator,
right: Box::new(right),
});
} else if self.match_token(EGenericToken::Operator) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(sts::Statement::BooleanLiteral(sts::BooleanLiteral {
kind: sts::EStatatement::BooleanLiteral,
raw,
value,
})),
operator,
right: Box::new(right),
});
}
} else if self.match_token(EGenericToken::StringLiteral) {
let string = self.current();
let raw = string.segment.to_string(&data.to_string());
let value = raw.clone();
self.advance_by(1);
if self.match_tokens(EXPR_TERMINATORS) || self.match_tokens(terminators) {
return sts::Statement::StringLiteral(sts::StringLiteral {
kind: sts::EStatatement::StringLiteral,
raw,
value,
});
} else if self.match_token(EGenericToken::Operator) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(sts::Statement::StringLiteral(sts::StringLiteral {
kind: sts::EStatatement::StringLiteral,
raw,
value,
})),
operator,
right: Box::new(right),
});
} else if self.match_token(EGenericToken::Operator) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(sts::Statement::StringLiteral(sts::StringLiteral {
kind: sts::EStatatement::StringLiteral,
raw,
value,
})),
operator,
right: Box::new(right),
});
}
} else if self.match_token(EGenericToken::BeginTemplateString) {
let property = self.resolve_template_string(data);
if self.match_token(EGenericToken::EndTemplateString) {
self.advance_by(1);
}
if self.match_tokens(EXPR_TERMINATORS) || self.match_tokens(terminators) {
return property;
} else if self.match_token(EGenericToken::Operator) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(property),
operator,
right: Box::new(right),
});
}
} else if self.match_token(EGenericToken::Identifier) {
let mark = self.position();
let mut tester = self.clone();
tester.forward_custom(chomatter_commons::walker::EMover::WhileBy(|x, y, z, w| {
if *z == 0 {
*z = 1;
return x.kind == EGenericToken::Identifier;
}
*z = 0;
x.kind == EGenericToken::Dot
}));
if tester.match_token(EGenericToken::LeftParen) && !self.match_tokens(terminators) {
let end = tester.position();
tester.prev();
let callee = resolve_member(&mut tester, &data.to_string());
self.goto(EGoto::Target(end));
self.advance_by(1);
let arguments = resolve_arguments(self, data);
return sts::Statement::CallExpression(sts::CallExpression {
kind: sts::EStatatement::CallExpression,
callee: Box::new(callee),
arguments,
});
}
else if tester.match_token(EGenericToken::Assign) && !tester.match_tokens(terminators)
{
let assign_pivot = tester.position();
let operator = tester.current().segment.to_string(&data.to_string());
self.goto(EGoto::Target(mark));
let left_expr = self.resolve_expr(data, &[EGenericToken::Assign]);
self.goto(EGoto::Target(assign_pivot));
self.forward().expect("Expected expression after assign");
let right_expr = self.resolve_expr(data, &[]);
return Statement::Assign(sts::Assign {
kind: sts::EStatatement::Assign,
object: Box::new(left_expr),
value: Box::new(right_expr),
operator,
default: false,
});
}
else if self.position() + 1 < tester.position() {
let end = tester.position();
tester.prev();
let statement = resolve_member(&mut tester, &data.to_string());
self.goto(EGoto::Target(end));
if self.match_token(EGenericToken::Operator) && !self.match_tokens(terminators) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(statement),
operator,
right: Box::new(right),
});
}
return statement;
}
else {
let identifier = self.current();
let name = identifier.segment.to_string(&data.to_string());
self.advance_by(1);
if self.match_token(EGenericToken::Operator) && !self.match_tokens(terminators) {
let operator = self.current().segment.to_string(&data.to_string());
self.advance_by(1);
let right = self.resolve_expr(data, &[]);
return sts::Statement::OperatorExpression(sts::OperatorExpression {
kind: sts::EStatatement::Operation,
left: Box::new(sts::Statement::Identifier(sts::Identifier {
kind: sts::EStatatement::Identifier,
name,
})),
operator,
right: Box::new(right),
});
}
return sts::Statement::Identifier(sts::Identifier {
kind: sts::EStatatement::Identifier,
name,
});
}
}
panic!("{:?} is not a valid expression", self.current());
}
fn resolve_props(&mut self, data: &str) -> Option<Vec<SpeekProperty>> {
let mut props = Vec::new();
self.advance_by(1);
while !self.is_eof() {
if self.match_token(EGenericToken::RightBrace) {
break;
}
if self.match_sequence(&[EGenericToken::Identifier, EGenericToken::Assign]) {
let name = self.next().unwrap().segment.to_string(&data.to_string());
self.advance_by(1);
props.push(SpeekProperty {
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name,
},
kind: sts::EStatatement::SpeekProperty,
value: Box::new(self.resolve_expr(&data.to_string(), &[])),
});
} else if self.match_tokens(&[EGenericToken::Comma]) {
self.advance_by(1);
} else {
panic!("Invalid token at props {:?}", self.current());
}
}
if props.len() > 0 {
Some(props)
} else {
None
}
}
fn resolve_template_string(&mut self, data: &str) -> Statement {
let mut parts = Vec::new();
self.advance_by(1);
while !self.is_eof() {
if self.match_token(EGenericToken::EndTemplateString) {
break;
} else if self.match_token(EGenericToken::StringPart) {
let part = self.current();
let raw = part.segment.to_string(&data.to_string());
let mut value = Walker::cook(&raw);
if value.len() > 0 {
parts.push(Statement::StringLiteral(sts::StringLiteral {
kind: sts::EStatatement::StringLiteral,
raw,
value,
}));
}
self.advance_by(1);
} else {
let exp = self.resolve_expr(&data.to_string(), &[]);
parts.push(exp);
}
}
if parts.len() == 1 {
let part = parts.first().unwrap();
if let Statement::StringLiteral(_) = part {
return part.clone();
}
}
sts::Statement::TemplateString(sts::TemplateString {
kind: sts::EStatatement::TemplateString,
parts,
})
}
fn cook(raw: &str) -> String {
let mut string = String::new();
let mut index = 0;
let mut len = raw.chars().count();
if raw.starts_with("}") || raw.starts_with("\"") || raw.starts_with("'") {
index = 1;
}
if raw.ends_with("#{") {
len -= 2;
}
if raw.ends_with("\"") || raw.ends_with("'") {
len -= 1;
}
while index < len {
let char = raw.chars().nth(index).unwrap();
if char == '\\' {
index += 1;
let char = raw.chars().nth(index).unwrap();
match char {
'\'' => string.push('\''),
'\"' => string.push('"'),
'n' => string.push('\n'),
'r' => string.push('\r'),
't' => string.push('\t'),
_ => string.push(char),
}
} else {
string.push(char);
index += 1;
}
}
string
}
fn parse(&mut self, data: &str, scope_level: usize) -> Vec<Statement> {
let mut statements = Vec::new();
let mut indent_level = 0;
let mut last_end_line = self.position();
while !self.is_eof() {
if self.match_token(EGenericToken::EndOfLine) {
indent_level = 0;
last_end_line = self.position();
self.advance_by(1);
continue;
} else if self.match_token(EGenericToken::Indent) {
indent_level += 1;
self.advance_by(1);
continue;
} else if indent_level < scope_level {
self.goto(EGoto::Target(last_end_line));
break;
}
if self.match_token(EGenericToken::New) {
self.forward().expect("Expected space after new");
self.forward().expect("Expected identifier after new");
let id = self.current().segment.to_string(&data.to_string());
self.forward().expect("Expected colon after new");
self.forward().expect("Expected end of line after colon");
let mut props = Vec::new();
let mut indent = 0;
while !self.is_eof() {
if self.match_token(EGenericToken::EndOfLine) {
indent = 0;
last_end_line = self.position();
self.advance_by(1);
continue;
} else if self.match_token(EGenericToken::Indent) {
indent += 1;
self.advance_by(1);
continue;
} else if indent < indent_level + 1 {
self.goto(EGoto::Target(last_end_line));
break;
}
if self.match_sequence(&[EGenericToken::Identifier, EGenericToken::Colon]) {
let name = self.next().unwrap().segment.to_string(&data.to_string());
self.advance_by(2);
let exp = self.resolve_expr(&data.to_string(), &[]);
props.push(sts::Property {
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name,
},
kind: sts::EStatatement::Property,
value: Box::new(exp),
});
} else {
println!("Ignoring at new token {:?}", self.current());
self.advance_by(1);
}
}
let props = if props.len() > 0 { Some(props) } else { None };
statements.push(Statement::SpeekerDeclaration(sts::SpeekerDeclaration {
kind: sts::EStatatement::SpeekerDeclaration,
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name: id,
},
properties: props,
}));
} else if self.match_token(EGenericToken::If) {
self.forward().expect("Expected space after if");
self.forward().expect("Expected expression after if");
let condition = self.resolve_expr(&data.to_string(), &[]);
self.forward().expect("Expected colon after if");
self.forward().expect("Expected end of line after colon");
let if_statements = self.parse(data, scope_level + 1);
let mark = self.position();
self.next();
let mut indent = 0;
while !self.is_eof() {
if self.match_token(EGenericToken::EndOfLine) {
indent = 0;
last_end_line = self.position();
self.advance_by(1);
break;
} else if self.match_token(EGenericToken::Indent) {
indent += 1;
self.advance_by(1);
continue;
} else {
break;
}
}
if indent < scope_level {
self.goto(EGoto::Target(mark));
}
let mut elifs = Vec::new();
while self.match_token(EGenericToken::ElseIf) {
self.forward().expect("Expected space after else if");
self.forward().expect("Expected expression after else if");
let condition = self.resolve_expr(&data.to_string(), &[]);
self.forward().expect("Expected colon after else");
self.forward().expect("Expected end of line after colon");
let else_statements = self.parse(data, scope_level + 1);
elifs.push(sts::Elif {
kind: sts::EStatatement::ElseIf,
condition: Box::new(condition),
statements: else_statements,
});
}
let mut indent = 0;
let mark = self.position();
self.advance_by(1);
while !self.is_eof() {
if self.match_token(EGenericToken::EndOfLine) {
indent = 0;
last_end_line = self.position();
self.advance_by(1);
break;
} else if self.match_token(EGenericToken::Indent) {
indent += 1;
self.advance_by(1);
continue;
} else {
break;
}
}
if indent < scope_level {
self.goto(EGoto::Target(mark));
}
let mut unless = None;
if self.match_token(EGenericToken::Else) {
self.forward().expect("Expected end of line after colon");
unless = Some(self.parse(data, scope_level + 1));
}
statements.push(Statement::If(sts::If {
kind: sts::EStatatement::If,
condition: Box::new(condition),
statements: if_statements,
elifs,
unless,
}));
}
else if self.match_token(EGenericToken::Case) {
self.forward().expect("Expected space after case");
self.forward().expect("Expected identifier after case");
let identifier = self.current().segment.to_string(&data.to_string());
self.forward().expect("Expected colon after identifier");
self.forward().expect("Expected end of line after colon");
self.forward().expect("Blank block after case");
let mut case_statements = self.parse(data, scope_level + 1);
statements.push(Statement::Case(sts::Case {
kind: sts::EStatatement::Case,
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name: identifier,
},
statements: case_statements,
}));
}
else if self.match_sequence(&[EGenericToken::Identifier, EGenericToken::Colon]) {
let identifier = self.current().segment.to_string(&data.to_string());
self.forward().expect("Expected colon after identifier");
self.forward().expect("Expected space after colon");
self.forward().expect("Expected string after space");
let id = sts::Identifier {
kind: sts::EStatatement::Identifier,
name: identifier,
};
let mut tbody = self.current();
let mut body: Statement;
if tbody.kind == EGenericToken::StringLiteral {
let raw = tbody.segment.to_string(&data.to_string());
let value = Self::cook(&raw);
body = Statement::StringLiteral(sts::StringLiteral {
kind: sts::EStatatement::StringLiteral,
raw,
value,
});
} else if tbody.kind == EGenericToken::BeginTemplateString {
body = self.resolve_template_string(data);
} else {
panic!("Expected string after space. Got {:?}", tbody);
}
let mut properties = None;
if let Some(t) = self.forward() {
if t.kind == EGenericToken::Space {
if let Some(t) = self.forward() {
if t.kind == EGenericToken::LeftBrace {
properties = self.resolve_props(data);
self.advance_by(1);
}
}
}
}
statements.push(Statement::Speek(sts::Speek {
kind: sts::EStatatement::Speek,
id,
body: Box::new(body),
properties,
}));
}
else if self.match_token(EGenericToken::Input) {
self.forward().expect("Expected space after input");
self.forward().expect("Expected expression after space");
let expr = self.resolve_expr(data, &[]);
statements.push(Statement::Input(sts::Input {
kind: sts::EStatatement::Input,
object: Box::new(expr),
}));
indent_level = 0;
}
else if self.match_token(EGenericToken::Default) {
self.forward().expect("Expected space after default");
self.forward().expect("Expected expression after space");
let expr = self.resolve_expr(data, &[EGenericToken::Assign]);
let operator = self.current().segment.to_string(&data.to_string());
self.forward().expect("Expected expression after assign");
let value = self.resolve_expr(data, &[]);
statements.push(Statement::Assign(sts::Assign {
kind: sts::EStatatement::Assign,
object: Box::new(expr),
value: Box::new(value),
operator,
default: true,
}));
indent_level = 0;
}
else if self.match_token(EGenericToken::Jump) {
self.forward().expect("Expected space after jump");
self.forward().expect("Expected identifier after space");
let identifier = self.current().segment.to_string(&data.to_string());
statements.push(Statement::Jump(sts::Jump {
kind: sts::EStatatement::Jump,
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name: identifier,
},
}));
self.advance_by(1);
indent_level = 0;
}
else if self.match_token(EGenericToken::Import) {
self.forward().expect("Expected space after Import");
self.forward().expect("Expected identifier after space");
let expr = self.resolve_expr(data, &[]);
statements.push(Statement::Import(sts::Import {
kind: sts::EStatatement::Import,
path: Box::new(expr),
}));
self.advance_by(1);
indent_level = 0;
}
else if self.match_token(EGenericToken::Goto) {
self.forward().expect("Expected space after goto");
self.forward().expect("Expected identifier after space");
let identifier = self.current().segment.to_string(&data.to_string());
statements.push(Statement::Goto(sts::Goto {
kind: sts::EStatatement::Goto,
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name: identifier,
},
}));
self.advance_by(1);
indent_level = 0;
}
else if self.match_token(EGenericToken::Call) {
self.forward().expect("Expected space after call");
self.forward().expect("Expected identifier after space");
let identifier = self.current().segment.to_string(&data.to_string());
statements.push(Statement::Call(sts::Call {
kind: sts::EStatatement::Call,
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name: identifier,
},
}));
self.advance_by(1);
indent_level = 0;
} else if self.match_token(EGenericToken::Return) {
statements.push(Statement::Return(sts::Return {
kind: sts::EStatatement::Return,
value: None,
iter: false,
}));
self.advance_by(1);
indent_level = 0;
} else if self.match_token(EGenericToken::Continue) {
statements.push(Statement::LoopKeyword(sts::LoopKeyword {
kind: sts::EStatatement::Continue,
}));
self.advance_by(1);
indent_level = 0;
} else if self.match_token(EGenericToken::Break) {
statements.push(Statement::LoopKeyword(sts::LoopKeyword {
kind: sts::EStatatement::Break,
}));
self.advance_by(1);
indent_level = 0;
} else if self.match_token(EGenericToken::Yield) {
statements.push(Statement::Return(sts::Return {
kind: sts::EStatatement::Return,
value: None,
iter: true,
}));
self.advance_by(1);
indent_level = 0;
}
else if self.match_token(EGenericToken::Do) {
self.forward().expect("Expected space after do");
self.forward().expect("Expected identifier after space");
let identifier = self.current().segment.to_string(&data.to_string());
statements.push(do_resolver(self, &identifier, data, indent_level));
indent_level = 0;
}
else if self.match_token(EGenericToken::Identifier) {
let expr = self.resolve_expr(data, &[]);
statements.push(expr);
indent_level = 0;
}
else if self.match_token(EGenericToken::ScopedVar)
|| self.match_token(EGenericToken::GlobalVar)
{
let global;
if self.match_token(EGenericToken::ScopedVar) {
global = false;
} else {
global = true;
}
self.forward().expect("Expected space after var");
self.forward().expect("Expected identifier after space");
let left = self.resolve_expr(data, &[EGenericToken::Assign]);
self.forward().expect("Expected expression after assign");
let right = self.resolve_expr(data, &[]);
statements.push(Statement::VariableDeclaration(sts::VariableDeclaration {
kind: sts::EStatatement::VariableDeclaration,
id: Box::new(left),
value: Box::new(right),
global,
}));
}
else if self.match_token(EGenericToken::Function) {
self.forward().expect("Expected space after function");
self.forward().expect("Expected identifier after space");
let identifier = self.current().segment.to_string(&data.to_string());
self.forward()
.expect("Expected left parenthesis after identifier");
self.forward()
.expect("Expected expression after left parenthesis");
let mut args = resolve_arguments(self, data);
self.prev();
self.forward()
.expect("Expected right parenthesis after arguments");
self.forward()
.expect("Expected colon after right parenthesis");
self.forward().expect("Expected end of line after colon");
let body = self.parse(data, indent_level + 1);
statements.push(Statement::Function(sts::Function {
kind: sts::EStatatement::Function,
id: sts::Identifier {
kind: sts::EStatatement::Identifier,
name: identifier,
},
parameters: args,
statements: body,
}));
} else {
panic!(
"Unexpected token {:?}. scope: {} indent: {}",
self.current(),
scope_level,
indent_level
);
}
}
statements
}
fn trim(&mut self) -> Walker<GenericToken> {
let mut vecs = self.tokens.clone();
vecs.retain(|t| {
t.kind != EGenericToken::LineComment && t.kind != EGenericToken::BlockComment
});
let mut walker = Walker::new(vecs);
while !walker.is_eof() {
if walker.match_token(EGenericToken::LineComment)
|| walker.match_token(EGenericToken::BlockComment)
{
walker.remove();
} else if walker.match_sequence(&[EGenericToken::Space, EGenericToken::Space]) {
walker.advance_by(1);
while !walker.is_eof() {
let token = walker.current().kind;
if token != EGenericToken::Space {
break;
}
walker.remove();
}
}
else if walker.match_tokens(&[
EGenericToken::Colon,
EGenericToken::RightParen,
EGenericToken::RightBrace,
EGenericToken::RightBracket,
EGenericToken::EndOfLine,
]) {
walker.prev();
while walker.current().kind == EGenericToken::Space
|| walker.current().kind == EGenericToken::Indent
|| walker.current().kind == EGenericToken::EndOfLine
{
walker.remove();
walker.prev();
}
walker.advance_by(2);
}
else if walker.match_tokens(&[
EGenericToken::LeftBrace,
EGenericToken::LeftParen,
EGenericToken::LeftBracket,
]) {
walker.advance_by(1);
while walker.current().kind == EGenericToken::Space {
walker.remove();
}
}
else if walker.match_tokens(&[
EGenericToken::Comma,
EGenericToken::Assign,
EGenericToken::Operator,
EGenericToken::Unary,
]) {
walker.prev();
while walker.current().kind == EGenericToken::Space {
walker.remove();
walker.prev();
}
walker.advance_by(2);
while walker.current().kind == EGenericToken::Space {
walker.remove();
}
} else {
walker.advance_by(1);
}
}
walker
}
}