feat: crates restructure (#22)

This commit is contained in:
Ivan Miletic
2023-04-24 20:28:27 +02:00
committed by GitHub
parent 307ba977dd
commit 062ee5df90
41 changed files with 85 additions and 192 deletions
+42
View File
@@ -0,0 +1,42 @@
#[derive(Debug, PartialEq)]
pub(crate) enum Associativity {
Left,
Right,
}
#[derive(Debug, PartialEq)]
pub(crate) enum Arity {
Single,
Closure,
Dual,
}
#[derive(Debug, PartialEq)]
pub(crate) struct Operator {
pub precedence: u8,
pub associativity: Associativity,
}
#[derive(Debug, PartialEq)]
pub(crate) struct BuiltIn {
pub arity: Arity,
}
#[macro_export]
macro_rules! hashmap {
(@single $($x:tt)*) => (());
(@count $($rest:expr),*) => (<[()]>::len(&[$(hashmap!(@single $rest)),*]));
($($key:expr => $value:expr,)+) => { hashmap!($($key => $value),+) };
($($key:expr => $value:expr),*) => {
{
let _cap = hashmap!(@count $($key),*);
let mut _map = ::std::collections::HashMap::default();
_map.reserve(_cap);
$(
let _ = _map.insert($key, $value);
)*
_map
}
};
}
+24
View File
@@ -0,0 +1,24 @@
use thiserror::Error;
#[derive(Debug, PartialEq, Eq, Error)]
pub enum ParserError {
#[error("Token out of bounds")]
TokenOutOfBounds,
#[error("Memory failure")]
MemoryFailure,
#[error("Unexpected token: received {received} instead of {expected}")]
UnexpectedToken { expected: String, received: String },
#[error("Failed to parse: {message}")]
FailedToParse { message: String },
#[error("Unknown built in: {token}")]
UnknownBuiltIn { token: String },
#[error("Unsupported built in: {token}")]
UnsupportedBuiltIn { token: String },
}
pub type ParserResult<T> = Result<T, ParserError>;
+164
View File
@@ -0,0 +1,164 @@
use std::cell::Cell;
use std::fmt::Debug;
use bumpalo::Bump;
use rust_decimal::Decimal;
use crate::ast::Node;
use crate::lexer::token::{Token, TokenKind};
use crate::parser::error::{ParserError, ParserResult};
type TokenValues<'a> = Option<&'a [&'a str]>;
#[derive(Debug)]
pub(crate) struct ParserIterator<'a, 'b> {
tokens: &'a Vec<Token<'a>>,
current: Cell<&'a Token<'a>>,
position: Cell<usize>,
bump: &'b Bump,
is_done: Cell<bool>,
}
impl<'a, 'b> ParserIterator<'a, 'b> {
pub fn try_new(tokens: &'a Vec<Token<'a>>, bump: &'b Bump) -> Result<Self, ParserError> {
let current = tokens.get(0).ok_or(ParserError::TokenOutOfBounds)?;
Ok(Self {
tokens,
bump,
current: Cell::new(current),
position: Cell::new(0),
is_done: Cell::new(false),
})
}
pub fn current(&self) -> &'a Token<'a> {
self.current.get()
}
pub fn is_done(&self) -> bool {
self.is_done.get()
}
pub fn next(&self) -> ParserResult<()> {
self.position.set(self.position.get() + 1);
if let Some(token) = self.tokens.get(self.position.get()) {
self.current.set(token);
Ok(())
} else {
if self.is_done.get() {
return Err(ParserError::TokenOutOfBounds);
}
self.is_done.set(true);
Ok(())
}
}
pub fn str_value(&self, str: &str) -> &'b str {
self.bump.alloc_str(str)
}
pub fn expect(&self, kind: TokenKind, values: TokenValues<'a>) -> Result<(), ParserError> {
self.token_cmp(kind, values)?;
self.next()?;
Ok(())
}
pub fn lookup(&self, dx: usize, kind: TokenKind, values: TokenValues<'a>) -> bool {
self.token_cmp_at_bool(self.position.get() + dx, kind, values)
}
pub fn lookup_back(&self, dx: usize, kind: TokenKind, values: TokenValues<'a>) -> bool {
if self.position.get() < dx {
return false;
}
self.token_cmp_at_bool(self.position.get() - dx, kind, values)
}
pub fn number(&self, token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
self.next()?;
let decimal =
Decimal::from_str_exact(token.value).map_err(|_| ParserError::FailedToParse {
message: format!("unknown float value: {:?}", token.value),
})?;
self.node(Node::Number(decimal))
}
pub fn string(&self, token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
self.next()?;
self.node(Node::String(self.bump.alloc_str(token.value)))
}
pub fn bool(&self, token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
match token.value {
"true" => self.node(Node::Bool(true)),
"false" => self.node(Node::Bool(false)),
_ => Err(ParserError::FailedToParse {
message: format!("unknown bool value: {:?}", token.value),
}),
}
}
pub fn null(&self, _token: &'a Token) -> Result<&'b Node<'b>, ParserError> {
self.node(Node::Null)
}
pub fn node(&self, node: Node<'b>) -> Result<&'b Node<'b>, ParserError> {
Ok(self.bump.alloc(node))
}
fn token_cmp_at_bool(&self, index: usize, kind: TokenKind, values: TokenValues<'a>) -> bool {
return if let Some(token) = self.tokens.get(index) {
if token.kind != kind {
return false;
}
if let Some(vals) = values {
return vals.iter().any(|&c| c == token.value);
}
true
} else {
false
};
}
fn token_cmp_at(
&self,
index: usize,
kind: TokenKind,
values: TokenValues<'a>,
) -> Result<(), ParserError> {
let token: &'a Token = self
.tokens
.get(index)
.ok_or(ParserError::TokenOutOfBounds)?;
if token.kind != kind {
return Err(ParserError::UnexpectedToken {
expected: format!("{kind:?} {values:?}"),
received: format!("{token:?}"),
});
}
if let Some(vals) = values {
if !vals.iter().any(|&c| c == token.value) {
return Err(ParserError::UnexpectedToken {
expected: format!("{kind:?} {values:?}"),
received: format!("{token:?}"),
});
}
}
Ok(())
}
fn token_cmp(&self, kind: TokenKind, values: TokenValues<'a>) -> Result<(), ParserError> {
self.token_cmp_at(self.position.get(), kind, values)
}
}
+9
View File
@@ -0,0 +1,9 @@
pub use standard::StandardParser;
pub use unary::UnaryParser;
pub mod error;
mod definitions;
mod iter;
mod standard;
mod unary;
@@ -0,0 +1,85 @@
use std::collections::HashMap;
use std::hash::BuildHasherDefault;
use ahash::AHasher;
use once_cell::sync::Lazy;
use crate::hashmap;
use crate::parser::definitions::Associativity::{Left, Right};
use crate::parser::definitions::{Arity, BuiltIn, Operator};
type ADefHasher = BuildHasherDefault<AHasher>;
pub(crate) static BUILT_INS: Lazy<HashMap<&'static str, BuiltIn, ADefHasher>> = Lazy::new(|| {
hashmap! {
"len" => BuiltIn { arity: Arity::Single },
"date" => BuiltIn { arity: Arity::Single },
"duration" => BuiltIn { arity: Arity::Single },
"upper" => BuiltIn { arity: Arity::Single },
"lower" => BuiltIn { arity: Arity::Single },
"abs" => BuiltIn { arity: Arity::Single },
"sum" => BuiltIn { arity: Arity::Single },
"avg" => BuiltIn { arity: Arity::Single },
"min" => BuiltIn { arity: Arity::Single },
"max" => BuiltIn { arity: Arity::Single },
"rand" => BuiltIn { arity: Arity::Single },
"floor" => BuiltIn { arity: Arity::Single },
"ceil" => BuiltIn { arity: Arity::Single },
"round" => BuiltIn { arity: Arity::Single },
"dayOfWeek" => BuiltIn { arity: Arity::Single },
"dayOfMonth" => BuiltIn { arity: Arity::Single },
"dayOfYear" => BuiltIn { arity: Arity::Single },
"weekOfMonth" => BuiltIn { arity: Arity::Single },
"weekOfYear" => BuiltIn { arity: Arity::Single },
"monthOfYear" => BuiltIn { arity: Arity::Single },
"seasonOfYear" => BuiltIn { arity: Arity::Single },
"monthString" => BuiltIn { arity: Arity::Single },
"weekdayString" => BuiltIn { arity: Arity::Single },
"startsWith" => BuiltIn { arity: Arity::Dual },
"endsWith" => BuiltIn { arity: Arity::Dual },
"contains" => BuiltIn { arity: Arity::Dual },
"all" => BuiltIn { arity: Arity::Closure },
"some" => BuiltIn { arity: Arity::Closure },
"none" => BuiltIn { arity: Arity::Closure },
"filter" => BuiltIn { arity: Arity::Closure },
"map" => BuiltIn { arity: Arity::Closure },
"count" => BuiltIn { arity: Arity::Closure },
"one" => BuiltIn { arity: Arity::Closure }
}
});
pub(crate) static BINARY_OPERATORS: Lazy<HashMap<&'static str, Operator, ADefHasher>> =
Lazy::new(|| {
hashmap! {
"or" => Operator { precedence: 10, associativity: Left },
"and" => Operator { precedence: 15, associativity: Left },
"==" => Operator { precedence: 20, associativity: Left },
"!=" => Operator { precedence: 20, associativity: Left },
"<" => Operator { precedence: 20, associativity: Left },
">" => Operator { precedence: 20, associativity: Left },
"<=" => Operator { precedence: 20, associativity: Left },
">=" => Operator { precedence: 20, associativity: Left },
"not in" => Operator { precedence: 20, associativity: Left },
"in" => Operator { precedence: 20, associativity: Left },
"+" => Operator { precedence: 30, associativity: Left },
"-" => Operator { precedence: 30, associativity: Left },
"*" => Operator { precedence: 60, associativity: Left },
"/" => Operator { precedence: 60, associativity: Left },
"%" => Operator { precedence: 60, associativity: Left },
"^" => Operator { precedence: 70, associativity: Right },
}
});
pub(crate) static UNARY_OPERATORS: Lazy<HashMap<&'static str, Operator, ADefHasher>> =
Lazy::new(|| {
hashmap! {
"not" => Operator { precedence: 50, associativity: Left },
"!" => Operator { precedence: 50, associativity: Left },
"+" => Operator { precedence: 200, associativity: Left },
"-" => Operator { precedence: 200, associativity: Left },
}
});
+365
View File
@@ -0,0 +1,365 @@
use std::cell::Cell;
use bumpalo::Bump;
use crate::ast::Node;
use crate::lexer::token::{Token, TokenKind};
use crate::parser::definitions::{Arity, Associativity};
use crate::parser::error::ParserError::{MemoryFailure, UnexpectedToken, UnknownBuiltIn};
use crate::parser::error::ParserResult;
use crate::parser::iter::ParserIterator;
use crate::parser::standard::constants::{BINARY_OPERATORS, BUILT_INS, UNARY_OPERATORS};
mod constants;
pub struct StandardParser<'a, 'b>
where
'b: 'a,
{
iterator: ParserIterator<'a, 'b>,
bump: &'b Bump,
depth: Cell<u8>,
}
impl<'a, 'b> StandardParser<'a, 'b>
where
'b: 'a,
{
pub fn try_new(tokens: &'a Vec<Token>, bump: &'b Bump) -> ParserResult<Self> {
Ok(Self {
iterator: ParserIterator::try_new(tokens, bump)?,
bump,
depth: Cell::new(0),
})
}
pub fn parse(&self) -> ParserResult<&'b Node<'b>> {
self.parse_expression(0)
}
fn parse_expression(&self, precedence: u8) -> ParserResult<&'b Node<'b>> {
let mut node_left = self.parse_primary()?;
let mut token = self.iterator.current();
while !self.iterator.is_done() {
if token.kind == TokenKind::Operator {
if let Some(op) = BINARY_OPERATORS.get(token.value) {
if op.precedence >= precedence {
self.iterator.next()?;
let node_right = match op.associativity {
Associativity::Left => self.parse_expression(op.precedence + 1)?,
_ => self.parse_expression(op.precedence)?,
};
node_left = self.iterator.node(Node::Binary {
operator: self.iterator.str_value(token.value),
left: node_left,
right: node_right,
})?;
token = self.iterator.current();
continue;
}
}
}
break;
}
if precedence == 0 {
node_left = self.parse_conditional(node_left)?;
}
Ok(node_left)
}
fn parse_primary(&self) -> ParserResult<&'b Node<'b>> {
let token = self.iterator.current();
if token.kind == TokenKind::Operator {
if let Some(op) = UNARY_OPERATORS.get(token.value) {
self.iterator.next()?;
let expr = self.parse_expression(op.precedence)?;
let node = self.iterator.node(Node::Unary {
operator: self.iterator.str_value(token.value),
node: expr,
})?;
return self.parse_postfix(node);
}
}
if let Some(interval_node) = self.parse_interval()? {
return self.parse_postfix(interval_node);
}
if token.kind == TokenKind::Bracket && token.value == "(" {
self.iterator.next()?;
let expr = self.parse_expression(0)?;
self.iterator.expect(TokenKind::Bracket, Some(&[")"]))?;
return self.parse_postfix(expr);
}
if self.depth.get() > 0 {
if token.kind == TokenKind::Operator && (token.value == "#" || token.value == ".") {
if token.value == "#" {
self.iterator.next()?;
}
let node = self.iterator.node(Node::Pointer)?;
return self.parse_postfix(node);
}
} else if token.kind == TokenKind::Operator && (token.value == "#" || token.value == ".") {
return Err(UnexpectedToken {
expected: "anything but Operator(#, .)".to_string(),
received: format!("{token:?}"),
});
}
self.parse_primary_expression()
}
fn parse_conditional(&self, node: &'b Node<'b>) -> ParserResult<&'b Node<'b>> {
let mut nd = self.iterator.node(node.clone())?;
let mut expr1: &'b Node;
let mut expr2: &'b Node;
while self.iterator.current().kind == TokenKind::Operator
&& self.iterator.current().value == "?"
{
self.iterator.next()?;
let token = self.iterator.current();
if token.kind != TokenKind::Operator && token.value != ":" {
expr1 = self.parse_expression(0)?;
self.iterator.expect(TokenKind::Operator, Some(&[":"]))?;
expr2 = self.parse_expression(0)?;
} else {
self.iterator.next()?;
expr1 = node;
expr2 = self.parse_expression(0)?;
}
nd = self.iterator.node(Node::Conditional {
condition: nd,
on_true: expr1,
on_false: expr2,
})?;
}
Ok(nd)
}
fn parse_primary_expression(&self) -> ParserResult<&'b Node<'b>> {
let node: &'b Node;
let token = self.iterator.current();
match token.kind {
TokenKind::Identifier => {
self.iterator.next()?;
match token.value {
"true" | "false" => return self.iterator.bool(token),
"null" => return self.iterator.null(token),
_ => node = self.parse_identifier_expression(token)?,
}
}
TokenKind::Number => return self.iterator.number(token),
TokenKind::String => return self.iterator.string(token),
_ => {
if token.kind == TokenKind::Bracket && token.value == "[" {
node = self.parse_array(token)?;
} else {
return Err(UnexpectedToken {
expected: "identifier, string, number or opening bracket".to_string(),
received: format!("{token:?}"),
});
}
}
}
self.parse_postfix(node)
}
fn parse_interval(&self) -> ParserResult<Option<&'b Node<'b>>> {
if self.iterator.current().kind != TokenKind::Bracket {
return Ok(None);
}
if !self.iterator.lookup(2, TokenKind::Operator, Some(&[".."])) {
return Ok(None);
}
let left_bracket = self.iterator.current().value;
self.iterator.expect(TokenKind::Bracket, None)?;
let left = self.parse_primary_expression()?;
self.iterator.expect(TokenKind::Operator, Some(&[".."]))?;
let right = self.parse_primary_expression()?;
let right_bracket = self.iterator.current().value;
self.iterator.expect(TokenKind::Bracket, None)?;
let interval_node = self.iterator.node(Node::Interval {
left_bracket: self.iterator.str_value(left_bracket),
left,
right,
right_bracket: self.iterator.str_value(right_bracket),
})?;
Ok(Some(interval_node))
}
fn parse_identifier_expression(&self, token: &Token) -> ParserResult<&'b Node<'b>> {
if self.iterator.current().kind != TokenKind::Bracket
|| self.iterator.current().value != "("
{
return self
.iterator
.node(Node::Identifier(self.iterator.str_value(token.value)));
}
let builtin = BUILT_INS.get(token.value).ok_or_else(|| UnknownBuiltIn {
token: token.value.to_string(),
})?;
self.iterator.expect(TokenKind::Bracket, Some(&["("]))?;
return match builtin.arity {
Arity::Single => {
let arg = self.parse_expression(0)?;
self.iterator.expect(TokenKind::Bracket, Some(&[")"]))?;
self.iterator.node(Node::BuiltIn {
name: self.iterator.str_value(token.value),
arguments: self.bump.alloc_slice_copy(&[arg]),
})
}
Arity::Dual => {
let arg1 = self.parse_expression(0)?;
self.iterator.expect(TokenKind::Operator, Some(&[","]))?;
let arg2 = self.parse_primary_expression()?;
self.iterator.expect(TokenKind::Bracket, Some(&[")"]))?;
self.iterator.node(Node::BuiltIn {
name: self.iterator.str_value(token.value),
arguments: self.bump.alloc_slice_copy(&[arg1, arg2]),
})
}
Arity::Closure => {
let arg1 = self.parse_expression(0)?;
self.iterator.expect(TokenKind::Operator, Some(&[","]))?;
let arg2 = self.parse_closure()?;
self.iterator.expect(TokenKind::Bracket, Some(&[")"]))?;
self.iterator.node(Node::BuiltIn {
name: self.iterator.str_value(token.value),
arguments: self.bump.alloc_slice_copy(&[arg1, arg2]),
})
}
};
}
fn parse_array(&self, _token: &Token) -> ParserResult<&'b Node<'b>> {
let mut nodes = Vec::new();
self.iterator.expect(TokenKind::Bracket, Some(&["["]))?;
while self.iterator.current().kind != TokenKind::Bracket
&& self.iterator.current().value != "]"
{
if !nodes.is_empty() {
self.iterator.expect(TokenKind::Operator, Some(&[","]))?;
if self.iterator.current().value == "]" {
break;
}
}
nodes.push(self.parse_primary()?);
}
self.iterator.expect(TokenKind::Bracket, Some(&["]"]))?;
let node = Node::Array(self.bump.alloc_slice_copy(nodes.as_slice()));
self.iterator.node(node)
}
fn parse_closure(&self) -> ParserResult<&'b Node<'b>> {
self.depth.set(self.depth.get() + 1);
let node = self.parse_expression(0)?;
self.depth.set(self.depth.get() - 1);
return self.iterator.node(Node::Closure(node));
}
fn parse_postfix(&self, node: &'b Node<'b>) -> ParserResult<&'b Node<'b>> {
let mut postfix_token = self.iterator.current();
let mut nd = self.iterator.node(node.clone())?;
while postfix_token.kind == TokenKind::Bracket || postfix_token.kind == TokenKind::Operator
{
if postfix_token.value == "." {
self.iterator.next()?;
let property_token = self.iterator.current();
self.iterator.next()?;
if property_token.kind != TokenKind::Identifier
&& (property_token.kind != TokenKind::Operator
|| !is_valid_identifier(property_token.value))
{
return Err(UnexpectedToken {
expected: "member identifier token".to_string(),
received: format!("{postfix_token:?}"),
});
}
let property = self
.iterator
.node(Node::String(self.iterator.str_value(property_token.value)))?;
nd = self.iterator.node(Node::Member { node: nd, property })?;
} else if postfix_token.value == "[" {
self.iterator.next()?;
let mut from: Option<&'b Node<'b>> = None;
let mut to: Option<&'b Node<'b>> = None;
let mut c = self.iterator.current();
if c.kind == TokenKind::Operator && c.value == ":" {
self.iterator.next()?;
c = self.iterator.current();
if c.kind != TokenKind::Bracket && c.value != "]" {
to = Some(self.parse_expression(0)?);
}
nd = self.iterator.node(Node::Slice { node: nd, to, from })?;
self.iterator.expect(TokenKind::Bracket, Some(&["]"]))?;
} else {
from = Some(self.parse_expression(0)?);
c = self.iterator.current();
if c.kind == TokenKind::Operator && c.value == ":" {
self.iterator.next()?;
c = self.iterator.current();
if c.kind != TokenKind::Bracket && c.value != "]" {
to = Some(self.parse_expression(0)?);
}
nd = self.iterator.node(Node::Slice { node: nd, from, to })?;
self.iterator.expect(TokenKind::Bracket, Some(&["]"]))?;
} else {
// Slice operator [:] was not found,
// it should be just an index node.
nd = self.iterator.node(Node::Member {
node: nd,
property: from.ok_or(MemoryFailure)?,
})?;
self.iterator.expect(TokenKind::Bracket, Some(&["]"]))?;
}
}
} else {
break;
}
postfix_token = self.iterator.current();
}
Ok(nd)
}
}
fn is_valid_identifier(str: &str) -> bool {
matches!(str, "and" | "or" | "in" | "not")
}
@@ -0,0 +1,52 @@
use phf::{phf_map, Map};
use crate::parser::definitions::Associativity::{Left, Right};
use crate::parser::definitions::{Arity, BuiltIn, Operator};
pub(crate) const BUILT_INS: Map<&'static str, BuiltIn> = phf_map! {
"date" => BuiltIn { arity: Arity::Single },
"duration" => BuiltIn { arity: Arity::Single },
"upper" => BuiltIn { arity: Arity::Single },
"lower" => BuiltIn { arity: Arity::Single },
"abs" => BuiltIn { arity: Arity::Single },
"sum" => BuiltIn { arity: Arity::Single },
"avg" => BuiltIn { arity: Arity::Single },
"min" => BuiltIn { arity: Arity::Single },
"max" => BuiltIn { arity: Arity::Single },
"rand" => BuiltIn { arity: Arity::Single },
"floor" => BuiltIn { arity: Arity::Single },
"ceil" => BuiltIn { arity: Arity::Single },
"round" => BuiltIn { arity: Arity::Single },
"dayOfWeek" => BuiltIn { arity: Arity::Single },
"dayOfMonth" => BuiltIn { arity: Arity::Single },
"dayOfYear" => BuiltIn { arity: Arity::Single },
"weekOfMonth" => BuiltIn { arity: Arity::Single },
"weekOfYear" => BuiltIn { arity: Arity::Single },
"monthOfYear" => BuiltIn { arity: Arity::Single },
"seasonOfYear" => BuiltIn { arity: Arity::Single },
"monthString" => BuiltIn { arity: Arity::Single },
"weekdayString" => BuiltIn { arity: Arity::Single },
};
pub(crate) const OPERATORS: Map<&'static str, Operator> = phf_map! {
"or" => Operator { precedence: 10, associativity: Left },
"and" => Operator { precedence: 15, associativity: Left },
"==" => Operator { precedence: 20, associativity: Left },
"!=" => Operator { precedence: 20, associativity: Left },
"<" => Operator { precedence: 20, associativity: Left },
">" => Operator { precedence: 20, associativity: Left },
"<=" => Operator { precedence: 20, associativity: Left },
">=" => Operator { precedence: 20, associativity: Left },
"not in" => Operator { precedence: 20, associativity: Left },
"in" => Operator { precedence: 20, associativity: Left },
"+" => Operator { precedence: 30, associativity: Left },
"-" => Operator { precedence: 30, associativity: Left },
"*" => Operator { precedence: 60, associativity: Left },
"/" => Operator { precedence: 60, associativity: Left },
"%" => Operator { precedence: 60, associativity: Left },
"^" => Operator { precedence: 70, associativity: Right },
};
+241
View File
@@ -0,0 +1,241 @@
use bumpalo::Bump;
use crate::ast::Node;
use crate::lexer::token::{Token, TokenKind};
use crate::parser::definitions::{Arity, Associativity};
use crate::parser::error::{ParserError, ParserResult};
use crate::parser::iter::ParserIterator;
use crate::parser::unary::constants::{BUILT_INS, OPERATORS};
mod constants;
pub struct UnaryParser<'a, 'b>
where
'b: 'a,
{
iterator: ParserIterator<'a, 'b>,
bump: &'b Bump,
}
const MAIN_NODE: Node<'static> = Node::Identifier("$");
impl<'a, 'b> UnaryParser<'a, 'b>
where
'b: 'a,
{
pub fn try_new(tokens: &'a Vec<Token>, bump: &'b Bump) -> ParserResult<Self> {
Ok(Self {
iterator: ParserIterator::try_new(tokens, bump)?,
bump,
})
}
pub fn parse(&self) -> ParserResult<&'b Node<'b>> {
self.parse_expression(0, true)
}
fn parse_expression(&self, precedence: u8, root: bool) -> ParserResult<&'b Node<'b>> {
let mut node_left: &'b Node<'b> = self.iterator.node(MAIN_NODE)?;
let mut token = self.iterator.current();
while !self.iterator.is_done() {
match token.kind {
TokenKind::Operator => {
if token.value == "," {
self.iterator.next()?;
let node_right: &'b Node<'b> = self.parse_expression(0, true)?;
token = self.iterator.current();
node_left = self.iterator.node(Node::Binary {
left: node_left,
operator: "or",
right: node_right,
})?;
continue;
} else if let Some(op) = OPERATORS.get(token.value) {
if op.precedence >= precedence {
self.iterator.next()?;
let node_right = match op.associativity {
Associativity::Left => {
self.parse_expression(op.precedence + 1, false)?
}
Associativity::Right => {
self.parse_expression(op.precedence, false)?
}
};
node_left = self.iterator.node(Node::Binary {
left: node_left,
operator: self.iterator.str_value(token.value),
right: node_right,
})?;
token = self.iterator.current();
continue;
}
}
}
TokenKind::Identifier | TokenKind::String | TokenKind::Number => {
let node_right = self.parse_primary()?;
if !root {
return Ok(node_right);
}
token = self.iterator.current();
node_left = self.iterator.node(Node::Binary {
left: node_left,
operator: "==",
right: node_right,
})?;
continue;
}
TokenKind::Bracket => {
let node_right: &Node;
if let Some(interval) = self.parse_interval(node_left)? {
node_left = interval;
} else if token.value == "[" {
let should_wrap = !self.iterator.lookup_back(
1,
TokenKind::Operator,
Some(&["not in", "in"]),
);
node_right = self.parse_array(token)?;
if should_wrap {
node_left = self.iterator.node(Node::Binary {
left: node_left,
right: node_right,
operator: "in",
})?;
} else {
node_left = node_right;
}
}
continue;
}
}
}
Ok(node_left)
}
fn parse_interval(&self, node: &'b Node<'b>) -> ParserResult<Option<&'b Node<'b>>> {
let current_token = self.iterator.current();
if current_token.kind != TokenKind::Bracket {
return Ok(None);
}
if !self.iterator.lookup(2, TokenKind::Operator, Some(&[".."])) {
return Ok(None);
}
let should_wrap =
!self
.iterator
.lookup_back(1, TokenKind::Operator, Some(&["not in", "in"]));
let left_bracket = self.iterator.current().value;
self.iterator.expect(TokenKind::Bracket, None)?;
let left = self.parse_primary()?;
self.iterator.expect(TokenKind::Operator, Some(&[".."]))?;
let right = self.parse_primary()?;
let right_bracket = self.iterator.current().value;
self.iterator.expect(TokenKind::Bracket, None)?;
let interval_node = self.iterator.node(Node::Interval {
left,
left_bracket: self.iterator.str_value(left_bracket),
right,
right_bracket: self.iterator.str_value(right_bracket),
})?;
if should_wrap {
return Ok(Some(self.iterator.node(Node::Binary {
left: node,
right: interval_node,
operator: "in",
})?));
}
Ok(Some(interval_node))
}
fn parse_array(&self, _token: &Token) -> ParserResult<&'b Node<'b>> {
let mut nodes = Vec::new();
self.iterator.expect(TokenKind::Bracket, Some(&["["]))?;
while self.iterator.current().kind != TokenKind::Bracket
&& self.iterator.current().value != "]"
{
if !nodes.is_empty() {
self.iterator.expect(TokenKind::Operator, Some(&[","]))?;
if self.iterator.current().value == "]" {
break;
}
}
nodes.push(self.parse_primary()?);
}
self.iterator.expect(TokenKind::Bracket, Some(&["]"]))?;
let node = Node::Array(self.bump.alloc_slice_copy(nodes.as_slice()));
self.iterator.node(node)
}
fn parse_primary(&self) -> ParserResult<&'b Node<'b>> {
let token = self.iterator.current();
match token.kind {
TokenKind::Identifier => {
self.iterator.next()?;
match token.value {
"true" | "false" => self.iterator.bool(token),
"null" => self.iterator.null(token),
_ => self.parse_prebuilt(token),
}
}
TokenKind::Number => self.iterator.number(token),
TokenKind::String => self.iterator.string(token),
_ => Err(ParserError::UnexpectedToken {
expected: "one of [identifier, number, string]".to_string(),
received: format!("{:?}", token.kind),
}),
}
}
fn parse_prebuilt(&self, token: &Token<'a>) -> ParserResult<&'b Node<'b>> {
let current_token = self.iterator.current();
let valid_token = current_token.kind == TokenKind::Bracket && current_token.value == "(";
if !valid_token {
return Err(ParserError::UnknownBuiltIn {
token: token.value.to_string(),
});
}
let built_in = BUILT_INS
.get(token.value)
.ok_or_else(|| ParserError::UnknownBuiltIn {
token: token.value.to_string(),
})?;
self.iterator.expect(TokenKind::Bracket, Some(&["("]))?;
match built_in.arity {
Arity::Single => {
let arg = self.parse_primary()?;
let node = self.iterator.node(Node::BuiltIn {
name: self.iterator.str_value(token.value),
arguments: self.bump.alloc_slice_copy(&[arg]),
})?;
self.iterator.expect(TokenKind::Bracket, Some(&[")"]))?;
Ok(node)
}
_ => Err(ParserError::UnsupportedBuiltIn {
token: token.value.to_string(),
}),
}
}
}