String literal

This commit is contained in:
Greg Shuflin 2021-11-18 03:16:43 -08:00
parent fc088923c0
commit 37e85c417e
2 changed files with 36 additions and 7 deletions

View File

@ -2,9 +2,9 @@ use std::{cell::RefCell, rc::Rc};
use nom::{ use nom::{
branch::alt, branch::alt,
bytes::complete::{tag, take_till}, bytes::complete::{tag, escaped_transform, take_till},
character::complete::{ character::complete::{
alpha1, alphanumeric0, char, line_ending, multispace0, none_of, not_line_ending, one_of, space0, alpha1, alphanumeric0, char, line_ending, none_of, not_line_ending, one_of, space0,
space1, space1,
}, },
combinator::{map, not, opt, peek, recognize, value}, combinator::{map, not, opt, peek, recognize, value},
@ -177,9 +177,36 @@ fn extended_expr(input: Span) -> ParseResult<ExpressionKind> {
} }
fn primary_expr(input: Span) -> ParseResult<ExpressionKind> { fn primary_expr(input: Span) -> ParseResult<ExpressionKind> {
context("primary-expr", alt((float_literal, number_literal, bool_literal, identifier_expr)))(input) context("primary-expr", alt((
string_literal, float_literal, number_literal, bool_literal, identifier_expr))
)(input)
} }
//TODO need to do something with prefix in the AST
fn string_literal(input: Span) -> ParseResult<ExpressionKind> {
tok(
map(pair(opt(identifier), bare_string_literal),
|(_maybe_prefix, s)| ExpressionKind::StringLiteral(Rc::new(s)))
)(input)
}
fn bare_string_literal(input: Span) -> ParseResult<String> {
let string_escape_transforms = alt((
value("\\", tag("\\")),
value("\"", tag("\"")),
value("\n", tag("n")),
value("\t", tag("t")),
));
alt((map(tag(r#""""#), |_| String::new()),
map(
tuple((
char('"'),
escaped_transform(none_of(r#""\"#), '\\', string_escape_transforms),
char('"'),
)), |(_, s, _)| s)))(input)
}
fn identifier_expr(input: Span) -> ParseResult<ExpressionKind> { fn identifier_expr(input: Span) -> ParseResult<ExpressionKind> {
context("identifier-expr", map(qualified_identifier, ExpressionKind::Value))(input) context("identifier-expr", map(qualified_identifier, ExpressionKind::Value))(input)
} }
@ -330,6 +357,8 @@ mod test {
fn combinator_test1() { fn combinator_test1() {
assert_eq!(span!(digits(digit_group_dec), "342"), Ok(("", vec!['3', '4', '2']))); assert_eq!(span!(digits(digit_group_dec), "342"), Ok(("", vec!['3', '4', '2'])));
assert_eq!(span!(bin_literal, "0b1111qsdf"), Ok(("qsdf", 15))); assert_eq!(span!(bin_literal, "0b1111qsdf"), Ok(("qsdf", 15)));
assert_eq!(span!(bare_string_literal, r#""fah""#), Ok(("", "fah".to_string())));
assert_eq!(span!(bare_string_literal, r#""""#), Ok(("", "".to_string())));
} }
#[test] #[test]

View File

@ -157,11 +157,11 @@ fn basic_literals() {
fn string_literals() { fn string_literals() {
use ExpressionKind::*; use ExpressionKind::*;
assert_expr!(r#""""#, expr(StringLiteral(rc("")))); assert_expr_comb!(r#""""#, expr(StringLiteral(rc(""))));
assert_expr!(r#""hello""#, expr(StringLiteral(rc("hello")))); assert_expr_comb!(r#""hello""#, expr(StringLiteral(rc("hello"))));
assert_expr!(r#"b"some bytestring""#, expr(StringLiteral(rc("some bytestring")))); assert_expr_comb!(r#"b"some bytestring""#, expr(StringLiteral(rc("some bytestring"))));
//NOTE I'm not 100% sure this case is correct, but I'll deal with it later //NOTE I'm not 100% sure this case is correct, but I'll deal with it later
assert_expr!(r#""Do \n \" escapes work\t""#, expr(StringLiteral(rc(r#"Do \n \" escapes work\t"#)))); assert_expr_comb!(r#""Do \n \" escapes work\t""#, expr(StringLiteral(rc("Do \n \" escapes work\t"))));
} }
#[test] #[test]