Browse Source

support non-latin scripts and tuples

Getty Ritter 2 years ago
parent
commit
33742abba5
4 changed files with 29 additions and 6 deletions
  1. 1 2
      examples/aquan.matzo
  2. 5 4
      src/grammar.lalrpop
  3. 22 0
      src/interp.rs
  4. 1 0
      src/main.rs

+ 1 - 2
examples/aquan.matzo

@@ -1,7 +1,6 @@
 (* Below is a literal assignment, which is
  * identical to cons := "p"| "t" | "k" | "w" | "h" | "n"; *)
-(* cons ::= p t k w h n; *)
-cons := 'p'| 't' | 'k' | 'w' | 'h' | 'n';
+cons ::= p t k w h n;
 
 (* And this could also be done with two rules and a literal
  * assignment *)

+ 5 - 4
src/grammar.lalrpop

@@ -20,8 +20,8 @@ match {
     "case",
     "let",
     "in",
-    r"[a-z][A-Za-z0-9_-]*",
-    r"[A-Z][A-Za-z0-9_-]*",
+    r"\p{Ll}(\pL|[0-9_-])*",
+    r"\p{Lu}(\pL|[0-9_-])*",
     r"[0-9]+",
     r"'([^'\\]|\\.)*'",
     r"\s*" => {},
@@ -43,10 +43,11 @@ pub Stmts: Vec<Stmt> = {
 pub Stmt: Stmt = {
     "puts" <Expr> => Stmt::Puts(<>),
     <Name> ":=" <Expr> => Stmt::Assn(<>),
+    <name:Name> "::=" <strs:(<Name>)*> => Stmt::LitAssn(name, strs),
 };
 
 pub Name: String = {
-    r"[a-z][A-Za-z0-9_-]*" => <>.to_owned(),
+    r"\p{Ll}(\pL|[0-9_-])*" => <>.to_owned(),
 };
 
 pub Expr: Expr = {
@@ -95,5 +96,5 @@ 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()),
+    r"\p{Lu}(\pL|[0-9_-])*" => Literal::Atom(<>.to_owned()),
 };

+ 22 - 0
src/interp.rs

@@ -5,6 +5,7 @@ use std::collections::HashMap;
 #[derive(Debug)]
 pub enum Value {
     Lit(Literal),
+    Tup(Vec<Value>),
 }
 
 impl Value {
@@ -13,6 +14,18 @@ impl Value {
             Value::Lit(Literal::Str(s)) => s.clone(),
             Value::Lit(Literal::Atom(s)) => s.clone(),
             Value::Lit(Literal::Num(n)) => format!("{}", n),
+            Value::Tup(values) => {
+                let mut buf = String::new();
+                buf.push_str("<");
+                for (i, val) in values.iter().enumerate() {
+                    if i > 0 {
+                        buf.push_str(", ");
+                    }
+                    buf.push_str(&val.to_string());
+                }
+                buf.push_str(">");
+                buf
+            }
         }
     }
 }
@@ -39,6 +52,13 @@ impl State {
             Stmt::Assn(name, expr) => {
                 self.scope.insert(name.to_string(), expr.clone());
             }
+            Stmt::LitAssn(name, strs) => {
+                let choices = strs.iter().map(|s| Choice {
+                    weight: None,
+                    value: Expr::Lit(Literal::Str(s.clone())),
+                }).collect();
+                self.scope.insert(name.to_string(), Expr::Chc(choices));
+            }
             _ => panic!("unimplemented"),
         }
     }
@@ -73,6 +93,8 @@ impl State {
                     self.choose(choices)
                 }
             }
+            Expr::Tup(values) =>
+                Value::Tup(values.iter().map(|v| self.eval(v)).collect()),
             _ => panic!("unimplemented: {:?}", expr),
         }
     }

+ 1 - 0
src/main.rs

@@ -23,6 +23,7 @@ fn run_repl() -> std::io::Result<()> {
         stdout.flush()?;
         buf.clear();
         stdin.read_line(&mut buf)?;
+
         let stmts = match parser.parse(&buf) {
             Ok(stmts) => stmts,
             Err(err) => {