feat: parse apply

This commit is contained in:
rvcas 2022-05-06 01:17:47 -04:00
parent 6da0c829df
commit 3484e484a9
No known key found for this signature in database
GPG Key ID: C09B64E263F7D68C
2 changed files with 77 additions and 61 deletions

View File

@ -1,14 +1,17 @@
use combine::{ use combine::{
attempt, between, choice, many1, attempt, between, choice, many1,
parser::char::{alpha_num, digit, hex_digit, space, spaces, string}, parser::char::{alpha_num, digit, hex_digit, space, spaces, string},
skip_many1, token, EasyParser, ParseError, Parser, Stream, skip_many1,
stream::position,
token, EasyParser, ParseError, Parser, Stream,
}; };
use crate::ast::{Constant, Program, Term}; use crate::ast::{Constant, Program, Term};
pub fn program(src: &str) -> anyhow::Result<Program> { pub fn program(src: &str) -> anyhow::Result<Program> {
let mut parser = program_(); let mut parser = program_();
let result = parser.easy_parse(src);
let result = parser.easy_parse(position::Stream::new(src));
match result { match result {
Ok((program, _)) => Ok(program), Ok((program, _)) => Ok(program),
@ -16,19 +19,20 @@ pub fn program(src: &str) -> anyhow::Result<Program> {
} }
} }
pub fn program_<Input>() -> impl Parser<Input, Output = Program> fn program_<Input>() -> impl Parser<Input, Output = Program>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
let prog = string("program") let prog = string("program").with(spaces()).with(
.with(spaces()) (version(), skip_many1(space()), term().skip(spaces()))
.with((version(), spaces(), term()).map(|(version, _, term)| Program { version, term })); .map(|(version, _, term)| Program { version, term }),
);
between(token('('), token(')'), prog).skip(spaces()) between(token('('), token(')'), prog).skip(spaces())
} }
pub fn version<Input>() -> impl Parser<Input, Output = String> fn version<Input>() -> impl Parser<Input, Output = String>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -47,25 +51,18 @@ where
) )
} }
pub fn term<Input>() -> impl Parser<Input, Output = Term> fn term<Input>() -> impl Parser<Input, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
choice((
attempt(between(token('['), token(']'), apply())),
attempt(between(
token('('),
token(')'),
choice(( choice((
attempt(delay()), attempt(delay()),
attempt(lambda()), attempt(lambda()),
attempt(apply()),
attempt(constant()), attempt(constant()),
attempt(force()), attempt(force()),
)),
)),
)) ))
.skip(spaces())
} }
parser! { parser! {
@ -76,59 +73,77 @@ parser! {
} }
} }
pub fn delay<Input>() -> impl Parser<Input, Output = Term> fn delay<Input>() -> impl Parser<Input, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
between(
token('('),
token(')'),
string("delay") string("delay")
.with(skip_many1(space())) .with(skip_many1(space()))
.with(term_()) .with(term_())
.map(|term| Term::Delay(Box::new(term))) .map(|term| Term::Delay(Box::new(term))),
)
} }
pub fn force<Input>() -> impl Parser<Input, Output = Term> fn force<Input>() -> impl Parser<Input, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
between(
token('('),
token(')'),
string("force") string("force")
.with(skip_many1(space())) .with(skip_many1(space()))
.with(term_()) .with(term_())
.map(|term| Term::Force(Box::new(term))) .map(|term| Term::Force(Box::new(term))),
)
} }
pub fn lambda<Input>() -> impl Parser<Input, Output = Term> fn lambda<Input>() -> impl Parser<Input, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
between(
token('('),
token(')'),
string("lam") string("lam")
.with(skip_many1(space())) .with(skip_many1(space()))
.with((many1(alpha_num()), skip_many1(space()), term_())) .with((many1(alpha_num()), skip_many1(space()), term_()))
.map(|(parameter_name, _, term)| Term::Lambda { .map(|(parameter_name, _, term)| Term::Lambda {
parameter_name, parameter_name,
body: Box::new(term), body: Box::new(term),
}) }),
)
} }
pub fn apply<Input>() -> impl Parser<Input, Output = Term> fn apply<Input>() -> impl Parser<Input, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
println!("daid"); between(
(term_(), skip_many1(space()), term_()).map(|(function, _, argument)| Term::Apply { token('['),
token(']'),
(term_().skip(skip_many1(space())), term_()).map(|(function, argument)| Term::Apply {
function: Box::new(function), function: Box::new(function),
argument: Box::new(argument), argument: Box::new(argument),
}) }),
)
} }
pub fn constant<Input>() -> impl Parser<Input, Output = Term> fn constant<Input>() -> impl Parser<Input, Output = Term>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{ {
between(
token('('),
token(')'),
string("con") string("con")
.with(skip_many1(space())) .with(skip_many1(space()))
.with(choice(( .with(choice((
@ -138,10 +153,11 @@ where
attempt(constant_unit()), attempt(constant_unit()),
attempt(constant_bool()), attempt(constant_bool()),
))) )))
.map(Term::Constant) .map(Term::Constant),
)
} }
pub fn constant_integer<Input>() -> impl Parser<Input, Output = Constant> fn constant_integer<Input>() -> impl Parser<Input, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -152,7 +168,7 @@ where
.map(|d: String| Constant::Integer(d.parse::<i64>().unwrap())) .map(|d: String| Constant::Integer(d.parse::<i64>().unwrap()))
} }
pub fn constant_bytestring<Input>() -> impl Parser<Input, Output = Constant> fn constant_bytestring<Input>() -> impl Parser<Input, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -164,7 +180,7 @@ where
.map(|b: String| Constant::ByteString(hex::decode(b).unwrap())) .map(|b: String| Constant::ByteString(hex::decode(b).unwrap()))
} }
pub fn constant_string<Input>() -> impl Parser<Input, Output = Constant> fn constant_string<Input>() -> impl Parser<Input, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -175,7 +191,7 @@ where
.map(Constant::String) .map(Constant::String)
} }
pub fn constant_unit<Input>() -> impl Parser<Input, Output = Constant> fn constant_unit<Input>() -> impl Parser<Input, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
@ -186,7 +202,7 @@ where
.map(|_| Constant::Unit) .map(|_| Constant::Unit)
} }
pub fn constant_bool<Input>() -> impl Parser<Input, Output = Constant> fn constant_bool<Input>() -> impl Parser<Input, Output = Constant>
where where
Input: Stream<Token = char>, Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>, Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,