feat: add constant and delay parsing

This commit is contained in:
Kasey White 2022-05-05 00:23:12 -04:00
parent 501396450f
commit 6c31acbf5d
3 changed files with 85 additions and 19 deletions

View File

@ -1,3 +1,3 @@
(program 1.0.0 (program 1.0.0
[[(builtin addInteger) (con integer 4)] (con integer 8)] (con integer 4)
) )

View File

@ -1,36 +1,36 @@
#[derive(Debug)] #[derive(Debug)]
pub struct Program<'a> { pub struct Program {
pub version: String, pub version: String,
pub term: Term<'a>, pub term: Term,
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Term<'a> { pub enum Term {
// tag: 0 // tag: 0
Var(String), Var(String),
// tag: 1 // tag: 1
Delay(&'a Term<'a>), Delay(Box<Term>),
// tag: 2 // tag: 2
Lambda { Lambda {
parameter_name: String, parameter_name: String,
body: &'a Term<'a>, body: Box<Term>,
}, },
// tag: 3 // tag: 3
Apply { Apply {
function: &'a Term<'a>, function: Box<Term>,
argument: &'a Term<'a>, argument: Box<Term>,
}, },
// tag: 4 // tag: 4
Constant(Constant), Constant(Constant),
// tag: 5 // tag: 5
Force(&'a Term<'a>), Force(Box<Term>),
// tag: 6 // tag: 6
Error(&'a Term<'a>), Error(Box<Term>),
// tag: 7 // tag: 7
// Builtin // Builtin
} }
#[derive(Debug)] #[derive(Debug, Clone)]
pub enum Constant { pub enum Constant {
// TODO: figure out the right size for this // TODO: figure out the right size for this
// tag: 0 // tag: 0

View File

@ -1,10 +1,10 @@
use combine::{ use combine::{
between, between, many1,
parser::char::{digit, spaces, string}, parser::char::{digit, spaces, string},
sep_by, token, ParseError, Parser, Stream, token, ParseError, Parser, Stream,
}; };
use crate::ast::{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_();
@ -16,7 +16,7 @@ pub fn program(src: &str) -> anyhow::Result<Program> {
} }
} }
pub fn program_<'a, Input>() -> impl Parser<Input, Output = Program<'a>> pub 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>,
@ -33,15 +33,81 @@ 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>,
{ {
sep_by(digit(), token('.')) (
many1(digit()),
token('.'),
many1(digit()),
token('.'),
many1(digit()),
)
.map(
|(major, _, minor, _, patch): (String, char, String, char, String)| {
format!("{}.{}.{}", major, minor, patch)
},
)
} }
pub fn term<'a, Input>() -> impl Parser<Input, Output = Term<'a>> pub 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>,
{ {
string("var").map(|x| Term::Var(x.to_string())) between(token('('), token(')'), constant()).skip(spaces())
}
pub fn delay<Input>() -> impl Parser<Input, Output = Term>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
string("delay")
.skip(spaces())
.with(term())
.map(|term| Term::Delay(Box::new(term)))
}
pub fn constant<Input>() -> impl Parser<Input, Output = Term>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
string("con")
.skip(spaces())
.with(constant_integer().or(unit()).or(constant_bool()))
.map(Term::Constant)
}
pub fn constant_integer<Input>() -> impl Parser<Input, Output = Constant>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
string("integer")
.skip(spaces())
.with(many1(digit()))
.map(|d: String| Constant::Integer(d.parse::<i64>().unwrap()))
}
pub fn constant_bool<Input>() -> impl Parser<Input, Output = Constant>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
string("bool")
.skip(spaces())
.with(string("True").or(string("False")))
.map(|b| Constant::Bool(b == "True"))
}
pub fn unit<Input>() -> impl Parser<Input, Output = Constant>
where
Input: Stream<Token = char>,
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
{
string("unit")
.skip(spaces())
.with(string("()"))
.map(|_| Constant::Unit)
} }
#[cfg(test)] #[cfg(test)]