diff --git a/argus-parser/Cargo.toml b/argus-parser/Cargo.toml index 41981ce..004e34e 100644 --- a/argus-parser/Cargo.toml +++ b/argus-parser/Cargo.toml @@ -3,15 +3,15 @@ name = "argus-parser" version = "0.1.0" edition = "2021" -[lib] -name = "argus_parser" - -[[bin]] -name = "argus_parser" -path = "src/main.rs" - +[[example]] +name = "dump_parse_tree" +required-features = ["reporting"] [dependencies] argus-core = { version = "0.1.0", path = "../argus-core" } -ariadne = "0.3.0" +ariadne = { version = "0.3.0", optional = true } chumsky = { version = "1.0.0-alpha.4", features = ["default", "label"] } + +[features] + +reporting = ["dep:ariadne"] diff --git a/argus-parser/src/main.rs b/argus-parser/examples/dump_parse_tree.rs similarity index 85% rename from argus-parser/src/main.rs rename to argus-parser/examples/dump_parse_tree.rs index aea9660..109b3fb 100644 --- a/argus-parser/src/main.rs +++ b/argus-parser/examples/dump_parse_tree.rs @@ -1,14 +1,14 @@ -use std::{env, fs}; +use std::env; -use argus_parser::lexer; -// use crate::parser::{parser, Error as ParseError}; +use argus_parser::{lexer, parser}; use ariadne::{sources, Color, Label, Report, ReportKind}; +use chumsky::prelude::Input; use chumsky::Parser; fn main() { let src = env::args().nth(1).expect("Expected expression"); - let (tokens, mut errs) = lexer().parse(src.as_str()).into_output_errors(); + let (tokens, errs) = lexer().parse(src.as_str()).into_output_errors(); println!("*** Outputting tokens ***"); if let Some(tokens) = &tokens { @@ -33,7 +33,7 @@ fn main() { errs.into_iter() .map(|e| e.map_token(|c| c.to_string())) - // .chain(parse_errs.into_iter().map(|e| e.map_token(|tok| tok.to_string()))) + .chain(parse_errs.into_iter().map(|e| e.map_token(|tok| tok.to_string()))) .for_each(|e| { Report::build(ReportKind::Error, src.clone(), e.span().start) .with_message(e.to_string()) diff --git a/argus-parser/src/lexer.rs b/argus-parser/src/lexer.rs index fb60d98..44734ce 100644 --- a/argus-parser/src/lexer.rs +++ b/argus-parser/src/lexer.rs @@ -94,16 +94,20 @@ pub fn lexer<'src>() -> impl Parser<'src, &'src str, Output<'src>, Error<'src>> let floating_number = just('-') .or_not() .then(digits) - .then(frac.or_not()) - .then(exp.or_not()) + .then(choice((frac.then(exp).slice(), frac.slice(), exp.slice()))) + // .then(frac.or_not()) + // .then(exp.or_not()) .map_slice(|s: &str| Token::Float(s.parse().unwrap())) .boxed(); let signed_int = one_of("+-") - .or_not() + // .or_not() .then(digits) + .then(frac.not().or(exp.not())) .map_slice(|s: &str| Token::Int(s.parse().unwrap())); - let unsigned_int = digits.map_slice(|s: &str| Token::UInt(s.parse().unwrap())); + let unsigned_int = digits + .then(frac.not().or(exp.not())) + .map_slice(|s: &str| Token::UInt(s.parse().unwrap())); let number = choice((floating_number, signed_int, unsigned_int)); @@ -160,10 +164,16 @@ pub fn lexer<'src>() -> impl Parser<'src, &'src str, Output<'src>, Error<'src>> "false" => Token::Bool(false), "G" => Token::Always, "alw" => Token::Always, + "always" => Token::Always, + "globally" => Token::Always, "F" => Token::Eventually, "ev" => Token::Eventually, + "eventually" => Token::Eventually, + "finally" => Token::Eventually, "X" => Token::Next, + "next" => Token::Next, "U" => Token::Until, + "until" => Token::Until, _ => Token::Ident(ident), }); diff --git a/argus-parser/src/parser.rs b/argus-parser/src/parser.rs index d6d9e15..5a35fd7 100644 --- a/argus-parser/src/parser.rs +++ b/argus-parser/src/parser.rs @@ -145,13 +145,6 @@ impl<'src> Expr<'src> { } } - fn var(name: &'src str) -> Self { - Self::Var { - name, - kind: Type::Unknown, - } - } - fn unary_op(op: UnaryOps, arg: Box>, interval: Option>>) -> Self { let mut arg = arg; (*arg).0.make_typed(op.default_type()); @@ -189,8 +182,7 @@ type ParserInput<'tokens, 'src> = SpannedInput, Span, &'tokens [(Tok pub fn num_expr_parser<'tokens, 'src: 'tokens>( ) -> impl Parser<'tokens, ParserInput<'tokens, 'src>, Spanned>, Error<'tokens, 'src>> + Clone { recursive(|num_expr| { - let var = select! { Token::Ident(ident) => Expr::Var{ name: ident.clone(), kind: Type::default()} } - .labelled("variable"); + let var = select! { Token::Ident(name) => Expr::Var{ name, kind: Type::default()} }.labelled("variable"); let num_literal = select! { Token::Int(val) => Expr::Int(val), @@ -223,24 +215,32 @@ pub fn num_expr_parser<'tokens, 'src: 'tokens>( // Product ops (multiply and divide) have equal precedence let product_op = { - let op = just(Token::Times) - .to(BinaryOps::Mul) - .or(just(Token::Divide).to(BinaryOps::Div)); - neg_op.clone().foldl(op.then(neg_op).repeated(), |a, (op, b)| { - let span = a.1.start..b.1.end; - (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) - }) + let op = choice(( + just(Token::Times).to(BinaryOps::Mul), + just(Token::Divide).to(BinaryOps::Div), + )); + neg_op + .clone() + .foldl(op.then(neg_op).repeated(), |a, (op, b)| { + let span = a.1.start..b.1.end; + (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) + }) + .boxed() }; // Sum ops (add and subtract) have equal precedence let sum_op = { - let op = just(Token::Plus) - .to(BinaryOps::Add) - .or(just(Token::Minus).to(BinaryOps::Sub)); - product_op.clone().foldl(op.then(product_op).repeated(), |a, (op, b)| { - let span = a.1.start..b.1.end; - (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) - }) + let op = choice(( + just(Token::Plus).to(BinaryOps::Add), + just(Token::Minus).to(BinaryOps::Sub), + )); + product_op + .clone() + .foldl(op.then(product_op).repeated(), |a, (op, b)| { + let span = a.1.start..b.1.end; + (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) + }) + .boxed() }; sum_op.labelled("numeric expression").as_context() @@ -272,8 +272,9 @@ pub fn parser<'tokens, 'src: 'tokens>( span.into(), ) }) + .boxed() }; - let num_expr = num_expr_parser(); + let num_expr = num_expr_parser().boxed(); recursive(|expr| { let literal = select! { @@ -284,32 +285,28 @@ pub fn parser<'tokens, 'src: 'tokens>( let var = select! { Token::Ident(ident) => Expr::Var{ name: ident.clone(), kind: Type::default()} } .labelled("variable"); - // Relational ops (<, <=, >, >=) have equal precedence + // Relational ops (<, <=, >, >=, ==, !=) have equal precedence let relational_op = { - let op = just(Token::Lt).to(BinaryOps::Lt).or(just(Token::Le) - .to(BinaryOps::Le) - .or(just(Token::Gt).to(BinaryOps::Gt).or(just(Token::Ge).to(BinaryOps::Ge)))); - num_expr.clone().foldl(op.then(num_expr).repeated(), |a, (op, b)| { - let span = a.1.start..b.1.end; - (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) - }) - }; - - // Equality ops (==, !=) have equal precedence - let equality_op = { - let op = just(Token::Eq) - .to(BinaryOps::Eq) - .or(just(Token::Neq).to(BinaryOps::Neq)); - relational_op + let op = choice(( + just(Token::Lt).to(BinaryOps::Lt), + just(Token::Le).to(BinaryOps::Le), + just(Token::Gt).to(BinaryOps::Gt), + just(Token::Ge).to(BinaryOps::Ge), + just(Token::Eq).to(BinaryOps::Eq), + just(Token::Neq).to(BinaryOps::Neq), + )); + num_expr .clone() - .foldl(op.then(relational_op).repeated(), |a, (op, b)| { + .then(op.then(num_expr)) + .map(|(a, (op, b))| { let span = a.1.start..b.1.end; (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) }) + .boxed() } .labelled("atomic predicate"); - let atom = equality_op + let atom = relational_op .or(var.or(literal).map_with_span(|expr, span| (expr, span))) // Atoms can also just be normal expressions, but surrounded with parentheses .or(expr.clone().delimited_by(just(Token::LParen), just(Token::RParen))) @@ -328,28 +325,23 @@ pub fn parser<'tokens, 'src: 'tokens>( .foldr(atom, |op, rhs| { let span = op.1.start..rhs.1.end; (Expr::unary_op(op.0, Box::new(rhs), None), span.into()) - }); - - let next_op = just(Token::Next) - .map_with_span(|_, span: Span| (UnaryOps::Next, span)) - .then(interval.or_not()) - .repeated() - .foldr(not_op, |(op, interval), rhs| { - let span = op.1.start..rhs.1.end; - (Expr::unary_op(op.0, Box::new(rhs), interval), span.into()) - }); + }) + .boxed(); let unary_temporal_op = { - let op = just(Token::Eventually) - .to(UnaryOps::Eventually) - .or(just(Token::Always).to(UnaryOps::Always)); + let op = choice(( + just(Token::Next).to(UnaryOps::Next), + just(Token::Eventually).to(UnaryOps::Eventually), + just(Token::Always).to(UnaryOps::Always), + )); op.map_with_span(|op, span: Span| (op, span)) - .then(interval.or_not()) + .then(interval.clone().or_not()) .repeated() - .foldr(next_op, |(op, interval), rhs| { + .foldr(not_op, |(op, interval), rhs| { let span = op.1.start..rhs.1.end; (Expr::unary_op(op.0, Box::new(rhs), interval), span.into()) }) + .boxed() }; let binary_temporal_op = unary_temporal_op @@ -363,7 +355,8 @@ pub fn parser<'tokens, 'src: 'tokens>( Expr::binary_op(op, (Box::new(lhs), Box::new(rhs)), interval), span.into(), ) - }); + }) + .boxed(); let and_op = { let op = just(Token::And).to(BinaryOps::And); @@ -373,34 +366,44 @@ pub fn parser<'tokens, 'src: 'tokens>( let span = a.1.start..b.1.end; (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) }) + .boxed() }; let or_op = { let op = just(Token::Or).to(BinaryOps::Or); - and_op.clone().foldl(op.then(and_op).repeated(), |a, (op, b)| { - let span = a.1.start..b.1.end; - (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) - }) + and_op + .clone() + .foldl(op.then(and_op).repeated(), |a, (op, b)| { + let span = a.1.start..b.1.end; + (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) + }) + .boxed() }; let xor_op = { let op = just(Token::Xor).to(BinaryOps::Xor); - or_op.clone().foldl(op.then(or_op).repeated(), |a, (op, b)| { - let span = a.1.start..b.1.end; - (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) - }) + or_op + .clone() + .foldl(op.then(or_op).repeated(), |a, (op, b)| { + let span = a.1.start..b.1.end; + (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) + }) + .boxed() }; let implies_equiv_op = { let op = just(Token::Implies) .to(BinaryOps::Implies) .or(just(Token::Equiv).to(BinaryOps::Equiv)); - xor_op.clone().foldl(op.then(xor_op).repeated(), |a, (op, b)| { - let span = a.1.start..b.1.end; - (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) - }) + xor_op + .clone() + .foldl(op.then(xor_op).repeated(), |a, (op, b)| { + let span = a.1.start..b.1.end; + (Expr::binary_op(op, (Box::new(a), Box::new(b)), None), span.into()) + }) + .boxed() }; - implies_equiv_op.labelled("expression").as_context() + implies_equiv_op.labelled("boolean expression").as_context() }) }