//! Parser and associated types
use crate::errors::{ExprErrorS, SyntaxError};
use crate::ast;
use crate::lexer::Token;
use crate::span::Spanned;
grammar<'err>(source: &str, errors: &'err mut Vec<ExprErrorS>);
pub Expr: ast::Expr = {
ExprIdentifier,
ExprCall,
ExprString,
ExprNumber,
ExprBool,
<e:!> => {
errors.push(SyntaxError::from_parser_error(e.error, source));
ast::Expr::Error
}
};
// Boolean Expressions
ExprBool: ast::Expr = {
"true" => ast::Expr::Bool(ast::ExprBool(true).into()),
"false" => ast::Expr::Bool(ast::ExprBool(false).into()),
};
// Number Expressions
ExprNumber: ast::Expr = {
number => ast::Expr::Number(ast::ExprNumber(<>).into())
};
// String Expressions
ExprString: ast::Expr = {
string => ast::Expr::String(ast::ExprString(<>).into())
};
// Call Expressions
CallCallee = ExprS;
CallArgs = Args<ExprS>;
ExprCall: ast::Expr = {
"(" <callee:CallCallee> <args:CallArgs> ")" => ast::Expr::Call(ast::ExprCall {
callee: callee.into(),
args
}.into())
}
// Identifier Expressions
ExprIdentifier: ast::Expr = {
<name:identifier> =>
ast::Expr::Identifier(ast::ExprIdentifier::new(&name).into()),
<ty:ty> =>
ast::Expr::Identifier(ast::ExprIdentifier::new(&ty).into()),
<ty:ty> "<" <subty:ty> ">" =>
ast::Expr::Identifier(ast::ExprIdentifier::new(&format!("{}<{}>", ty, subty)).into()),
"Fn" "(" <args:Seperated<ty, ",">> ")" "->" <return_ty:ty> => {
let id = format!("Fn({}) -> {}", args.join(", "), return_ty);
ast::Expr::Identifier(ast::ExprIdentifier::new(&id).into())
},
"Fn" "(" <args:Seperated<ty, ",">> "," "..." <varg:ty> ")" "->" <return_ty:ty> => {
let id = format!("Fn({}, ...{}) -> {}", args.join(", "), varg, return_ty);
ast::Expr::Identifier(ast::ExprIdentifier::new(&id).into())
},
"Fn" "(" "..." <varg:ty> ")" "->" <return_ty:ty> => {
let id = format!("Fn(...{}) -> {}", varg, return_ty);
ast::Expr::Identifier(ast::ExprIdentifier::new(&id).into())
},
}
// Utility Types
ExprS = Spanned<Expr>;
Spanned<T>: Spanned<T> = <l:@L> <t:T> <r:@R> =>
(t, l..r);
#[inline]
Args<E>: Vec<E> = {
<first:E> <mut args:(<E>)*> => {
args.insert(0, first);
args
},
() => Vec::new(),
}
#[inline]
Seperated<E, T>: Vec<E> = {
<first:E> <mut args:(T <E>)*> => {
args.insert(0, first);
args
},
() => Vec::new(),
}
extern {
type Location = usize;
type Error = ExprErrorS;
enum Token {
"(" => Token::LParan,
")" => Token::RParan,
"," => Token::Comma,
"<" => Token::LAngle,
">" => Token::RAngle,
"->" => Token::Arrow,
"Fn" => Token::Fn,
"..." => Token::ThreeDot,
"true" => Token::True,
"false" => Token::False,
string => Token::String(<String>),
number => Token::Number(<f64>),
identifier => Token::Identifier(<String>),
ty => Token::Type(<String>)
}
}