lang: add pipelines and rename parser to lst_parser
This commit is contained in:
parent
db2643359c
commit
30f17773a8
18 changed files with 108 additions and 47 deletions
|
@ -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;
|
||||||
|
|
|
@ -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, .. } => {
|
|
@ -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,
|
||||||
}
|
}
|
|
@ -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 {
|
|
@ -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);
|
81
crates/lang/src/lst_parser/grammar/expression.rs
Normal file
81
crates/lang/src/lst_parser/grammar/expression.rs
Normal 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
|
||||||
|
}
|
|
@ -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,
|
||||||
};
|
};
|
|
@ -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 {
|
|
@ -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;
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,
|
|
@ -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)>,
|
|
@ -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};
|
||||||
|
|
|
@ -92,6 +92,7 @@ pub enum SyntaxKind {
|
||||||
MAPPING_PIPE,
|
MAPPING_PIPE,
|
||||||
#[token("!|")]
|
#[token("!|")]
|
||||||
NULL_PIPE,
|
NULL_PIPE,
|
||||||
|
PIPELINE,
|
||||||
#[token("=")]
|
#[token("=")]
|
||||||
EQ,
|
EQ,
|
||||||
#[token(":")]
|
#[token(":")]
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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))
|
|
||||||
}
|
|
|
@ -1,4 +1 @@
|
||||||
generator | {
|
meow 1 (3 | add 1)
|
||||||
foo,
|
|
||||||
bar
|
|
||||||
} |
|
|
||||||
|
|
Loading…
Reference in a new issue