✨ symbol literal.
parent
c45b885dc5
commit
76e5db35b4
|
@ -17,5 +17,6 @@ BUILTIN ::=
|
||||||
| float
|
| float
|
||||||
| int
|
| int
|
||||||
| string
|
| string
|
||||||
|
| symbol
|
||||||
|
|
||||||
ARRAY ::= osquare EXPR* csquare
|
ARRAY ::= osquare EXPR* csquare
|
||||||
|
|
|
@ -155,6 +155,33 @@ impl Lexer {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn scan_symbol(&self) -> Option<Token> {
|
||||||
|
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<Token> {
|
fn scan_int(&self) -> Option<Token> {
|
||||||
let mut value = String::from("");
|
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() {
|
if let Some(token) = self.scan_identifier() {
|
||||||
self.cursor = token.position;
|
self.cursor = token.position;
|
||||||
return Some(Contextual(Node::Ident(token.value.clone()),
|
return Some(Contextual(Node::Ident(token.value.clone()),
|
||||||
|
@ -401,7 +434,7 @@ mod test {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Err(error::AstError {
|
return Err(error::AstError {
|
||||||
msg: format!("unknown symbol <{}>", val),
|
msg: format!("unknown text <{}>", val),
|
||||||
line: lexer.line
|
line: lexer.line
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -519,6 +552,29 @@ mod test {
|
||||||
Ok(())
|
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]
|
#[test]
|
||||||
fn test_variables() -> Result<(), error::AstError> {
|
fn test_variables() -> Result<(), error::AstError> {
|
||||||
let mut lex = Lexer::new();
|
let mut lex = Lexer::new();
|
||||||
|
|
|
@ -8,6 +8,7 @@ pub enum Node {
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
String(String),
|
String(String),
|
||||||
|
Symbol(String),
|
||||||
OSquare,
|
OSquare,
|
||||||
CSquare,
|
CSquare,
|
||||||
Array(Vec<Contextual<Node>>),
|
Array(Vec<Contextual<Node>>),
|
||||||
|
|
|
@ -176,6 +176,10 @@ impl Parser {
|
||||||
|
|
||||||
Contextual(Node::String(value), ctx)
|
Contextual(Node::String(value), ctx)
|
||||||
=> Ok(Some(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 {
|
Err(error::AstError {
|
||||||
msg: String::from(format!("unexpected {:?}", node)),
|
msg: String::from(format!("unexpected {:?}", node)),
|
||||||
|
@ -279,11 +283,25 @@ mod test {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn symbols() -> TestResult {
|
||||||
|
test_parser(
|
||||||
|
Node::Module("mod".to_owned(), vec![
|
||||||
|
Contextual(Node::Symbol(String::from("bonjour++")),
|
||||||
|
Context(0))
|
||||||
|
]),
|
||||||
|
" 'bonjour++ ; "
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn strings() -> TestResult {
|
fn strings() -> TestResult {
|
||||||
test_parser(
|
test_parser(
|
||||||
Node::Module("mod".to_owned(), vec![
|
Node::Module("mod".to_owned(), vec![
|
||||||
Contextual(Node::String(String::from("pizza! ")), Context(0))
|
Contextual(Node::String(String::from("pizza! ")),
|
||||||
|
Context(0))
|
||||||
]),
|
]),
|
||||||
" \"pizza! \"; "
|
" \"pizza! \"; "
|
||||||
)?;
|
)?;
|
||||||
|
@ -339,6 +357,7 @@ mod test {
|
||||||
)?;
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arrays() -> TestResult {
|
fn arrays() -> TestResult {
|
||||||
test_parser(
|
test_parser(
|
||||||
|
|
|
@ -139,8 +139,13 @@ impl Evaluator {
|
||||||
Node::Bool(value) => Ok(Some(Value::Bool(*value))),
|
Node::Bool(value) => Ok(Some(Value::Bool(*value))),
|
||||||
Node::Int(value) => Ok(Some(Value::Int(*value))),
|
Node::Int(value) => Ok(Some(Value::Int(*value))),
|
||||||
Node::Float(value) => Ok(Some(Value::Float(*value))),
|
Node::Float(value) => Ok(Some(Value::Float(*value))),
|
||||||
|
|
||||||
Node::String(value)
|
Node::String(value)
|
||||||
=> Ok(Some(Value::String(value.clone()))),
|
=> Ok(Some(Value::String(value.clone()))),
|
||||||
|
|
||||||
|
Node::Symbol(value)
|
||||||
|
=> Ok(Some(Value::Symbol(value.clone()))),
|
||||||
|
|
||||||
Node::Array(nodes) => {
|
Node::Array(nodes) => {
|
||||||
let mut values: Vec<Value> = vec![];
|
let mut values: Vec<Value> = vec![];
|
||||||
|
|
||||||
|
@ -274,6 +279,14 @@ mod test {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn symbols() -> TestResult {
|
||||||
|
test_eval_value(Value::Symbol(String::from("bim-bam")),
|
||||||
|
" 'bim-bam ; ")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn arrays() -> TestResult {
|
fn arrays() -> TestResult {
|
||||||
test_eval_value(
|
test_eval_value(
|
||||||
|
|
|
@ -6,6 +6,7 @@ pub enum Value {
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
String(String),
|
String(String),
|
||||||
|
Symbol(String),
|
||||||
Array(Vec<Value>)
|
Array(Vec<Value>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue