feat: most of the constants and better space skipping
This commit is contained in:
parent
6fdcd7012d
commit
b3318e5f24
|
@ -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]]
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
(program 1.0.0
|
||||
(con integer 4)
|
||||
(con bool False)
|
||||
)
|
|
@ -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<Program> {
|
||||
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<Token = char>,
|
||||
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
||||
{
|
||||
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<Input::Token, Input::Range, Input::Position>,
|
||||
{
|
||||
string("delay")
|
||||
.skip(spaces())
|
||||
.with(skip_many1(space()))
|
||||
.with(term_())
|
||||
.map(|term| Term::Delay(Box::new(term)))
|
||||
}
|
||||
|
||||
pub fn force<Input>() -> impl Parser<Input, Output = Term>
|
||||
where
|
||||
Input: Stream<Token = char>,
|
||||
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
||||
{
|
||||
string("force")
|
||||
.with(skip_many1(space()))
|
||||
.with(term_())
|
||||
.map(|term| Term::Force(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()))
|
||||
.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<Input::Token, Input::Range, Input::Position>,
|
||||
{
|
||||
string("integer")
|
||||
.skip(spaces())
|
||||
.with(skip_many1(space()))
|
||||
.with(many1(digit()))
|
||||
.map(|d: String| Constant::Integer(d.parse::<i64>().unwrap()))
|
||||
}
|
||||
|
||||
pub fn constant_bytestring<Input>() -> impl Parser<Input, Output = Constant>
|
||||
where
|
||||
Input: Stream<Token = char>,
|
||||
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
||||
{
|
||||
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<Input>() -> impl Parser<Input, Output = Constant>
|
||||
where
|
||||
Input: Stream<Token = char>,
|
||||
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
||||
{
|
||||
string("string")
|
||||
.with(skip_many1(space()))
|
||||
.with(between(token('"'), token('"'), many1(alpha_num())))
|
||||
.map(Constant::String)
|
||||
}
|
||||
|
||||
pub fn constant_unit<Input>() -> impl Parser<Input, Output = Constant>
|
||||
where
|
||||
Input: Stream<Token = char>,
|
||||
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
||||
{
|
||||
string("unit")
|
||||
.with(skip_many1(space()))
|
||||
.with(string("()"))
|
||||
.map(|_| Constant::Unit)
|
||||
}
|
||||
|
||||
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(skip_many1(space()))
|
||||
.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)]
|
||||
mod test {
|
||||
use combine::Parser;
|
||||
|
|
Loading…
Reference in New Issue