diff options
| author | bnewbold <bnewbold@robocracy.org> | 2016-04-21 16:51:11 -0400 | 
|---|---|---|
| committer | bnewbold <bnewbold@robocracy.org> | 2016-04-21 16:51:11 -0400 | 
| commit | 115ba20ce23d5917b5b88384c53509fd04a96512 (patch) | |
| tree | 9404309df112c5821bd0b174bbb02f1cf466a9dc | |
| parent | 010656f9ce275d12d8d6520d2443fa6d1d6e3b13 (diff) | |
| download | spectrum-115ba20ce23d5917b5b88384c53509fd04a96512.tar.gz spectrum-115ba20ce23d5917b5b88384c53509fd04a96512.zip  | |
rust: fix symbols by adding identifiers, and handle comments
| -rw-r--r-- | rust/spectrum.rs | 33 | 
1 files changed, 27 insertions, 6 deletions
diff --git a/rust/spectrum.rs b/rust/spectrum.rs index 8a82a33..317dce2 100644 --- a/rust/spectrum.rs +++ b/rust/spectrum.rs @@ -27,6 +27,7 @@ enum SchemeExpr<'a> {      SchemeNum(f64),      SchemeBuiltin(&'a str),      SchemeSymbol(&'a str), +    SchemeIdentifier(&'a str),      SchemeStr(&'a str),      SchemeProcedure(          Vec<&'a str>, @@ -41,17 +42,21 @@ enum SchemeExpr<'a> {  fn is_scheme_whitespace(c: char) -> bool{      " \r\n".find(c) != None  } +  fn is_scheme_sep(c: char) -> bool {      "()".find(c) != None  } -fn is_valid_symbol(s: &str) -> bool { +fn is_valid_identifier(s: &str) -> bool {      // TODO: this could be an 'any' or 'filter' call?      if s.len() == 0 {          return false;      } +    if s.starts_with("-") || s.ends_with("-") { +        return false; +    }      for c in s.chars() { -        if !c.is_alphabetic() && c != '-' { +        if !(c.is_alphabetic() || c == '-') {              return false;          }      } @@ -63,6 +68,7 @@ fn scheme_tokenize<'a>(raw_str: &'a str) -> Result<Vec<&'a str>, &'static str> {      let mut ret = Vec::<&str>::new();      let mut food: usize = 0;      let mut quoted: bool = false; +    let mut commented: bool = false;      for (i, c) in raw_str.chars().enumerate() {          if quoted {              if c == '"' && raw_str.chars().collect::<Vec<char>>()[i-1] != '\\' { @@ -74,6 +80,14 @@ fn scheme_tokenize<'a>(raw_str: &'a str) -> Result<Vec<&'a str>, &'static str> {              } else {                  food += 1;              } +        } else if commented { +            food = 0; +            if c == '\n' { +                commented = false; +            } +        } else if c == ';' { +            commented = true; +            food = 0;          } else if c == '"' {              if food > 0 {                  return Err("unexpected quote char"); @@ -125,11 +139,16 @@ fn scheme_parse_token(token: &str) -> Result<SchemeExpr, &'static str> {          return Ok(SchemeExpr::SchemeStr(token));      } -    // If it's all alphas, must be a symbol -    if is_valid_symbol(token) { +    // Is it a symbol? +    if token.starts_with("'") && is_valid_identifier(&token[1..]) {          return Ok(SchemeExpr::SchemeSymbol(token));      } +    // Else, we'll treat it as an identifier +    if is_valid_identifier(token) { +        return Ok(SchemeExpr::SchemeIdentifier(token)); +    } +      return Err("unparsable token");  } @@ -180,6 +199,7 @@ fn scheme_repr(ast: &SchemeExpr) -> Result<String, &'static str> {          &SchemeExpr::SchemeBuiltin(b)=> Ok(b.to_string()),          &SchemeExpr::SchemeStr(s)=> Ok(s.to_string()),          &SchemeExpr::SchemeSymbol(s)=> Ok(s.to_string()), +        &SchemeExpr::SchemeIdentifier(s)=> Ok("'".to_string() + s),          &SchemeExpr::SchemeProcedure(ref binds, ref body, _) => {              let mut ret = "(lambda (".to_string();              for bind in binds { @@ -253,7 +273,7 @@ fn lambda_action<'a>(list: &Vec<SchemeExpr<'a>>, ctx: HashMap<&'a str, SchemeExp      };      for bind in bind_list {          match bind { -            &SchemeExpr::SchemeSymbol(name) => +            &SchemeExpr::SchemeIdentifier(name) =>                  binds.push(name),              _ => return Err("lambda binds must all be non-builtin symbols")          } @@ -399,12 +419,13 @@ fn scheme_meaning<'a>(ast: &SchemeExpr<'a>, ctx: HashMap<&'a str, SchemeExpr<'a>          &SchemeExpr::SchemeFalse        => Ok(ast.clone()),          &SchemeExpr::SchemeNull         => Ok(ast.clone()),          &SchemeExpr::SchemeStr(_)       => Ok(ast.clone()), +        &SchemeExpr::SchemeSymbol(_)    => Ok(ast.clone()),          &SchemeExpr::SchemeNum(_)       => Ok(ast.clone()),          &SchemeExpr::SchemeBuiltin(_)   => Ok(ast.clone()),          &SchemeExpr::SchemeProcedure(_, _, _) => Ok(ast.clone()),          &SchemeExpr::SchemeQuote(ref list)                                          => Ok(SchemeExpr::SchemeList(list.clone())), -        &SchemeExpr::SchemeSymbol(sym)  => match ctx.get(sym) { +        &SchemeExpr::SchemeIdentifier(sym)  => match ctx.get(sym) {              // the "lookup action"              Some(val) => Ok(val.clone()),              None => Err("symbol not defined"),  | 
