feat: most of the constants and better space skipping
This commit is contained in:
parent
6fdcd7012d
commit
b3318e5f24
|
@ -107,6 +107,12 @@ dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hex"
|
||||||
|
version = "0.4.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "1.8.1"
|
version = "1.8.1"
|
||||||
|
@ -142,6 +148,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"clap",
|
"clap",
|
||||||
"combine",
|
"combine",
|
||||||
|
"hex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -9,3 +9,4 @@ edition = "2021"
|
||||||
anyhow = "1.0.57"
|
anyhow = "1.0.57"
|
||||||
clap = { version = "3.1.14", features = ["derive"] }
|
clap = { version = "3.1.14", features = ["derive"] }
|
||||||
combine = "4.6.4"
|
combine = "4.6.4"
|
||||||
|
hex = "0.4.3"
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
(program 1.0.0
|
(program 1.0.0
|
||||||
(con integer 4)
|
(con bool False)
|
||||||
)
|
)
|
|
@ -1,14 +1,14 @@
|
||||||
use combine::{
|
use combine::{
|
||||||
between, many1,
|
attempt, between, choice, many1,
|
||||||
parser::char::{digit, spaces, string},
|
parser::char::{alpha_num, digit, hex_digit, space, spaces, string},
|
||||||
token, ParseError, Parser, Stream,
|
skip_many1, token, EasyParser, ParseError, Parser, Stream,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::ast::{Constant, 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_();
|
||||||
let result = parser.parse(src);
|
let result = parser.easy_parse(src);
|
||||||
|
|
||||||
match result {
|
match result {
|
||||||
Ok((program, _)) => Ok(program),
|
Ok((program, _)) => Ok(program),
|
||||||
|
@ -52,7 +52,12 @@ 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>,
|
||||||
{
|
{
|
||||||
between(token('('), token(')'), constant().or(delay())).skip(spaces())
|
between(
|
||||||
|
token('('),
|
||||||
|
token(')'),
|
||||||
|
choice((attempt(constant()), attempt(delay()), attempt(force()))),
|
||||||
|
)
|
||||||
|
.skip(spaces())
|
||||||
}
|
}
|
||||||
|
|
||||||
parser! {
|
parser! {
|
||||||
|
@ -69,19 +74,36 @@ where
|
||||||
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
||||||
{
|
{
|
||||||
string("delay")
|
string("delay")
|
||||||
.skip(spaces())
|
.with(skip_many1(space()))
|
||||||
.with(term_())
|
.with(term_())
|
||||||
.map(|term| Term::Delay(Box::new(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>
|
pub fn constant<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("con")
|
string("con")
|
||||||
.skip(spaces())
|
.with(skip_many1(space()))
|
||||||
.with(constant_integer().or(unit()).or(constant_bool()))
|
.with(choice((
|
||||||
|
attempt(constant_integer()),
|
||||||
|
attempt(constant_bytestring()),
|
||||||
|
attempt(constant_string()),
|
||||||
|
attempt(constant_unit()),
|
||||||
|
attempt(constant_bool()),
|
||||||
|
)))
|
||||||
.map(Term::Constant)
|
.map(Term::Constant)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,33 +113,56 @@ where
|
||||||
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
Input::Error: ParseError<Input::Token, Input::Range, Input::Position>,
|
||||||
{
|
{
|
||||||
string("integer")
|
string("integer")
|
||||||
.skip(spaces())
|
.with(skip_many1(space()))
|
||||||
.with(many1(digit()))
|
.with(many1(digit()))
|
||||||
.map(|d: String| Constant::Integer(d.parse::<i64>().unwrap()))
|
.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>
|
pub fn constant_bool<Input>() -> impl Parser<Input, Output = Constant>
|
||||||
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("bool")
|
string("bool")
|
||||||
.skip(spaces())
|
.with(skip_many1(space()))
|
||||||
.with(string("True").or(string("False")))
|
.with(string("True").or(string("False")))
|
||||||
.map(|b| Constant::Bool(b == "True"))
|
.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)]
|
||||||
mod test {
|
mod test {
|
||||||
use combine::Parser;
|
use combine::Parser;
|
||||||
|
|
Loading…
Reference in New Issue