diff --git a/doc/grammar.bnf b/doc/grammar.bnf index 5239a3a..e51e5fb 100644 --- a/doc/grammar.bnf +++ b/doc/grammar.bnf @@ -17,5 +17,6 @@ BUILTIN ::= | float | int | string +| symbol ARRAY ::= osquare EXPR* csquare diff --git a/src/ast/lexer.rs b/src/ast/lexer.rs index 384c974..947f668 100644 --- a/src/ast/lexer.rs +++ b/src/ast/lexer.rs @@ -155,6 +155,33 @@ impl Lexer { None } + fn scan_symbol(&self) -> Option { + let mut value = String::from(""); + let offset = 1; + + if let Some('\'') = self.text.chars().nth(self.cursor) { + } else { + return None; + } + + for c in self.text.chars().skip(self.cursor + offset) { + if c.is_whitespace() || c == ';' { + break; + } + + value.push(c); + } + + if value.len() > 0 { + Some(Token { + position: self.cursor + offset + value.len(), + value + }) + } else { + None + } + } + fn scan_int(&self) -> Option { let mut value = String::from(""); @@ -369,6 +396,12 @@ impl Iterator for Lexer { } } + if let Some(token) = self.scan_symbol() { + self.cursor = token.position; + return Some(Contextual(Node::Symbol(token.value.clone()), + Context(self.line))) + } + if let Some(token) = self.scan_identifier() { self.cursor = token.position; return Some(Contextual(Node::Ident(token.value.clone()), @@ -401,7 +434,7 @@ mod test { } return Err(error::AstError { - msg: format!("unknown symbol <{}>", val), + msg: format!("unknown text <{}>", val), line: lexer.line }); } @@ -519,6 +552,29 @@ mod test { Ok(()) } + #[test] + fn test_symbols() -> Result<(), error::AstError> { + let mut lex = Lexer::new(); + + let res = lexer_run(&mut lex, + " 'abc '+-*/ 'a; ")?; + + assert_eq!(4, res.len()); + + assert_eq!(Node::Symbol(String::from("abc")), + res.get(0).unwrap().0); + + assert_eq!(Node::Symbol(String::from("+-*/")), + res.get(1).unwrap().0); + + assert_eq!(Node::Symbol(String::from("a")), + res.get(2).unwrap().0); + + assert_eq!(Node::Semicolon, res.get(3).unwrap().0); + + Ok(()) + } + #[test] fn test_variables() -> Result<(), error::AstError> { let mut lex = Lexer::new(); diff --git a/src/ast/node.rs b/src/ast/node.rs index 47df0f8..52fa226 100644 --- a/src/ast/node.rs +++ b/src/ast/node.rs @@ -8,6 +8,7 @@ pub enum Node { Int(i32), Float(f64), String(String), + Symbol(String), OSquare, CSquare, Array(Vec>), diff --git a/src/ast/parser.rs b/src/ast/parser.rs index 2bc8b22..5ed866a 100644 --- a/src/ast/parser.rs +++ b/src/ast/parser.rs @@ -176,6 +176,10 @@ impl Parser { Contextual(Node::String(value), ctx) => Ok(Some(Contextual(Node::String(value), ctx))), + + Contextual(Node::Symbol(value), ctx) + => Ok(Some(Contextual(Node::Symbol(value), ctx))), + _ => { Err(error::AstError { msg: String::from(format!("unexpected {:?}", node)), @@ -279,11 +283,25 @@ mod test { Ok(()) } + #[test] + fn symbols() -> TestResult { + test_parser( + Node::Module("mod".to_owned(), vec![ + Contextual(Node::Symbol(String::from("bonjour++")), + Context(0)) + ]), + " 'bonjour++ ; " + )?; + + Ok(()) + } + #[test] fn strings() -> TestResult { test_parser( Node::Module("mod".to_owned(), vec![ - Contextual(Node::String(String::from("pizza! ")), Context(0)) + Contextual(Node::String(String::from("pizza! ")), + Context(0)) ]), " \"pizza! \"; " )?; @@ -339,6 +357,7 @@ mod test { )?; Ok(()) } + #[test] fn arrays() -> TestResult { test_parser( diff --git a/src/eval/evaluator.rs b/src/eval/evaluator.rs index 3f09987..59d9a2c 100644 --- a/src/eval/evaluator.rs +++ b/src/eval/evaluator.rs @@ -139,8 +139,13 @@ impl Evaluator { Node::Bool(value) => Ok(Some(Value::Bool(*value))), Node::Int(value) => Ok(Some(Value::Int(*value))), Node::Float(value) => Ok(Some(Value::Float(*value))), + Node::String(value) => Ok(Some(Value::String(value.clone()))), + + Node::Symbol(value) + => Ok(Some(Value::Symbol(value.clone()))), + Node::Array(nodes) => { let mut values: Vec = vec![]; @@ -274,6 +279,14 @@ mod test { Ok(()) } + #[test] + fn symbols() -> TestResult { + test_eval_value(Value::Symbol(String::from("bim-bam")), + " 'bim-bam ; ")?; + + Ok(()) + } + #[test] fn arrays() -> TestResult { test_eval_value( diff --git a/src/eval/value.rs b/src/eval/value.rs index 986d7e5..f96c748 100644 --- a/src/eval/value.rs +++ b/src/eval/value.rs @@ -6,6 +6,7 @@ pub enum Value { Int(i32), Float(f64), String(String), + Symbol(String), Array(Vec) }