Parse table literals
This commit is contained in:
parent
7f0f886fb7
commit
5b24bd7b79
2 changed files with 42 additions and 15 deletions
|
|
@ -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 }`
|
||||||
|
|
|
||||||
|
|
@ -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())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue