From b3318e5f246f5a382ca87b9f98e536d8248b3f12 Mon Sep 17 00:00:00 2001 From: rvcas Date: Fri, 6 May 2022 00:26:20 -0400 Subject: [PATCH] feat: most of the constants and better space skipping --- Cargo.lock | 7 ++++ Cargo.toml | 1 + example/plutus-core | 2 +- src/parser.rs | 87 ++++++++++++++++++++++++++++++++++----------- 4 files changed, 75 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12d30458..b70139f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,6 +107,12 @@ dependencies = [ "libc", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "indexmap" version = "1.8.1" @@ -142,6 +148,7 @@ dependencies = [ "anyhow", "clap", "combine", + "hex", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 5793c20b..3118c9ee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,3 +9,4 @@ edition = "2021" anyhow = "1.0.57" clap = { version = "3.1.14", features = ["derive"] } combine = "4.6.4" +hex = "0.4.3" diff --git a/example/plutus-core b/example/plutus-core index 53a1833e..f060918b 100644 --- a/example/plutus-core +++ b/example/plutus-core @@ -1,3 +1,3 @@ (program 1.0.0 - (con integer 4) + (con bool False) ) \ No newline at end of file diff --git a/src/parser.rs b/src/parser.rs index 23327212..10523e34 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,14 +1,14 @@ use combine::{ - between, many1, - parser::char::{digit, spaces, string}, - token, ParseError, Parser, Stream, + attempt, between, choice, many1, + parser::char::{alpha_num, digit, hex_digit, space, spaces, string}, + skip_many1, token, EasyParser, ParseError, Parser, Stream, }; use crate::ast::{Constant, Program, Term}; pub fn program(src: &str) -> anyhow::Result { let mut parser = program_(); - let result = parser.parse(src); + let result = parser.easy_parse(src); match result { Ok((program, _)) => Ok(program), @@ -52,7 +52,12 @@ where Input: Stream, Input::Error: ParseError, { - between(token('('), token(')'), constant().or(delay())).skip(spaces()) + between( + token('('), + token(')'), + choice((attempt(constant()), attempt(delay()), attempt(force()))), + ) + .skip(spaces()) } parser! { @@ -69,19 +74,36 @@ where Input::Error: ParseError, { string("delay") - .skip(spaces()) + .with(skip_many1(space())) .with(term_()) .map(|term| Term::Delay(Box::new(term))) } +pub fn force() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("force") + .with(skip_many1(space())) + .with(term_()) + .map(|term| Term::Force(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())) + .with(skip_many1(space())) + .with(choice(( + attempt(constant_integer()), + attempt(constant_bytestring()), + attempt(constant_string()), + attempt(constant_unit()), + attempt(constant_bool()), + ))) .map(Term::Constant) } @@ -91,33 +113,56 @@ where Input::Error: ParseError, { string("integer") - .skip(spaces()) + .with(skip_many1(space())) .with(many1(digit())) .map(|d: String| Constant::Integer(d.parse::().unwrap())) } +pub fn constant_bytestring() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("bytestring") + .with(skip_many1(space())) + .with(token('#')) + .with(many1(hex_digit())) + .map(|b: String| Constant::ByteString(hex::decode(b).unwrap())) +} + +pub fn constant_string() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("string") + .with(skip_many1(space())) + .with(between(token('"'), token('"'), many1(alpha_num()))) + .map(Constant::String) +} + +pub fn constant_unit() -> impl Parser +where + Input: Stream, + Input::Error: ParseError, +{ + string("unit") + .with(skip_many1(space())) + .with(string("()")) + .map(|_| Constant::Unit) +} + pub fn constant_bool() -> impl Parser where Input: Stream, Input::Error: ParseError, { string("bool") - .skip(spaces()) + .with(skip_many1(space())) .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)] mod test { use combine::Parser;