Parse general s-expressions
authorCaleb Jones <code@calebjones.net>
Sun, 25 Dec 2016 02:33:47 +0000 (21:33 -0500)
committerCaleb Jones <code@calebjones.net>
Sun, 25 Dec 2016 02:33:47 +0000 (21:33 -0500)
src/lib.rs

index 011d9fbb97c4d18aa3a23f36473e66201e000495..11dfc187514219427b533034f248b28fa8ae3aec 100644 (file)
@@ -126,9 +126,27 @@ impl IsDelimeter for char {
 \f
 // Parsers /////////////////////////////////////////////////////////////////////
 
-// pub fn parse_one(input: &str) -> Result<Sexp, ParseError>;
+pub fn parse_sexp(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
+    let end_of_white = if let Some(pos) = input.find(|c: char| !c.is_whitespace()) {
+        pos
+    } else {
+        return Error(ParseError::Number(
+            Box::new(ParseError::UnexpectedEof),
+            (input.len(), input.len()).offset(start_loc)));
+    };
 
-// pub fn parse(input: &str) -> Result<Vec<Sexp>, ParseError>;
+    let input = &input[end_of_white..];
+    let start_loc = start_loc + end_of_white;
+
+    match input.chars().next() {
+        Some('0'...'9') => parse_number(input, start_loc),
+        Some('(') => unimplemented!(),
+        Some('#') => parse_character(input, start_loc),
+        Some('"') => parse_string(input, start_loc),
+        Some(_) => parse_symbol(input, start_loc),
+        None => unreachable!(),
+    }
+}
 
 pub fn parse_number(input: &str, start_loc: usize) -> ParseResult<Sexp, ParseError> {
     // Consume all the whitespace at the beginning of the string
@@ -329,6 +347,15 @@ mod test {
     use super::*;
     use super::ParseResult::*;
 
+    #[test]
+    fn test_parse_sexp() {
+        assert_eq!(parse_sexp("        1", 0), Done("", Sexp::Int(1, (1, 2))));
+        assert_eq!(parse_sexp("2.2", 0), Done("", Sexp::Float(2.2, (0, 3))));
+        assert_eq!(parse_sexp(" a", 0), Done("", Sexp::Sym("a".into(), (1, 2))));
+        assert_eq!(parse_sexp("#\\c", 0), Done("", Sexp::Char('c', (0, 3))));
+        assert_eq!(parse_sexp(r#""hi""#, 0), Done("", Sexp::Str("hi".into(), (0, 4))));
+    }
+
     #[test]
     fn test_parse_number() {
         assert_eq!(parse_number("1", 0), Done("", Sexp::Int(1, (0, 1))));