From 6c31acbf5df3d26fcda23c25e334e0ce8ab87db7 Mon Sep 17 00:00:00 2001 From: Kasey White Date: Thu, 5 May 2022 00:23:12 -0400 Subject: [PATCH] feat: add constant and delay parsing --- example/plutus-core | 2 +- src/ast.rs | 22 ++++++------- src/parser.rs | 80 +++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 19 deletions(-) diff --git a/example/plutus-core b/example/plutus-core index e91bf68f..53a1833e 100644 --- a/example/plutus-core +++ b/example/plutus-core @@ -1,3 +1,3 @@ (program 1.0.0 - [[(builtin addInteger) (con integer 4)] (con integer 8)] + (con integer 4) ) \ No newline at end of file diff --git a/src/ast.rs b/src/ast.rs index 482eca5b..707b9b7b 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -1,36 +1,36 @@ #[derive(Debug)] -pub struct Program<'a> { +pub struct Program { pub version: String, - pub term: Term<'a>, + pub term: Term, } -#[derive(Debug)] -pub enum Term<'a> { +#[derive(Debug, Clone)] +pub enum Term { // tag: 0 Var(String), // tag: 1 - Delay(&'a Term<'a>), + Delay(Box), // tag: 2 Lambda { parameter_name: String, - body: &'a Term<'a>, + body: Box, }, // tag: 3 Apply { - function: &'a Term<'a>, - argument: &'a Term<'a>, + function: Box, + argument: Box, }, // tag: 4 Constant(Constant), // tag: 5 - Force(&'a Term<'a>), + Force(Box), // tag: 6 - Error(&'a Term<'a>), + Error(Box), // tag: 7 // Builtin } -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum Constant { // TODO: figure out the right size for this // tag: 0 diff --git a/src/parser.rs b/src/parser.rs index 6f0ca5b3..d5943dad 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,10 +1,10 @@ use combine::{ - between, + between, many1, 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 { let mut parser = program_(); @@ -16,7 +16,7 @@ pub fn program(src: &str) -> anyhow::Result { } } -pub fn program_<'a, Input>() -> impl Parser> +pub fn program_() -> impl Parser where Input: Stream, Input::Error: ParseError, @@ -33,15 +33,81 @@ where Input: Stream, Input::Error: ParseError, { - 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> +pub fn term() -> impl Parser where Input: Stream, Input::Error: ParseError, { - string("var").map(|x| Term::Var(x.to_string())) + between(token('('), token(')'), constant()).skip(spaces()) +} + +pub fn delay() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("delay") + .skip(spaces()) + .with(term()) + .map(|term| Term::Delay(Box::new(term))) +} + +pub fn constant() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("con") + .skip(spaces()) + .with(constant_integer().or(unit()).or(constant_bool())) + .map(Term::Constant) +} + +pub fn constant_integer() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("integer") + .skip(spaces()) + .with(many1(digit())) + .map(|d: String| Constant::Integer(d.parse::().unwrap())) +} + +pub fn constant_bool() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("bool") + .skip(spaces()) + .with(string("True").or(string("False"))) + .map(|b| Constant::Bool(b == "True")) +} + +pub fn unit() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("unit") + .skip(spaces()) + .with(string("()")) + .map(|_| Constant::Unit) } #[cfg(test)]