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),
|
||||
"trace" => Some(Token::Trace),
|
||||
"test" => Some(Token::Test),
|
||||
// TODO: remove this in a future release
|
||||
"error" => Some(Token::Fail),
|
||||
"fail" => Some(Token::Fail),
|
||||
"and" => Some(Token::And),
|
||||
"or" => Some(Token::Or),
|
||||
"validator" => Some(Token::Validator),
|
||||
_ => None,
|
||||
}
|
||||
|
@ -779,6 +783,15 @@ pub enum BinOp {
|
|||
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)]
|
||||
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)]
|
||||
pub enum Error {
|
||||
#[error(
|
||||
|
|
|
@ -533,6 +533,12 @@ pub enum UntypedExpr {
|
|||
location: Span,
|
||||
value: Box<Self>,
|
||||
},
|
||||
|
||||
LogicalOpChain {
|
||||
kind: LogicalOpChainKind,
|
||||
expressions: Vec<Self>,
|
||||
location: Span,
|
||||
},
|
||||
}
|
||||
|
||||
pub const DEFAULT_TODO_STR: &str = "aiken::todo";
|
||||
|
@ -716,6 +722,7 @@ impl UntypedExpr {
|
|||
| Self::FieldAccess { location, .. }
|
||||
| Self::RecordUpdate { location, .. }
|
||||
| Self::UnOp { location, .. }
|
||||
| Self::LogicalOpChain { location, .. }
|
||||
| Self::If { location, .. } => *location,
|
||||
Self::Sequence {
|
||||
location,
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
use chumsky::prelude::*;
|
||||
|
||||
use super::anonymous_binop::parser as anonymous_binop;
|
||||
use super::anonymous_function::parser as anonymous_function;
|
||||
use super::assignment;
|
||||
use super::block::parser as block;
|
||||
|
@ -14,6 +13,7 @@ use super::string::parser as string;
|
|||
use super::tuple::parser as tuple;
|
||||
use super::var::parser as var;
|
||||
use super::when::parser as when;
|
||||
use super::{and_or_chain, anonymous_binop::parser as anonymous_binop};
|
||||
|
||||
use crate::{
|
||||
expr::UntypedExpr,
|
||||
|
@ -33,6 +33,7 @@ pub fn parser<'a>(
|
|||
field_access::parser(),
|
||||
call(expression.clone()),
|
||||
));
|
||||
|
||||
chain_start(sequence, expression)
|
||||
.then(chain.repeated())
|
||||
.foldl(|expr, chain| match chain {
|
||||
|
@ -60,6 +61,7 @@ pub fn chain_start<'a>(
|
|||
record_update(expression.clone()),
|
||||
record(expression.clone()),
|
||||
field_access::constructor(),
|
||||
and_or_chain(expression.clone()),
|
||||
var(),
|
||||
tuple(expression.clone()),
|
||||
bytearray(),
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use chumsky::prelude::*;
|
||||
use vec1::Vec1;
|
||||
|
||||
mod and_or_chain;
|
||||
mod anonymous_binop;
|
||||
pub mod anonymous_function;
|
||||
pub mod assignment;
|
||||
|
@ -19,6 +20,7 @@ mod tuple;
|
|||
mod var;
|
||||
pub mod when;
|
||||
|
||||
pub use and_or_chain::parser as and_or_chain;
|
||||
pub use anonymous_function::parser as anonymous_function;
|
||||
pub use block::parser as block;
|
||||
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() {
|
||||
"trace" => Token::Trace,
|
||||
"fail" => Token::Fail,
|
||||
// TODO: delete this eventually
|
||||
// TODO: remove this in a future release
|
||||
"error" => Token::Fail,
|
||||
"fail" => Token::Fail,
|
||||
"as" => Token::As,
|
||||
"assert" => Token::Expect,
|
||||
"and" => Token::And,
|
||||
"or" => Token::Or,
|
||||
"expect" => Token::Expect,
|
||||
"const" => Token::Const,
|
||||
"fn" => Token::Fn,
|
||||
|
|
|
@ -56,6 +56,8 @@ pub enum Token {
|
|||
Vbar, // '|'
|
||||
VbarVbar, // '||'
|
||||
AmperAmper, // '&&'
|
||||
And, // and
|
||||
Or, // or
|
||||
NewLinePipe, // '↳|>'
|
||||
Pipe, // '|>'
|
||||
Dot, // '.'
|
||||
|
@ -143,6 +145,8 @@ impl fmt::Display for Token {
|
|||
Token::Vbar => "|",
|
||||
Token::VbarVbar => "||",
|
||||
Token::AmperAmper => "&&",
|
||||
Token::And => "and",
|
||||
Token::Or => "or",
|
||||
Token::NewLinePipe => "↳|>",
|
||||
Token::Pipe => "|>",
|
||||
Token::Dot => ".",
|
||||
|
|
|
@ -945,12 +945,12 @@ fn trace_non_strings() {
|
|||
#[test]
|
||||
fn trace_if_false_ok() {
|
||||
let source_code = r#"
|
||||
fn or(a: Bool, b: Bool) {
|
||||
fn or_func(a: Bool, b: Bool) {
|
||||
(a || b)?
|
||||
}
|
||||
|
||||
test foo() {
|
||||
or(True, False)?
|
||||
or_func(True, False)?
|
||||
}
|
||||
|
||||
test bar() {
|
||||
|
|
|
@ -250,7 +250,7 @@ fn format_nested_function_calls() {
|
|||
_ -> fail "expected inline datum"
|
||||
},
|
||||
]
|
||||
|> list.and
|
||||
|> list.and_func
|
||||
}
|
||||
"#
|
||||
);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
---
|
||||
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) {
|
||||
[
|
||||
|
@ -16,6 +16,6 @@ fn foo(output) {
|
|||
_ -> fail @"expected inline datum"
|
||||
},
|
||||
]
|
||||
|> list.and
|
||||
|> list.and_func
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue