feat: add constant and delay parsing
This commit is contained in:
parent
501396450f
commit
6c31acbf5d
|
@ -1,3 +1,3 @@
|
||||||
(program 1.0.0
|
(program 1.0.0
|
||||||
[[(builtin addInteger) (con integer 4)] (con integer 8)]
|
(con integer 4)
|
||||||
)
|
)
|
22
src/ast.rs
22
src/ast.rs
|
@ -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
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
Loading…
Reference in New Issue