diff options
Diffstat (limited to '')
-rw-r--r-- | src/parser/expr.rs | 34 | ||||
-rw-r--r-- | src/parser/mod.rs | 12 | ||||
-rw-r--r-- | src/parser/type_.rs | 2 |
3 files changed, 43 insertions, 5 deletions
diff --git a/src/parser/expr.rs b/src/parser/expr.rs index 73c873b5b304..2ec6d60cd04f 100644 --- a/src/parser/expr.rs +++ b/src/parser/expr.rs @@ -1,11 +1,14 @@ +use std::borrow::Cow; + +use nom::alt; use nom::character::complete::{digit1, multispace0, multispace1}; use nom::{ - alt, call, char, complete, delimited, do_parse, flat_map, many0, map, named, opt, parse_to, + call, char, complete, delimited, do_parse, flat_map, many0, map, named, opt, parse_to, preceded, separated_list0, separated_list1, tag, tuple, }; use pratt::{Affix, Associativity, PrattParser, Precedence}; -use crate::ast::{BinaryOperator, Binding, Expr, Fun, Ident, Literal, UnaryOperator}; +use crate::ast::{BinaryOperator, Binding, Expr, Fun, Literal, UnaryOperator}; use crate::parser::{ident, type_}; #[derive(Debug)] @@ -161,7 +164,22 @@ named!(bool_(&str) -> Literal, alt!( tag!("false") => { |_| Literal::Bool(false) } )); -named!(literal(&str) -> Literal, alt!(int | bool_)); +fn string_internal(i: &str) -> nom::IResult<&str, Cow<'_, str>, nom::error::Error<&str>> { + let (s, rem) = i + .split_once('"') + .ok_or_else(|| nom::Err::Error(nom::error::Error::new(i, nom::error::ErrorKind::Tag)))?; + Ok((rem, Cow::Borrowed(s))) +} + +named!(string(&str) -> Literal, preceded!( + char!('"'), + map!( + string_internal, + |s| Literal::String(s) + ) +)); + +named!(literal(&str) -> Literal, alt!(int | bool_ | string)); named!(literal_expr(&str) -> Expr, map!(literal, Expr::Literal)); @@ -308,7 +326,7 @@ named!(pub expr(&str) -> Expr, alt!( #[cfg(test)] pub(crate) mod tests { use super::*; - use crate::ast::Type; + use crate::ast::{Ident, Type}; use std::convert::TryFrom; use BinaryOperator::*; use Expr::{BinaryOp, If, Let, UnaryOp}; @@ -419,6 +437,14 @@ pub(crate) mod tests { } #[test] + fn simple_string_lit() { + assert_eq!( + test_parse!(expr, "\"foobar\""), + Expr::Literal(Literal::String(Cow::Borrowed("foobar"))) + ) + } + + #[test] fn let_complex() { let res = test_parse!(expr, "let x = 1; y = x * 7 in (x + y) * 4"); assert_eq!( diff --git a/src/parser/mod.rs b/src/parser/mod.rs index 0251d02df464..9ac590cee86c 100644 --- a/src/parser/mod.rs +++ b/src/parser/mod.rs @@ -16,7 +16,17 @@ pub type Error = nom::Err<nom::error::Error<String>>; pub(crate) fn is_reserved(s: &str) -> bool { matches!( s, - "if" | "then" | "else" | "let" | "in" | "fn" | "int" | "float" | "bool" | "true" | "false" + "if" | "then" + | "else" + | "let" + | "in" + | "fn" + | "int" + | "float" + | "bool" + | "true" + | "false" + | "cstring" ) } diff --git a/src/parser/type_.rs b/src/parser/type_.rs index 076df7d6bd55..66b4f9f72c23 100644 --- a/src/parser/type_.rs +++ b/src/parser/type_.rs @@ -27,6 +27,7 @@ named!(pub type_(&str) -> Type, alt!( tag!("int") => { |_| Type::Int } | tag!("float") => { |_| Type::Float } | tag!("bool") => { |_| Type::Bool } | + tag!("cstring") => { |_| Type::CString } | function_type | delimited!( tuple!(tag!("("), multispace0), @@ -44,6 +45,7 @@ mod tests { assert_eq!(test_parse!(type_, "int"), Type::Int); assert_eq!(test_parse!(type_, "float"), Type::Float); assert_eq!(test_parse!(type_, "bool"), Type::Bool); + assert_eq!(test_parse!(type_, "cstring"), Type::CString); } #[test] |