about summary refs log tree commit diff
path: root/src/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/parser')
-rw-r--r--src/parser/expr.rs34
-rw-r--r--src/parser/mod.rs12
-rw-r--r--src/parser/type_.rs2
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]