summary refs log tree commit diff
diff options
context:
space:
mode:
authorIrene Knapp <ireneista@gmail.com>2020-09-15 20:22:35 -0700
committerIrene Knapp <ireneista@gmail.com>2020-09-15 20:22:35 -0700
commitcca86b496e00605163e96d93cda4b9b248df91fe (patch)
tree3797c1c9ed3072383d7d70179140fe4f4409dac9
parent320664d6b82229a4a07fa8045dd93f260ca61308 (diff)
Use lalrpop in a trivial way as a proof of concept. Mess with some Unicode character classes.
-rw-r--r--src/commandline.lalrpop16
-rw-r--r--src/error.rs15
-rw-r--r--src/main.rs11
3 files changed, 40 insertions, 2 deletions
diff --git a/src/commandline.lalrpop b/src/commandline.lalrpop
new file mode 100644
index 0000000..0655281
--- /dev/null
+++ b/src/commandline.lalrpop
@@ -0,0 +1,16 @@
+grammar;
+
+//
+// Z is the unicode class for separators, including line, paragraph, and space
+// separators. C is the class for control characters. P is the class for
+// punctuation. This regexp tests for the intersection of the negation of these
+// character classes, which is any character NOT in one of these three classes.
+//
+// [1] is the official reference, and [2] is a site that is useful for browsing
+// to get an intuitive idea of what these classes mean.
+//
+// [1] http://www.unicode.org/reports/tr44/#General_Category_Values
+// [2] https://www.compart.com/en/unicode/category
+//
+pub Filename: String = <filename:r"[\P{Z}&&\P{C}&&\P{P}]+"> => filename.to_string();
+
diff --git a/src/error.rs b/src/error.rs
index aa9e9d6..96be297 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -1,6 +1,10 @@
+type ParseError<'a> =
+    lalrpop_util::ParseError<usize, lalrpop_util::lexer::Token<'a>, &'a str>;
+
 #[derive(Debug)]
 pub enum Error {
     IO(std::io::Error),
+    Parse(String),
 }
 
 impl std::error::Error for Error { }
@@ -9,6 +13,7 @@ impl std::fmt::Display for Error {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
             Error::IO(e) => e.fmt(f),
+            Error::Parse(e) => e.fmt(f),
         }
     }
 }
@@ -18,6 +23,9 @@ impl std::cmp::PartialEq for Error {
         match (self, other) {
             (Error::IO(_), Error::IO(_)) =>
                 false,
+            (Error::Parse(_), Error::Parse(_)) =>
+                false,
+            _  => false,
         }
     }
 }
@@ -27,3 +35,10 @@ impl From<std::io::Error> for Error {
         Error::IO(e)
     }
 }
+
+impl From<ParseError<'_>> for Error {
+    fn from(e: ParseError<'_>) -> Error {
+        Error::Parse(format!("{}", e))
+    }
+}
+
diff --git a/src/main.rs b/src/main.rs
index e176dc0..816ed49 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,6 +4,10 @@ use error::Error;
 use std::io;
 use std::io::prelude::*;
 
+#[macro_use] extern crate lalrpop_util;
+
+lalrpop_mod!(pub commandline);
+
 
 pub type Result<T> = std::result::Result<T, Error>;
 
@@ -33,7 +37,7 @@ fn repl() -> Result<()> {
 
         let input = read()?;
         match input {
-            Input::String(string) => execute(string)?,
+            Input::String(string) => execute(&string)?,
             Input::End => break,
         }
     }
@@ -62,8 +66,11 @@ fn read() -> Result<Input> {
 }
 
 
-fn execute(input: String) -> Result<()> {
+fn execute(input: &str) -> Result<()> {
+    let filename = commandline::FilenameParser::new().parse(input)?;
+
     println!("{}", input);
+    println!("filename '{}'", filename);
 
     Ok(())
 }