lang: add pipelines and rename parser to lst_parser

This commit is contained in:
Schrottkatze 2024-04-30 12:21:06 +02:00
parent db2643359c
commit 30f17773a8
No known key found for this signature in database
18 changed files with 108 additions and 47 deletions

View file

@ -1,2 +1,2 @@
#![feature(type_alias_impl_trait, lint_reasons)]
pub mod parser;
pub mod lst_parser;

View file

@ -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, .. } => {

View file

@ -1,6 +1,7 @@
use crate::parser::syntax_kind::SyntaxKind;
use crate::lst_parser::syntax_kind::SyntaxKind;
#[derive(Debug)]
pub enum SyntaxError {
Expected(Vec<SyntaxKind>),
PipelineNeedsSink,
}

View file

@ -1,4 +1,4 @@
use crate::parser::syntax_kind::SyntaxKind;
use crate::lst_parser::syntax_kind::SyntaxKind;
#[derive(Debug)]
pub enum Event {

View file

@ -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);

View file

@ -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<CompletedMarker> {
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<CompletedMarker> {
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<CompletedMarker> {
literal(p)
.or_else(|| collection(p))
.or_else(|| parenthesized_expr(p))
}
pub fn parenthesized_expr(p: &mut Parser) -> Option<CompletedMarker> {
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
}

View file

@ -1,6 +1,6 @@
use enumset::enum_set;
use crate::parser::{
use crate::lst_parser::{
syntax_kind::{SyntaxKind::*, TokenSet},
CompletedMarker, Parser,
};

View file

@ -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<CompletedMarker> {
// 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 {

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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,

View file

@ -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)>,

View file

@ -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};

View file

@ -92,6 +92,7 @@ pub enum SyntaxKind {
MAPPING_PIPE,
#[token("!|")]
NULL_PIPE,
PIPELINE,
#[token("=")]
EQ,
#[token(":")]

View file

@ -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);

View file

@ -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<CompletedMarker> {
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<CompletedMarker> {
literal(p).or_else(|| collection(p))
}

View file

@ -1,4 +1 @@
generator | {
foo,
bar
} |
meow 1 (3 | add 1)