Browse Source

understand basic string literals

Getty Ritter 2 years ago
parent
commit
6bb1f6b1dc
4 changed files with 108 additions and 0 deletions
  1. 22 0
      src/ast.rs
  2. 2 0
      src/grammar.lalrpop
  3. 10 0
      tests/str_lit.matzo
  4. 74 0
      tests/str_lit.parsed

+ 22 - 0
src/ast.rs

@@ -47,3 +47,25 @@ pub enum Literal {
     Atom(String),
     Num(i64),
 }
+
+impl Literal {
+    pub fn from_str_literal(s: &str) -> Literal {
+        // strip the outer pieces from the string
+        let mut buf = String::new();
+        let mut src = s[1..s.len() - 1].chars().into_iter();
+        while let Some(c) = src.next() {
+            if c == '\\' {
+                match src.next() {
+                    Some('n') => buf.push('\n'),
+                    Some('t') => buf.push('\t'),
+                    Some('r') => buf.push('\r'),
+                    Some(c) => buf.push(c),
+                    None => panic!("bad escape"),
+                }
+            } else {
+                buf.push(c);
+            }
+        }
+        Literal::Str(buf)
+    }
+}

+ 2 - 0
src/grammar.lalrpop

@@ -22,6 +22,7 @@ match {
     r"[a-z][A-Za-z0-9_-]*",
     r"[A-Z][A-Za-z0-9_-]*",
     r"[0-9]+",
+    r"'([^'\\]|\\.)*'",
     r"\s*" => {},
     r"\(\*([^*]|\*[^)])*\*\)" => {},
 }
@@ -87,5 +88,6 @@ pub Num: i64 = {
 
 pub Literal: Literal = {
     <Num> => Literal::Num(<>),
+    r"'([^'\\]|\\.)*'" => Literal::from_str_literal(<>),
     r"[A-Z][A-Za-z0-9_-]*" => Literal::Atom(<>.to_owned()),
 };

+ 10 - 0
tests/str_lit.matzo

@@ -0,0 +1,10 @@
+(* basic string literals *)
+puts 'foo';
+(* string literals with spaces *)
+puts 'foo bar baz';
+
+(* string literals with escaped quotes *)
+puts 'won\'t you';
+
+(* string literals with escaped newlines *)
+puts 'this\nthat';

+ 74 - 0
tests/str_lit.parsed

@@ -0,0 +1,74 @@
+[
+    Puts(
+        Chc(
+            [
+                Choice {
+                    weight: None,
+                    value: Cat(
+                        [
+                            Lit(
+                                Str(
+                                    "foo",
+                                ),
+                            ),
+                        ],
+                    ),
+                },
+            ],
+        ),
+    ),
+    Puts(
+        Chc(
+            [
+                Choice {
+                    weight: None,
+                    value: Cat(
+                        [
+                            Lit(
+                                Str(
+                                    "foo bar baz",
+                                ),
+                            ),
+                        ],
+                    ),
+                },
+            ],
+        ),
+    ),
+    Puts(
+        Chc(
+            [
+                Choice {
+                    weight: None,
+                    value: Cat(
+                        [
+                            Lit(
+                                Str(
+                                    "won't you",
+                                ),
+                            ),
+                        ],
+                    ),
+                },
+            ],
+        ),
+    ),
+    Puts(
+        Chc(
+            [
+                Choice {
+                    weight: None,
+                    value: Cat(
+                        [
+                            Lit(
+                                Str(
+                                    "this\nthat",
+                                ),
+                            ),
+                        ],
+                    ),
+                },
+            ],
+        ),
+    ),
+]