feat(parser): add support for and/or chaining
This commit is contained in:
parent
4a1ae9f412
commit
ab3a418b9c
|
@ -116,7 +116,11 @@ fn str_to_keyword(word: &str) -> Option<Token> {
|
||||||
"type" => Some(Token::Type),
|
"type" => Some(Token::Type),
|
||||||
"trace" => Some(Token::Trace),
|
"trace" => Some(Token::Trace),
|
||||||
"test" => Some(Token::Test),
|
"test" => Some(Token::Test),
|
||||||
|
// TODO: remove this in a future release
|
||||||
"error" => Some(Token::Fail),
|
"error" => Some(Token::Fail),
|
||||||
|
"fail" => Some(Token::Fail),
|
||||||
|
"and" => Some(Token::And),
|
||||||
|
"or" => Some(Token::Or),
|
||||||
"validator" => Some(Token::Validator),
|
"validator" => Some(Token::Validator),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -779,6 +783,15 @@ pub enum BinOp {
|
||||||
ModInt,
|
ModInt,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<LogicalOpChainKind> for BinOp {
|
||||||
|
fn from(value: LogicalOpChainKind) -> Self {
|
||||||
|
match value {
|
||||||
|
LogicalOpChainKind::And => BinOp::And,
|
||||||
|
LogicalOpChainKind::Or => BinOp::Or,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
pub enum UnOp {
|
pub enum UnOp {
|
||||||
// !
|
// !
|
||||||
|
@ -1225,6 +1238,21 @@ impl chumsky::Span for Span {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
|
pub enum LogicalOpChainKind {
|
||||||
|
And,
|
||||||
|
Or,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for LogicalOpChainKind {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
LogicalOpChainKind::And => write!(f, "and"),
|
||||||
|
LogicalOpChainKind::Or => write!(f, "or"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, Diagnostic)]
|
#[derive(Debug, thiserror::Error, Diagnostic)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
#[error(
|
#[error(
|
||||||
|
|
|
@ -533,6 +533,12 @@ pub enum UntypedExpr {
|
||||||
location: Span,
|
location: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
},
|
},
|
||||||
|
|
||||||
|
LogicalOpChain {
|
||||||
|
kind: LogicalOpChainKind,
|
||||||
|
expressions: Vec<Self>,
|
||||||
|
location: Span,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const DEFAULT_TODO_STR: &str = "aiken::todo";
|
pub const DEFAULT_TODO_STR: &str = "aiken::todo";
|
||||||
|
@ -716,6 +722,7 @@ impl UntypedExpr {
|
||||||
| Self::FieldAccess { location, .. }
|
| Self::FieldAccess { location, .. }
|
||||||
| Self::RecordUpdate { location, .. }
|
| Self::RecordUpdate { location, .. }
|
||||||
| Self::UnOp { location, .. }
|
| Self::UnOp { location, .. }
|
||||||
|
| Self::LogicalOpChain { location, .. }
|
||||||
| Self::If { location, .. } => *location,
|
| Self::If { location, .. } => *location,
|
||||||
Self::Sequence {
|
Self::Sequence {
|
||||||
location,
|
location,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
|
|
||||||
use super::anonymous_binop::parser as anonymous_binop;
|
|
||||||
use super::anonymous_function::parser as anonymous_function;
|
use super::anonymous_function::parser as anonymous_function;
|
||||||
use super::assignment;
|
use super::assignment;
|
||||||
use super::block::parser as block;
|
use super::block::parser as block;
|
||||||
|
@ -14,6 +13,7 @@ use super::string::parser as string;
|
||||||
use super::tuple::parser as tuple;
|
use super::tuple::parser as tuple;
|
||||||
use super::var::parser as var;
|
use super::var::parser as var;
|
||||||
use super::when::parser as when;
|
use super::when::parser as when;
|
||||||
|
use super::{and_or_chain, anonymous_binop::parser as anonymous_binop};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
expr::UntypedExpr,
|
expr::UntypedExpr,
|
||||||
|
@ -33,6 +33,7 @@ pub fn parser<'a>(
|
||||||
field_access::parser(),
|
field_access::parser(),
|
||||||
call(expression.clone()),
|
call(expression.clone()),
|
||||||
));
|
));
|
||||||
|
|
||||||
chain_start(sequence, expression)
|
chain_start(sequence, expression)
|
||||||
.then(chain.repeated())
|
.then(chain.repeated())
|
||||||
.foldl(|expr, chain| match chain {
|
.foldl(|expr, chain| match chain {
|
||||||
|
@ -60,6 +61,7 @@ pub fn chain_start<'a>(
|
||||||
record_update(expression.clone()),
|
record_update(expression.clone()),
|
||||||
record(expression.clone()),
|
record(expression.clone()),
|
||||||
field_access::constructor(),
|
field_access::constructor(),
|
||||||
|
and_or_chain(expression.clone()),
|
||||||
var(),
|
var(),
|
||||||
tuple(expression.clone()),
|
tuple(expression.clone()),
|
||||||
bytearray(),
|
bytearray(),
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
use chumsky::prelude::*;
|
use chumsky::prelude::*;
|
||||||
use vec1::Vec1;
|
use vec1::Vec1;
|
||||||
|
|
||||||
|
mod and_or_chain;
|
||||||
mod anonymous_binop;
|
mod anonymous_binop;
|
||||||
pub mod anonymous_function;
|
pub mod anonymous_function;
|
||||||
pub mod assignment;
|
pub mod assignment;
|
||||||
|
@ -19,6 +20,7 @@ mod tuple;
|
||||||
mod var;
|
mod var;
|
||||||
pub mod when;
|
pub mod when;
|
||||||
|
|
||||||
|
pub use and_or_chain::parser as and_or_chain;
|
||||||
pub use anonymous_function::parser as anonymous_function;
|
pub use anonymous_function::parser as anonymous_function;
|
||||||
pub use block::parser as block;
|
pub use block::parser as block;
|
||||||
pub use bytearray::parser as bytearray;
|
pub use bytearray::parser as bytearray;
|
||||||
|
|
|
@ -222,11 +222,12 @@ pub fn lexer() -> impl Parser<char, Vec<(Token, Span)>, Error = ParseError> {
|
||||||
|
|
||||||
let keyword = text::ident().map(|s: String| match s.as_str() {
|
let keyword = text::ident().map(|s: String| match s.as_str() {
|
||||||
"trace" => Token::Trace,
|
"trace" => Token::Trace,
|
||||||
"fail" => Token::Fail,
|
// TODO: remove this in a future release
|
||||||
// TODO: delete this eventually
|
|
||||||
"error" => Token::Fail,
|
"error" => Token::Fail,
|
||||||
|
"fail" => Token::Fail,
|
||||||
"as" => Token::As,
|
"as" => Token::As,
|
||||||
"assert" => Token::Expect,
|
"and" => Token::And,
|
||||||
|
"or" => Token::Or,
|
||||||
"expect" => Token::Expect,
|
"expect" => Token::Expect,
|
||||||
"const" => Token::Const,
|
"const" => Token::Const,
|
||||||
"fn" => Token::Fn,
|
"fn" => Token::Fn,
|
||||||
|
|
|
@ -56,6 +56,8 @@ pub enum Token {
|
||||||
Vbar, // '|'
|
Vbar, // '|'
|
||||||
VbarVbar, // '||'
|
VbarVbar, // '||'
|
||||||
AmperAmper, // '&&'
|
AmperAmper, // '&&'
|
||||||
|
And, // and
|
||||||
|
Or, // or
|
||||||
NewLinePipe, // '↳|>'
|
NewLinePipe, // '↳|>'
|
||||||
Pipe, // '|>'
|
Pipe, // '|>'
|
||||||
Dot, // '.'
|
Dot, // '.'
|
||||||
|
@ -143,6 +145,8 @@ impl fmt::Display for Token {
|
||||||
Token::Vbar => "|",
|
Token::Vbar => "|",
|
||||||
Token::VbarVbar => "||",
|
Token::VbarVbar => "||",
|
||||||
Token::AmperAmper => "&&",
|
Token::AmperAmper => "&&",
|
||||||
|
Token::And => "and",
|
||||||
|
Token::Or => "or",
|
||||||
Token::NewLinePipe => "↳|>",
|
Token::NewLinePipe => "↳|>",
|
||||||
Token::Pipe => "|>",
|
Token::Pipe => "|>",
|
||||||
Token::Dot => ".",
|
Token::Dot => ".",
|
||||||
|
|
|
@ -945,12 +945,12 @@ fn trace_non_strings() {
|
||||||
#[test]
|
#[test]
|
||||||
fn trace_if_false_ok() {
|
fn trace_if_false_ok() {
|
||||||
let source_code = r#"
|
let source_code = r#"
|
||||||
fn or(a: Bool, b: Bool) {
|
fn or_func(a: Bool, b: Bool) {
|
||||||
(a || b)?
|
(a || b)?
|
||||||
}
|
}
|
||||||
|
|
||||||
test foo() {
|
test foo() {
|
||||||
or(True, False)?
|
or_func(True, False)?
|
||||||
}
|
}
|
||||||
|
|
||||||
test bar() {
|
test bar() {
|
||||||
|
|
|
@ -250,7 +250,7 @@ fn format_nested_function_calls() {
|
||||||
_ -> fail "expected inline datum"
|
_ -> fail "expected inline datum"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|> list.and
|
|> list.and_func
|
||||||
}
|
}
|
||||||
"#
|
"#
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
---
|
---
|
||||||
source: crates/aiken-lang/src/tests/format.rs
|
source: crates/aiken-lang/src/tests/format.rs
|
||||||
description: "Code:\n\nfn foo(output) {\n [\n output.address.stake_credential == Some(\n Inline(\n VerificationKeyCredential(\n #\"66666666666666666666666666666666666666666666666666666666\",\n ))\n )\n ,\n when output.datum is {\n InlineDatum(_) -> True\n _ -> fail \"expected inline datum\"\n },\n ]\n |> list.and\n}\n"
|
description: "Code:\n\nfn foo(output) {\n [\n output.address.stake_credential == Some(\n Inline(\n VerificationKeyCredential(\n #\"66666666666666666666666666666666666666666666666666666666\",\n ))\n )\n ,\n when output.datum is {\n InlineDatum(_) -> True\n _ -> fail \"expected inline datum\"\n },\n ]\n |> list.and_func\n}\n"
|
||||||
---
|
---
|
||||||
fn foo(output) {
|
fn foo(output) {
|
||||||
[
|
[
|
||||||
|
@ -16,6 +16,6 @@ fn foo(output) {
|
||||||
_ -> fail @"expected inline datum"
|
_ -> fail @"expected inline datum"
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|> list.and
|
|> list.and_func
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue