Reid/src/parser/parsed_reid.rs

258 lines
8.9 KiB
Rust
Raw Normal View History

2020-06-24 18:29:16 +02:00
use super::{Expectable, Parser, Position, SyntaxError};
2020-06-21 00:45:09 +02:00
type Ident = String;
2020-06-22 20:49:21 +02:00
#[derive(Debug, Clone)]
2020-06-21 00:45:09 +02:00
pub struct ParsedReid(pub Expression);
2020-06-22 20:49:21 +02:00
#[derive(Debug, Clone)]
2020-06-21 00:45:09 +02:00
pub enum Statement {
LetStatement(Position, Ident, Box<Expression>),
2020-06-22 15:58:42 +02:00
ExprStatement(Position, Expression),
2020-06-21 00:45:09 +02:00
}
impl Statement {
2020-06-22 20:49:21 +02:00
pub fn parse(parser: &mut Parser) -> Result<Statement, SyntaxError> {
2020-06-21 00:45:09 +02:00
let pos = parser.pos();
2020-06-25 00:13:35 +02:00
if parser.expect_static("let").get().is_some() {
2020-06-21 00:45:09 +02:00
let ident = parser
.expect_ident()
2020-06-22 20:49:21 +02:00
.get_or(SyntaxError::ExpectedIdent(pos))?;
2020-06-21 00:45:09 +02:00
parser
2020-06-24 18:29:16 +02:00
.expect_static("=")
2020-06-22 20:49:21 +02:00
.get_or(SyntaxError::ExpectedToken(pos, '='))?;
2020-07-05 21:20:49 +02:00
match Expression::parse(parser, true) {
2020-06-21 00:45:09 +02:00
Ok(expr) => {
parser
2020-06-24 18:29:16 +02:00
.expect_static(";")
2020-06-22 20:49:21 +02:00
.get_or(SyntaxError::ExpectedToken(pos, ';'))?;
2020-06-21 00:45:09 +02:00
Ok(Statement::LetStatement(pos, ident, Box::new(expr)))
}
2020-06-22 20:49:21 +02:00
Err(err) => Err(SyntaxError::ExpectedExpression(pos, Some(Box::new(err)))),
2020-06-22 15:58:42 +02:00
}
} else {
2020-07-05 21:20:49 +02:00
match Expression::parse(parser, true) {
2020-06-22 15:58:42 +02:00
Ok(expr) => {
let statement = Statement::ExprStatement(pos, expr);
parser
2020-06-24 18:29:16 +02:00
.expect_static(";")
2020-06-22 20:49:21 +02:00
.get_or(SyntaxError::ExpectedToken(pos, ';'))?;
2020-06-22 15:58:42 +02:00
Ok(statement)
}
2020-06-22 20:49:21 +02:00
Err(err) => Err(SyntaxError::ExpectedStatement(pos, Some(Box::new(err)))),
2020-06-22 15:58:42 +02:00
}
}
}
}
2020-06-22 20:49:21 +02:00
#[derive(Debug, Clone)]
2020-06-22 15:58:42 +02:00
pub enum Expression {
BlockExpr(Position, Vec<Statement>),
2020-06-24 18:29:16 +02:00
FunctionCall(Position, Ident, Vec<Expression>),
2020-07-05 21:20:49 +02:00
ArithmeticExpression(Position, Box<ArithmeticExpression>),
2020-06-22 15:58:42 +02:00
ValueRef(Position, Pattern),
}
impl Expression {
2020-07-05 21:20:49 +02:00
pub fn parse(parser: &mut Parser, allow_arithmetic: bool) -> Result<Expression, SyntaxError> {
2020-06-22 15:58:42 +02:00
let begin_pos = parser.pos();
2020-07-05 21:20:49 +02:00
let first = if parser.expect_static("{").get().is_some() {
2020-06-22 15:58:42 +02:00
let mut statement_list = Vec::new();
while {
match Statement::parse(parser) {
Ok(exp) => {
statement_list.push(exp);
true
}
Err(_) => false,
}
} {}
2020-06-25 00:13:35 +02:00
if parser.expect_static("}").get().is_some() {
2020-06-22 15:58:42 +02:00
Ok(Expression::BlockExpr(begin_pos, statement_list))
} else {
2020-06-22 20:49:21 +02:00
Err(SyntaxError::ExpectedToken(parser.pos(), '}'))
2020-06-21 00:45:09 +02:00
}
2020-06-24 18:29:16 +02:00
} else if let Some(texts) = parser.expect_ident().and(Expectable::Static("(")).get() {
2020-06-24 20:58:16 +02:00
let pos = parser.pos();
2020-06-24 18:29:16 +02:00
let name = texts.get(0).unwrap();
let mut arg_list = Vec::new();
while {
2020-07-05 21:20:49 +02:00
match Expression::parse(parser, true) {
2020-06-24 18:29:16 +02:00
Ok(exp) => {
arg_list.push(exp);
2020-06-25 00:13:35 +02:00
parser.expect_static(",").get().is_some()
2020-06-24 18:29:16 +02:00
}
Err(err) => {
if arg_list.is_empty() {
false
} else {
return Err(err);
}
}
}
} {}
parser
.expect_static(")")
.get_or(SyntaxError::ExpectedToken(pos, ')'))?;
Ok(Expression::FunctionCall(pos, name.clone(), arg_list))
2020-06-21 00:45:09 +02:00
} else if let Ok(pattern) = Pattern::parse(parser) {
2020-06-22 15:58:42 +02:00
Ok(Expression::ValueRef(begin_pos, pattern))
2020-06-21 00:45:09 +02:00
} else {
2020-06-22 20:49:21 +02:00
Err(SyntaxError::ExpectedExpression(begin_pos, None))
2020-07-05 21:20:49 +02:00
}?;
if allow_arithmetic {
if let Ok(exp) = ArithmeticExpression::parse(first.clone(), parser) {
Ok(Expression::ArithmeticExpression(begin_pos, Box::new(exp)))
} else {
Ok(first)
}
} else {
Ok(first)
2020-06-21 00:45:09 +02:00
}
}
}
2020-07-05 21:20:49 +02:00
#[derive(Debug, Clone)]
pub enum ArithmeticExpression {
Add(Expression, Expression),
Subtract(Expression, Expression),
Mult(Expression, Expression),
2020-07-06 11:42:38 +02:00
Div(Expression, Expression),
Pow(Expression, Expression),
2020-07-05 21:20:49 +02:00
}
impl ArithmeticExpression {
fn parse(
first_exp: Expression,
parser: &mut Parser,
) -> Result<ArithmeticExpression, SyntaxError> {
let mut list = Vec::new();
let mut exp = first_exp;
while {
let sign = parser
.expect_static("+")
.get()
.or_else(|| parser.expect_static("-").get())
2020-07-06 11:42:38 +02:00
.or_else(|| parser.expect_static("**").get())
.or_else(|| parser.expect_static("/").get())
2020-07-05 21:20:49 +02:00
.or_else(|| parser.expect_static("*").get());
if sign.is_some() {
list.push((exp, sign.clone()));
exp = Expression::parse(parser, false)?;
}
sign.is_some()
} {}
list.push((exp, None));
if list.len() == 1 {
return Err(SyntaxError::Fatal);
}
2020-07-06 11:42:38 +02:00
// Replace all (expr, "*/**//"), (expr, any) => ((mult/pow/div_expr, any)
2020-07-05 21:20:49 +02:00
let clone = list.clone();
let iter = clone.iter().enumerate().rev();
for (idx, (exp, sign)) in iter {
if let Some(sign) = sign {
2020-07-06 11:42:38 +02:00
if sign == "**" {
if let Some((exp2, sign2)) = list.clone().get(idx + 1) {
list.remove(idx + 1);
list.remove(idx);
let expr = Expression::ArithmeticExpression(
parser.pos(),
Box::new(ArithmeticExpression::Pow(exp.clone(), exp2.clone())),
);
list.insert(idx, (expr, sign2.clone()));
};
}
if sign == "/" {
if let Some((exp2, sign2)) = list.clone().get(idx + 1) {
list.remove(idx + 1);
list.remove(idx);
let expr = Expression::ArithmeticExpression(
parser.pos(),
Box::new(ArithmeticExpression::Div(exp.clone(), exp2.clone())),
);
list.insert(idx, (expr, sign2.clone()));
};
}
2020-07-05 21:20:49 +02:00
if sign == "*" {
2020-07-06 10:44:19 +02:00
if let Some((exp2, sign2)) = list.clone().get(idx + 1) {
2020-07-05 21:20:49 +02:00
list.remove(idx + 1);
list.remove(idx);
let expr = Expression::ArithmeticExpression(
parser.pos(),
Box::new(ArithmeticExpression::Mult(exp.clone(), exp2.clone())),
);
list.insert(idx, (expr, sign2.clone()));
};
}
}
}
2020-07-06 11:42:38 +02:00
// Replace all (expr, "+/-"), (expr, any) => ((add/sub_expr, any))
2020-07-05 21:20:49 +02:00
let mut ret = Err(SyntaxError::Fatal);
while list.len() > 1 {
let (exp2, sign2) = list.remove(1);
let (exp1, sign1) = list.remove(0);
let expr = if let Some(sign1) = sign1 {
match &*sign1 {
"+" => Some(Box::new(ArithmeticExpression::Add(exp1, exp2))),
"-" => Some(Box::new(ArithmeticExpression::Subtract(exp1, exp2))),
_ => None,
}
} else {
return Err(SyntaxError::ExpectedExpression(parser.pos(), None));
};
if let Some(expr) = expr {
list.insert(
0,
(Expression::ArithmeticExpression(parser.pos(), expr), sign2),
);
}
}
if let Some(first) = list.get(0) {
if let Expression::ArithmeticExpression(_, expr) = &first.0 {
ret = Ok(*expr.clone());
}
}
ret
}
}
2020-06-22 20:49:21 +02:00
#[derive(Debug, Clone)]
2020-06-21 00:45:09 +02:00
pub enum Pattern {
IdentPattern(Position, Ident),
LiteralPattern(Position, LiteralPattern),
}
impl Pattern {
2020-06-22 20:49:21 +02:00
fn parse(parser: &mut Parser) -> Result<Pattern, SyntaxError> {
2020-06-21 00:45:09 +02:00
let pos = parser.pos();
if let Some(string) = parser.expect_string_lit().get() {
Ok(Pattern::LiteralPattern(
pos,
LiteralPattern::StringLit(string),
))
2020-06-24 23:39:18 +02:00
} else if let Some(int) = parser.expect_numeral_lit().get() {
Ok(Pattern::LiteralPattern(
pos,
LiteralPattern::Integer32Lit(int),
))
2020-06-21 00:45:09 +02:00
} else if let Some(ident) = parser.expect_ident().get() {
Ok(Pattern::IdentPattern(pos, ident))
} else {
2020-06-22 20:49:21 +02:00
Err(SyntaxError::ExpectedPattern(pos))
2020-06-21 00:45:09 +02:00
}
}
}
2020-06-22 20:49:21 +02:00
#[derive(Debug, Clone)]
2020-06-21 00:45:09 +02:00
pub enum LiteralPattern {
StringLit(String),
2020-06-24 23:39:18 +02:00
Integer32Lit(String),
2020-06-21 00:45:09 +02:00
}