Parse string literals

This commit is contained in:
Joscha 2022-11-20 17:28:04 +01:00
parent 867595b5b9
commit 82e5b589e1
2 changed files with 41 additions and 7 deletions

View file

@ -61,8 +61,6 @@ pub enum StringLitElem {
Unicode(char), Unicode(char),
/// `\\` /// `\\`
Backslash, Backslash,
/// `\'`
SingleQuote,
/// `\"'` /// `\"'`
DoubleQuote, DoubleQuote,
/// `\t` /// `\t`
@ -77,8 +75,8 @@ pub enum StringLitElem {
/// - `""` /// - `""`
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct StringLit { pub struct StringLit {
elems: Vec<StringLitElem>, pub elems: Vec<StringLitElem>,
span: Span, pub span: Span,
} }
impl HasSpan for StringLit { impl HasSpan for StringLit {

View file

@ -2,7 +2,9 @@
use chumsky::prelude::*; use chumsky::prelude::*;
use crate::ast::{Expr, Ident, Lit, NumLit, NumLitStr, Space, StringLit, TableLit, TableLitElem}; use crate::ast::{
Expr, Ident, Lit, NumLit, NumLitStr, Space, StringLit, StringLitElem, TableLit, TableLitElem,
};
use crate::builtin::Builtin; use crate::builtin::Builtin;
use super::basic::{EParser, Error}; use super::basic::{EParser, Error};
@ -78,9 +80,43 @@ fn num_lit() -> impl Parser<char, NumLit, Error = Error> {
.map_with_span(|(value, str), span| NumLit { value, str, span }) .map_with_span(|(value, str), span| NumLit { value, str, span })
} }
fn string_lit_elem() -> impl Parser<char, StringLitElem, Error = Error> {
let plain = filter(|c: &char| !matches!(c, '"' | '\\'))
.repeated()
.at_least(1)
.collect::<String>()
.map(StringLitElem::Plain);
let unicode_char = num_lit_str_radix(16).try_map(|(n, _), span| {
let msg = "not a valid unicode code point";
let n: u32 = n.try_into().map_err(|_| Simple::custom(span, msg))?;
let c: char = n.try_into().map_err(|_| Simple::custom(span, msg))?;
Ok(c)
});
let unicode = just("\\u{")
.ignore_then(unicode_char)
.then_ignore(just('}'))
.map(StringLitElem::Unicode);
let backslash = just("\\\\").to(StringLitElem::Backslash);
let double_quote = just("\\\"").to(StringLitElem::DoubleQuote);
let tab = just("\\t").to(StringLitElem::Tab);
let carriage_return = just("\\r").to(StringLitElem::CarriageReturn);
let newline = just("\\n").to(StringLitElem::Newline);
plain
.or(unicode)
.or(backslash)
.or(double_quote)
.or(tab)
.or(carriage_return)
.or(newline)
}
fn string_lit() -> impl Parser<char, StringLit, Error = Error> { fn string_lit() -> impl Parser<char, StringLit, Error = Error> {
// TODO Parse string literals string_lit_elem()
filter(|_| false).map(|_| unreachable!()) .repeated()
.delimited_by(just('"'), just('"'))
.map_with_span(|elems, span| StringLit { elems, span })
} }
pub fn table_lit_elem( pub fn table_lit_elem(