Parse table literals

This commit is contained in:
Joscha 2022-11-17 18:20:44 +01:00
parent 7f0f886fb7
commit 5b24bd7b79
2 changed files with 42 additions and 15 deletions

View file

@ -27,12 +27,6 @@ pub enum TableLitElem {
/// `foo: a` /// `foo: a`
Named(Ident, Box<Expr>), Named(Ident, Box<Expr>),
/// ```text
/// # foo
/// # bar
/// ```
BlockString(Vec<String>),
} }
/// `'{ a, foo: b }` /// `'{ a, foo: b }`

View file

@ -1,16 +1,16 @@
use chumsky::prelude::*; use chumsky::prelude::*;
use chumsky::text::Character; use chumsky::text::Character;
use crate::ast::{Ident, NumLit}; use crate::ast::{Expr, Ident, Lit, NumLit, TableLit, TableLitElem};
fn ident() -> impl Parser<char, Ident, Error = Simple<char>> { fn ident() -> impl Parser<char, Ident, Error = Simple<char>> {
text::ident().map(Ident) text::ident().padded().map(Ident)
} }
fn num_lit_radix_digits( fn num_lit_radix_digits(
radix: u32, radix: u32,
max_digits: usize, max_digits: usize,
) -> impl Parser<char, (i64, String), Error = Simple<char>> { ) -> impl Parser<char, (i64, String), Error = Simple<char>> + Clone {
filter(move |c: &char| c.is_digit(radix) || *c == '_') filter(move |c: &char| c.is_digit(radix) || *c == '_')
.repeated() .repeated()
.at_least(1) .at_least(1)
@ -28,7 +28,7 @@ fn num_lit_radix_digits(
}) })
} }
fn num_lit_bin_digits() -> impl Parser<char, (i64, String), Error = Simple<char>> { fn num_lit_bin_digits() -> impl Parser<char, (i64, String), Error = Simple<char>> + Clone {
// u64::MAX in binary is 0b_1111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111 // u64::MAX in binary is 0b_1111111_11111111_11111111_11111111_11111111_11111111_11111111_11111111
// 63 digits are necessary to represent the full range. // 63 digits are necessary to represent the full range.
const MAX_BIN_DIGITS: usize = 63; const MAX_BIN_DIGITS: usize = 63;
@ -36,7 +36,7 @@ fn num_lit_bin_digits() -> impl Parser<char, (i64, String), Error = Simple<char>
just("0b").ignore_then(num_lit_radix_digits(2, MAX_BIN_DIGITS)) just("0b").ignore_then(num_lit_radix_digits(2, MAX_BIN_DIGITS))
} }
fn num_lit_dec_digits() -> impl Parser<char, (i64, String), Error = Simple<char>> { fn num_lit_dec_digits() -> impl Parser<char, (i64, String), Error = Simple<char>> + Clone {
// u64::MAX in decimal is 9_223_372_036_854_775_807 // u64::MAX in decimal is 9_223_372_036_854_775_807
// 19 digits are necessary to represent the full range. // 19 digits are necessary to represent the full range.
const MAX_DEC_DIGITS: usize = 19; const MAX_DEC_DIGITS: usize = 19;
@ -44,7 +44,7 @@ fn num_lit_dec_digits() -> impl Parser<char, (i64, String), Error = Simple<char>
num_lit_radix_digits(10, MAX_DEC_DIGITS) num_lit_radix_digits(10, MAX_DEC_DIGITS)
} }
fn num_lit_hex_digits() -> impl Parser<char, (i64, String), Error = Simple<char>> { fn num_lit_hex_digits() -> impl Parser<char, (i64, String), Error = Simple<char>> + Clone {
// u64::MAX in hexadecimal is 0x_7fff_ffff_ffff_ffff // u64::MAX in hexadecimal is 0x_7fff_ffff_ffff_ffff
// 16 digits are necessary to represent the full range. // 16 digits are necessary to represent the full range.
const MAX_HEX_DIGITS: usize = 16; const MAX_HEX_DIGITS: usize = 16;
@ -52,12 +52,45 @@ fn num_lit_hex_digits() -> impl Parser<char, (i64, String), Error = Simple<char>
just("0x").ignore_then(num_lit_radix_digits(16, MAX_HEX_DIGITS)) just("0x").ignore_then(num_lit_radix_digits(16, MAX_HEX_DIGITS))
} }
fn num_lit() -> impl Parser<char, NumLit, Error = Simple<char>> { fn num_lit() -> impl Parser<char, NumLit, Error = Simple<char>> + Clone {
(num_lit_bin_digits().map(|(num, text)| NumLit::Bin(num, text))) (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_hex_digits().map(|(num, text)| NumLit::Hex(num, text)))
.or(num_lit_dec_digits().map(|(num, text)| NumLit::Dec(num, text))) .or(num_lit_dec_digits().map(|(num, text)| NumLit::Dec(num, text)))
.padded()
} }
pub fn parser() -> impl Parser<char, NumLit, Error = Simple<char>> { fn table_lit_elems(
num_lit().padded().then_ignore(end()) expr: impl Parser<char, Expr, Error = Simple<char>> + Clone,
) -> impl Parser<char, (Vec<TableLitElem>, bool), Error = Simple<char>> {
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<char, Expr, Error = Simple<char>> + Clone,
) -> impl Parser<char, TableLit, Error = Simple<char>> {
just("'{")
.ignore_then(table_lit_elems(expr))
.then_ignore(just("}"))
.padded()
.map(|(elems, trailing_comma)| TableLit {
elems,
trailing_comma,
})
}
pub fn parser() -> impl Parser<char, TableLit, Error = Simple<char>> {
let expr = num_lit().map(|num| Expr::Lit(Lit::Num(num)));
table_lit(expr).then_ignore(end())
} }