Skip to content

Commit

Permalink
Parse module syntax.
Browse files Browse the repository at this point in the history
  • Loading branch information
01mf02 committed May 24, 2024
1 parent 0ad3dc4 commit ef0b298
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 6 deletions.
67 changes: 63 additions & 4 deletions jaq-parse/src/term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ impl<'a> Parser<'a> {
})
}

fn terminated<T>(&mut self, f: impl FnOnce(&mut Self) -> Result<'a, T>) -> Result<'a, T> {
let y = f(self)?;
self.char1(';')?;
Ok(y)
}

fn char1(&mut self, c: char) -> Result<'a, &'a str> {
match self.i.next() {
Some(Token::Char(s)) if s.chars().eq([c]) => Ok(*s),
Expand Down Expand Up @@ -413,7 +419,7 @@ impl<'a> Parser<'a> {

fn def_tail(&mut self) -> Result<'a, Def<&'a str, Term<&'a str>>> {
let name = match self.i.next() {
Some(Token::Word(name)) if !name.starts_with(['$', '@']) => name,
Some(Token::Word(name)) if !name.starts_with(['$']) => name,
next => return Err((Expect::Ident, next)),
};
let args = self.args(|p| {
Expand All @@ -425,15 +431,68 @@ impl<'a> Parser<'a> {
self.char1(':')?;

let body = self.term()?;
self.char1(';')?;

Ok(Def { name, args, body })
}

fn bare_str(&mut self) -> Result<'a, &'a str> {
match self.i.next() {
Some(Token::Char(";")) => (),
next => return Err((Expect::Char(';'), next)),
Some(Token::Str(parts)) => match parts[..] {
[StrPart::Str(s)] => Ok(s),
_ => todo!(),
},
next => Err((Expect::Str, next)),
}
}

fn include(&mut self) -> Result<'a, (&'a str, Option<&'a str>)> {
self.bare_str().map(|path| (path, None))
}

fn import(&mut self) -> Result<'a, (&'a str, Option<&'a str>)> {
let path = self.bare_str()?;
self.keyword("as")?;
let name = match self.i.next() {
Some(Token::Word(name)) if !name.starts_with(['$', '@']) => *name,
next => return Err((Expect::Ident, next)),
};
Ok((path, Some(name)))
}

Ok(Def { name, args, body })
pub fn module<B, F>(&mut self, f: F) -> Result<'a, Module<&'a str, B>>
where
F: FnOnce(&mut Self) -> Result<'a, B>,
{
let meta = self
.maybe(|p| match p.i.next() {
Some(Token::Word("module")) => Some(p.terminated(|p| p.term())),
_ => None,
})
.transpose()?;

let mods = core::iter::from_fn(|| {
self.maybe(|p| match p.i.next() {
Some(Token::Word("include")) => Some(p.terminated(|p| p.include())),
Some(Token::Word("import")) => Some(p.terminated(|p| p.import())),
_ => None,
})
})
.collect::<Result<_>>()?;

let body = f(self)?;

Ok(Module { meta, mods, body })
}
}

#[derive(Debug)]
pub struct Module<S, B> {
meta: Option<Term<S>>,
mods: Vec<(S, Option<S>)>,
body: B,
}

#[derive(Debug)]
pub struct Def<S, F> {
name: S,
Expand Down
3 changes: 1 addition & 2 deletions jaq/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,13 @@ fn parse(filter_str: &str, vars: Vec<String>) -> Result<Filter, Vec<ParseError>>
let (tokens, lex_errs) = jaq_parse::lex::Lex::new(filter_str).lex();
if lex_errs.is_empty() {
let mut parser = jaq_parse::term::Parser::new(&tokens);
std::println!("{:?}", parser.term());
std::println!("{:?}", parser.module(|p| p.term()));
std::println!("{:?}", parser.e);
} else {
std::println!("{:?}", lex_errs);
}
*/


assert!(defs.errs.is_empty());
let (filter, errs) = jaq_parse::parse(filter_str, jaq_parse::main());
if !errs.is_empty() {
Expand Down

0 comments on commit ef0b298

Please sign in to comment.