diff --git a/src/parser.rs b/src/parser.rs index 727d059..149d985 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,7 +1,7 @@ use chumsky::prelude::*; use chumsky::text::Character; -use crate::ast::{Ident, NumLit, NumLitStr, Space}; +use crate::ast::{Expr, Ident, Lit, NumLit, NumLitStr, Space, StringLit, TableLit, TableLitElem}; use crate::span::Span; type Error = Simple; @@ -21,7 +21,7 @@ fn ident() -> impl Parser { text::ident().map_with_span(|name, span| Ident { name, span }) } -fn num_lit_str_radix(radix: u32) -> impl Parser { +fn num_lit_str_radix(radix: u32) -> impl Parser + Clone { // Minimum amount of digits required to represent i64::MAX. The rest of this // code assumes that any value that can be represented using this amount of // digits fits into an u64. @@ -71,13 +71,63 @@ fn num_lit_str_radix(radix: u32) -> impl Parser impl Parser { +fn num_lit() -> impl Parser + Clone { (just("0b").ignore_then(num_lit_str_radix(2))) .or(just("0x").ignore_then(num_lit_str_radix(16))) .or(num_lit_str_radix(10)) .map_with_span(|(value, str), span| NumLit { value, str, span }) } -pub fn parser() -> impl Parser { - num_lit().padded().then_ignore(end()) +fn string_lit() -> impl Parser { + // TODO Parse string literals + filter(|_| false).to(unreachable!()) +} + +fn table_lit_elem( + expr: impl Parser + Clone, +) -> impl Parser { + let positional = expr + .clone() + .map(|value| TableLitElem::Positional(Box::new(value))); + + let named = ident() + .then(space()) + .then_ignore(just(':')) + .then(space()) + .then(expr) + .map(|(((name, s0), s1), value)| TableLitElem::Named { + name, + s0, + s1, + value: Box::new(value), + }); + + positional.or(named) +} + +fn table_lit( + expr: impl Parser + Clone, +) -> impl Parser { + let elem = space() + .then(table_lit_elem(expr)) + .then(space()) + .map(|((s0, elem), s1)| (s0, elem, s1)); + + let trailing_comma = just(",").ignore_then(space()).or_not(); + + let elems = elem.separated_by(just(",")).then(trailing_comma); + + just("'{") + .ignore_then(elems) + .then_ignore(just("}")) + .map_with_span(|(elems, trailing_comma), span| TableLit { + elems, + trailing_comma, + span, + }) +} + +pub fn parser() -> impl Parser { + let expr = num_lit().map(|n| Expr::Lit(Lit::Num(n))); + table_lit(expr).padded().then_ignore(end()) }