diff --git a/src/ast.rs b/src/ast.rs index 8617d5e..a786160 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -27,12 +27,6 @@ pub enum TableLitElem { /// `foo: a` Named(Ident, Box), - - /// ```text - /// # foo - /// # bar - /// ``` - BlockString(Vec), } /// `'{ a, foo: b }` diff --git a/src/parser.rs b/src/parser.rs index 36b8bd0..2089425 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,16 +1,16 @@ use chumsky::prelude::*; use chumsky::text::Character; -use crate::ast::{Ident, NumLit}; +use crate::ast::{Expr, Ident, Lit, NumLit, TableLit, TableLitElem}; fn ident() -> impl Parser> { - text::ident().map(Ident) + text::ident().padded().map(Ident) } fn num_lit_radix_digits( radix: u32, max_digits: usize, -) -> impl Parser> { +) -> impl Parser> + Clone { filter(move |c: &char| c.is_digit(radix) || *c == '_') .repeated() .at_least(1) @@ -28,7 +28,7 @@ fn num_lit_radix_digits( }) } -fn num_lit_bin_digits() -> impl Parser> { +fn num_lit_bin_digits() -> impl Parser> + Clone { // u64::MAX in binary is 0b_1111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111 // 63 digits are necessary to represent the full range. const MAX_BIN_DIGITS: usize = 63; @@ -36,7 +36,7 @@ fn num_lit_bin_digits() -> impl Parser just("0b").ignore_then(num_lit_radix_digits(2, MAX_BIN_DIGITS)) } -fn num_lit_dec_digits() -> impl Parser> { +fn num_lit_dec_digits() -> impl Parser> + Clone { // u64::MAX in decimal is 9_223_372_036_854_775_807 // 19 digits are necessary to represent the full range. const MAX_DEC_DIGITS: usize = 19; @@ -44,7 +44,7 @@ fn num_lit_dec_digits() -> impl Parser num_lit_radix_digits(10, MAX_DEC_DIGITS) } -fn num_lit_hex_digits() -> impl Parser> { +fn num_lit_hex_digits() -> impl Parser> + Clone { // u64::MAX in hexadecimal is 0x_7fff_ffff_ffff_ffff // 16 digits are necessary to represent the full range. const MAX_HEX_DIGITS: usize = 16; @@ -52,12 +52,45 @@ fn num_lit_hex_digits() -> impl Parser just("0x").ignore_then(num_lit_radix_digits(16, MAX_HEX_DIGITS)) } -fn num_lit() -> impl Parser> { +fn num_lit() -> impl Parser> + Clone { (num_lit_bin_digits().map(|(num, text)| NumLit::Bin(num, text))) .or(num_lit_hex_digits().map(|(num, text)| NumLit::Hex(num, text))) .or(num_lit_dec_digits().map(|(num, text)| NumLit::Dec(num, text))) + .padded() } -pub fn parser() -> impl Parser> { - num_lit().padded().then_ignore(end()) +fn table_lit_elems( + expr: impl Parser> + Clone, +) -> impl Parser, bool), Error = Simple> { + let positional = expr.clone().map(|e| TableLitElem::Positional(Box::new(e))); + let named = ident() + .then_ignore(just(":")) + .then(expr) + .map(|(n, e)| TableLitElem::Named(n, Box::new(e))); + + let trailing_comma = just(',').or_not().map(|o| o.is_some()); + + positional + .or(named) + .separated_by(just(',')) + .then(trailing_comma) + .padded() +} + +fn table_lit( + expr: impl Parser> + Clone, +) -> impl Parser> { + just("'{") + .ignore_then(table_lit_elems(expr)) + .then_ignore(just("}")) + .padded() + .map(|(elems, trailing_comma)| TableLit { + elems, + trailing_comma, + }) +} + +pub fn parser() -> impl Parser> { + let expr = num_lit().map(|num| Expr::Lit(Lit::Num(num))); + table_lit(expr).then_ignore(end()) }