diff --git a/crates/lang/src/lib.rs b/crates/lang/src/lib.rs index 1b08789..e552496 100644 --- a/crates/lang/src/lib.rs +++ b/crates/lang/src/lib.rs @@ -1,2 +1,2 @@ #![feature(type_alias_impl_trait, lint_reasons)] -pub mod parser; +pub mod lst_parser; diff --git a/crates/lang/src/parser.rs b/crates/lang/src/lst_parser.rs similarity index 96% rename from crates/lang/src/parser.rs rename to crates/lang/src/lst_parser.rs index dfd80c5..9b93010 100644 --- a/crates/lang/src/parser.rs +++ b/crates/lang/src/lst_parser.rs @@ -134,8 +134,8 @@ pub(crate) struct CompletedMarker { } impl CompletedMarker { - pub(crate) fn precede(self, p: &mut Parser<'_, '_>) -> Marker { - let new_pos = p.start("new_pos"); + pub(crate) fn precede(self, p: &mut Parser<'_, '_>, name: &str) -> Marker { + let new_pos = p.start(name); match &mut p.events[self.pos] { Event::Start { forward_parent, .. } => { diff --git a/crates/lang/src/parser/error.rs b/crates/lang/src/lst_parser/error.rs similarity index 51% rename from crates/lang/src/parser/error.rs rename to crates/lang/src/lst_parser/error.rs index 698ecaf..d13306c 100644 --- a/crates/lang/src/parser/error.rs +++ b/crates/lang/src/lst_parser/error.rs @@ -1,6 +1,7 @@ -use crate::parser::syntax_kind::SyntaxKind; +use crate::lst_parser::syntax_kind::SyntaxKind; #[derive(Debug)] pub enum SyntaxError { Expected(Vec), + PipelineNeedsSink, } diff --git a/crates/lang/src/parser/events.rs b/crates/lang/src/lst_parser/events.rs similarity index 88% rename from crates/lang/src/parser/events.rs rename to crates/lang/src/lst_parser/events.rs index 6fc5b2c..00d7524 100644 --- a/crates/lang/src/parser/events.rs +++ b/crates/lang/src/lst_parser/events.rs @@ -1,4 +1,4 @@ -use crate::parser::syntax_kind::SyntaxKind; +use crate::lst_parser::syntax_kind::SyntaxKind; #[derive(Debug)] pub enum Event { diff --git a/crates/lang/src/parser/grammar.rs b/crates/lang/src/lst_parser/grammar.rs similarity index 87% rename from crates/lang/src/parser/grammar.rs rename to crates/lang/src/lst_parser/grammar.rs index afcee25..9d081bb 100644 --- a/crates/lang/src/parser/grammar.rs +++ b/crates/lang/src/lst_parser/grammar.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; -use crate::parser::syntax_kind::SyntaxKind::*; +use crate::lst_parser::syntax_kind::SyntaxKind::*; use super::{ input::Input, @@ -14,7 +14,7 @@ mod expression; pub fn source_file(p: &mut Parser) { let root = p.start("root"); - expression::expression(p); + expression::expression(p, false); p.eat_succeeding_ws(); root.complete(p, ROOT); diff --git a/crates/lang/src/lst_parser/grammar/expression.rs b/crates/lang/src/lst_parser/grammar/expression.rs new file mode 100644 index 0000000..6ad7235 --- /dev/null +++ b/crates/lang/src/lst_parser/grammar/expression.rs @@ -0,0 +1,81 @@ +use crate::lst_parser::{error::SyntaxError, syntax_kind::SyntaxKind::*, CompletedMarker, Parser}; + +use self::{collection::collection, instruction::instr, lit::literal, pipeline::PIPES}; + +mod collection; +mod instruction; +mod lit; +mod pipeline { + use enumset::enum_set; + + use crate::lst_parser::{ + error::SyntaxError, + syntax_kind::{SyntaxKind::*, TokenSet}, + CompletedMarker, Parser, + }; + + use super::expression; + + pub fn pipeline(p: &mut Parser, start_expr: CompletedMarker) -> Option { + if !pipe(p) { + return Some(start_expr); + } + let pipeline_marker = start_expr.precede(p, "pipeline_start"); + + loop { + if expression(p, true).is_none() { + return Some(pipeline_marker.complete_err(p, SyntaxError::PipelineNeedsSink)); + } + if !pipe(p) { + return Some(pipeline_marker.complete(p, PIPELINE)); + } + } + } + + pub const PIPES: TokenSet = enum_set!(PIPE | MAPPING_PIPE | NULL_PIPE); + + fn pipe(p: &mut Parser) -> bool { + if PIPES.contains(p.current()) { + p.do_bump(); + true + } else { + false + } + } +} + +pub fn expression(p: &mut Parser, in_pipe: bool) -> Option { + let expr = p.start("expr"); + + if atom(p).or_else(|| instr(p)).is_none() { + expr.abandon(p); + return None; + } + + let r = expr.complete(p, EXPR); + + if PIPES.contains(p.current()) && !in_pipe { + pipeline::pipeline(p, r) + } else { + Some(r) + } +} + +pub fn atom(p: &mut Parser) -> Option { + literal(p) + .or_else(|| collection(p)) + .or_else(|| parenthesized_expr(p)) +} + +pub fn parenthesized_expr(p: &mut Parser) -> Option { + if p.eat(L_PAREN) { + let par_expr = p.start("parenthesized"); + expression(p, false); + if !p.eat(R_PAREN) { + return Some(par_expr.complete_err(p, SyntaxError::Expected(vec![R_PAREN]))); + } + + return Some(par_expr.complete(p, PARENTHESIZED_EXPR)); + } + None +} diff --git a/crates/lang/src/parser/grammar/expression/collection.rs b/crates/lang/src/lst_parser/grammar/expression/collection.rs similarity index 95% rename from crates/lang/src/parser/grammar/expression/collection.rs rename to crates/lang/src/lst_parser/grammar/expression/collection.rs index e72cb6c..8535291 100644 --- a/crates/lang/src/parser/grammar/expression/collection.rs +++ b/crates/lang/src/lst_parser/grammar/expression/collection.rs @@ -1,6 +1,6 @@ use enumset::enum_set; -use crate::parser::{ +use crate::lst_parser::{ syntax_kind::{SyntaxKind::*, TokenSet}, CompletedMarker, Parser, }; diff --git a/crates/lang/src/parser/grammar/expression/collection/attr_set.rs b/crates/lang/src/lst_parser/grammar/expression/collection/attr_set.rs similarity index 95% rename from crates/lang/src/parser/grammar/expression/collection/attr_set.rs rename to crates/lang/src/lst_parser/grammar/expression/collection/attr_set.rs index 2ef90b5..b5a73fa 100644 --- a/crates/lang/src/parser/grammar/expression/collection/attr_set.rs +++ b/crates/lang/src/lst_parser/grammar/expression/collection/attr_set.rs @@ -1,4 +1,4 @@ -use crate::parser::{ +use crate::lst_parser::{ error::SyntaxError, grammar::expression::{atom, expression}, CompletedMarker, Marker, Parser, @@ -36,7 +36,7 @@ fn attr(p: &mut Parser) -> Option { // TODO: handle failed expr parser too let attr_value = p.start("attr_value"); - let _ = expression(p); + let _ = expression(p, false); attr_value.complete(p, ATTR_VALUE); Some(attr_start.complete(p, ATTR)) } else { diff --git a/crates/lang/src/parser/grammar/expression/collection/vec.rs b/crates/lang/src/lst_parser/grammar/expression/collection/vec.rs similarity index 87% rename from crates/lang/src/parser/grammar/expression/collection/vec.rs rename to crates/lang/src/lst_parser/grammar/expression/collection/vec.rs index eff741a..fa76058 100644 --- a/crates/lang/src/parser/grammar/expression/collection/vec.rs +++ b/crates/lang/src/lst_parser/grammar/expression/collection/vec.rs @@ -1,4 +1,4 @@ -use crate::parser::{ +use crate::lst_parser::{ error::SyntaxError, grammar::expression::atom, CompletedMarker, Marker, Parser, SyntaxKind::*, }; @@ -7,7 +7,8 @@ pub fn vec_matrix_list(p: &mut Parser) -> CompletedMarker { assert!(p.eat(L_BRACK)); let row_start = p.start("matrix_row_start"); if let Some(item) = atom(p) { - item.precede(p).complete(p, COLLECTION_ITEM); + item.precede(p, "coll_item_start") + .complete(p, COLLECTION_ITEM); if p.at(COMMA) { row_start.abandon(p); @@ -27,7 +28,8 @@ fn finish_list(p: &mut Parser, list_start: Marker) -> CompletedMarker { loop { if p.eat(COMMA) { if let Some(item) = atom(p) { - item.precede(p).complete(p, COLLECTION_ITEM); + item.precede(p, "coll_item_start") + .complete(p, COLLECTION_ITEM); } else if p.eat(R_BRACK) { return list_start.complete(p, LIST); } @@ -43,7 +45,8 @@ fn finish_mat_or_vec(p: &mut Parser, coll_start: Marker, mut row_start: Marker) let mut row_item_count = 1; loop { if let Some(item) = atom(p) { - item.precede(p).complete(p, COLLECTION_ITEM); + item.precede(p, "coll_item_start") + .complete(p, COLLECTION_ITEM); row_item_count += 1; } else if p.at(SEMICOLON) { is_matrix = true; diff --git a/crates/lang/src/parser/grammar/expression/instruction.rs b/crates/lang/src/lst_parser/grammar/expression/instruction.rs similarity index 78% rename from crates/lang/src/parser/grammar/expression/instruction.rs rename to crates/lang/src/lst_parser/grammar/expression/instruction.rs index 832d2ab..bbe0ed3 100644 --- a/crates/lang/src/parser/grammar/expression/instruction.rs +++ b/crates/lang/src/lst_parser/grammar/expression/instruction.rs @@ -1,4 +1,4 @@ -use crate::parser::{syntax_kind::SyntaxKind::*, CompletedMarker, Parser}; +use crate::lst_parser::{syntax_kind::SyntaxKind::*, CompletedMarker, Parser}; use super::{atom, lit::literal}; @@ -29,6 +29,6 @@ fn instr_params(p: &mut Parser) { if let Some(start) = atom(p) { while atom(p).is_some() {} - start.precede(p).complete(p, INSTR_PARAMS); + start.precede(p, "params_start").complete(p, INSTR_PARAMS); } } diff --git a/crates/lang/src/parser/grammar/expression/lit.rs b/crates/lang/src/lst_parser/grammar/expression/lit.rs similarity index 97% rename from crates/lang/src/parser/grammar/expression/lit.rs rename to crates/lang/src/lst_parser/grammar/expression/lit.rs index 4917c88..8a18a04 100644 --- a/crates/lang/src/parser/grammar/expression/lit.rs +++ b/crates/lang/src/lst_parser/grammar/expression/lit.rs @@ -1,7 +1,7 @@ use enumset::enum_set; use indoc::indoc; -use crate::parser::{ +use crate::lst_parser::{ grammar::check_parser, syntax_kind::{SyntaxKind::*, TokenSet}, CompletedMarker, Parser, diff --git a/crates/lang/src/parser/input.rs b/crates/lang/src/lst_parser/input.rs similarity index 97% rename from crates/lang/src/parser/input.rs rename to crates/lang/src/lst_parser/input.rs index c61fc87..e9a5e2e 100644 --- a/crates/lang/src/parser/input.rs +++ b/crates/lang/src/lst_parser/input.rs @@ -1,4 +1,4 @@ -use crate::parser::syntax_kind::SyntaxKind; +use crate::lst_parser::syntax_kind::SyntaxKind; pub struct Input<'src, 'toks> { raw: &'toks Vec<(SyntaxKind, &'src str)>, diff --git a/crates/lang/src/parser/output.rs b/crates/lang/src/lst_parser/output.rs similarity index 98% rename from crates/lang/src/parser/output.rs rename to crates/lang/src/lst_parser/output.rs index 75019bb..b530ac3 100644 --- a/crates/lang/src/parser/output.rs +++ b/crates/lang/src/lst_parser/output.rs @@ -1,7 +1,7 @@ use rowan::{GreenNode, GreenNodeBuilder, GreenNodeData, GreenTokenData, Language, NodeOrToken}; use std::mem; -use crate::parser::syntax_kind::{Lang, SyntaxKind}; +use crate::lst_parser::syntax_kind::{Lang, SyntaxKind}; use super::{error::SyntaxError, events::Event}; diff --git a/crates/lang/src/parser/syntax_kind.rs b/crates/lang/src/lst_parser/syntax_kind.rs similarity index 99% rename from crates/lang/src/parser/syntax_kind.rs rename to crates/lang/src/lst_parser/syntax_kind.rs index 0447a90..3d817e3 100644 --- a/crates/lang/src/parser/syntax_kind.rs +++ b/crates/lang/src/lst_parser/syntax_kind.rs @@ -92,6 +92,7 @@ pub enum SyntaxKind { MAPPING_PIPE, #[token("!|")] NULL_PIPE, + PIPELINE, #[token("=")] EQ, #[token(":")] diff --git a/crates/lang/src/parser/tests.rs b/crates/lang/src/lst_parser/tests.rs similarity index 100% rename from crates/lang/src/parser/tests.rs rename to crates/lang/src/lst_parser/tests.rs diff --git a/crates/lang/src/main.rs b/crates/lang/src/main.rs index 515cbe0..517094d 100644 --- a/crates/lang/src/main.rs +++ b/crates/lang/src/main.rs @@ -1,7 +1,7 @@ use clap::Parser; use std::{fs, path::PathBuf}; -use lang::parser::{self, grammar, input, output::Output, syntax_kind}; +use lang::lst_parser::{self, grammar, input, output::Output, syntax_kind}; #[derive(Parser)] struct Args { @@ -16,7 +16,7 @@ fn main() { let toks = dbg!(syntax_kind::lex(&f)); let input = input::Input::new(&toks); - let mut parser = parser::Parser::new(input); + let mut parser = lst_parser::Parser::new(input); grammar::source_file(&mut parser); diff --git a/crates/lang/src/parser/grammar/expression.rs b/crates/lang/src/parser/grammar/expression.rs deleted file mode 100644 index 2d3460c..0000000 --- a/crates/lang/src/parser/grammar/expression.rs +++ /dev/null @@ -1,22 +0,0 @@ -use crate::parser::{syntax_kind::SyntaxKind::*, CompletedMarker, Parser}; - -use self::{collection::collection, instruction::instr, lit::literal}; - -mod collection; -mod instruction; -mod lit; - -pub fn expression(p: &mut Parser) -> Option { - let expr = p.start("expr"); - - if atom(p).or_else(|| instr(p)).is_none() { - expr.abandon(p); - return None; - } - - Some(expr.complete(p, EXPR)) -} - -pub fn atom(p: &mut Parser) -> Option { - literal(p).or_else(|| collection(p)) -} diff --git a/testfiles/test.owo b/testfiles/test.owo index 51f07d1..bbcf720 100644 --- a/testfiles/test.owo +++ b/testfiles/test.owo @@ -1,4 +1 @@ -generator | { - foo, - bar -} | +meow 1 (3 | add 1)