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
Signed by: schrottkatze
SSH key fingerprint: SHA256:hXb3t1vINBFCiDCmhRABHX5ocdbLiKyCdKI4HK2Rbbc
18 changed files with 108 additions and 47 deletions

View file

@ -1,2 +1,2 @@
#![feature(type_alias_impl_trait, lint_reasons)] #![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 { impl CompletedMarker {
pub(crate) fn precede(self, p: &mut Parser<'_, '_>) -> Marker { pub(crate) fn precede(self, p: &mut Parser<'_, '_>, name: &str) -> Marker {
let new_pos = p.start("new_pos"); let new_pos = p.start(name);
match &mut p.events[self.pos] { match &mut p.events[self.pos] {
Event::Start { forward_parent, .. } => { 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)] #[derive(Debug)]
pub enum SyntaxError { pub enum SyntaxError {
Expected(Vec<SyntaxKind>), 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)] #[derive(Debug)]
pub enum Event { pub enum Event {

View file

@ -1,6 +1,6 @@
use std::fmt::Debug; use std::fmt::Debug;
use crate::parser::syntax_kind::SyntaxKind::*; use crate::lst_parser::syntax_kind::SyntaxKind::*;
use super::{ use super::{
input::Input, input::Input,
@ -14,7 +14,7 @@ mod expression;
pub fn source_file(p: &mut Parser) { pub fn source_file(p: &mut Parser) {
let root = p.start("root"); let root = p.start("root");
expression::expression(p); expression::expression(p, false);
p.eat_succeeding_ws(); p.eat_succeeding_ws();
root.complete(p, ROOT); 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 enumset::enum_set;
use crate::parser::{ use crate::lst_parser::{
syntax_kind::{SyntaxKind::*, TokenSet}, syntax_kind::{SyntaxKind::*, TokenSet},
CompletedMarker, Parser, CompletedMarker, Parser,
}; };

View file

@ -1,4 +1,4 @@
use crate::parser::{ use crate::lst_parser::{
error::SyntaxError, error::SyntaxError,
grammar::expression::{atom, expression}, grammar::expression::{atom, expression},
CompletedMarker, Marker, Parser, CompletedMarker, Marker, Parser,
@ -36,7 +36,7 @@ fn attr(p: &mut Parser) -> Option<CompletedMarker> {
// TODO: handle failed expr parser too // TODO: handle failed expr parser too
let attr_value = p.start("attr_value"); let attr_value = p.start("attr_value");
let _ = expression(p); let _ = expression(p, false);
attr_value.complete(p, ATTR_VALUE); attr_value.complete(p, ATTR_VALUE);
Some(attr_start.complete(p, ATTR)) Some(attr_start.complete(p, ATTR))
} else { } else {

View file

@ -1,4 +1,4 @@
use crate::parser::{ use crate::lst_parser::{
error::SyntaxError, grammar::expression::atom, CompletedMarker, Marker, Parser, SyntaxKind::*, 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)); assert!(p.eat(L_BRACK));
let row_start = p.start("matrix_row_start"); let row_start = p.start("matrix_row_start");
if let Some(item) = atom(p) { 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) { if p.at(COMMA) {
row_start.abandon(p); row_start.abandon(p);
@ -27,7 +28,8 @@ fn finish_list(p: &mut Parser, list_start: Marker) -> CompletedMarker {
loop { loop {
if p.eat(COMMA) { if p.eat(COMMA) {
if let Some(item) = atom(p) { 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) { } else if p.eat(R_BRACK) {
return list_start.complete(p, LIST); 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; let mut row_item_count = 1;
loop { loop {
if let Some(item) = atom(p) { 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; row_item_count += 1;
} else if p.at(SEMICOLON) { } else if p.at(SEMICOLON) {
is_matrix = true; 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}; use super::{atom, lit::literal};
@ -29,6 +29,6 @@ fn instr_params(p: &mut Parser) {
if let Some(start) = atom(p) { if let Some(start) = atom(p) {
while atom(p).is_some() {} 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 enumset::enum_set;
use indoc::indoc; use indoc::indoc;
use crate::parser::{ use crate::lst_parser::{
grammar::check_parser, grammar::check_parser,
syntax_kind::{SyntaxKind::*, TokenSet}, syntax_kind::{SyntaxKind::*, TokenSet},
CompletedMarker, Parser, 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> { pub struct Input<'src, 'toks> {
raw: &'toks Vec<(SyntaxKind, &'src str)>, raw: &'toks Vec<(SyntaxKind, &'src str)>,

View file

@ -1,7 +1,7 @@
use rowan::{GreenNode, GreenNodeBuilder, GreenNodeData, GreenTokenData, Language, NodeOrToken}; use rowan::{GreenNode, GreenNodeBuilder, GreenNodeData, GreenTokenData, Language, NodeOrToken};
use std::mem; use std::mem;
use crate::parser::syntax_kind::{Lang, SyntaxKind}; use crate::lst_parser::syntax_kind::{Lang, SyntaxKind};
use super::{error::SyntaxError, events::Event}; use super::{error::SyntaxError, events::Event};

View file

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

View file

@ -1,7 +1,7 @@
use clap::Parser; use clap::Parser;
use std::{fs, path::PathBuf}; 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)] #[derive(Parser)]
struct Args { struct Args {
@ -16,7 +16,7 @@ fn main() {
let toks = dbg!(syntax_kind::lex(&f)); let toks = dbg!(syntax_kind::lex(&f));
let input = input::Input::new(&toks); 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); 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 | { meow 1 (3 | add 1)
foo,
bar
} |