mirror of
https://github.com/gorules/zen.git
synced 2026-10-04 00:02:18 +00:00
242 lines
8.4 KiB
Rust
242 lines
8.4 KiB
Rust
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(),
|
|
}),
|
|
}
|
|
}
|
|
}
|