✨ array values.
parent
35e8cc813e
commit
4e7e7ad07b
|
@ -1,8 +1,11 @@
|
||||||
MODULE ::= INSTR*
|
MODULE ::= INSTR*
|
||||||
INSTR ::= EXPR semicolon
|
INSTR ::= EXPR semicolon
|
||||||
EXPR ::= BUILTIN
|
EXPR ::= LITERAL
|
||||||
|
LITERAL ::= BUILTIN | ARRAY
|
||||||
BUILTIN ::=
|
BUILTIN ::=
|
||||||
| bool
|
| bool
|
||||||
| float
|
| float
|
||||||
| int
|
| int
|
||||||
| string
|
| string
|
||||||
|
|
||||||
|
ARRAY ::= osquare EXPR* csquare
|
||||||
|
|
|
@ -19,7 +19,7 @@ impl Lexer {
|
||||||
line: 1,
|
line: 1,
|
||||||
text: String::from(""),
|
text: String::from(""),
|
||||||
separators: vec![
|
separators: vec![
|
||||||
';'
|
';', '[', ']'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -242,6 +242,7 @@ impl Lexer {
|
||||||
|
|
||||||
self.cursor += 1;
|
self.cursor += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.skip_spaces();
|
self.skip_spaces();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,6 +255,16 @@ impl Iterator for Lexer {
|
||||||
self.skip_spaces();
|
self.skip_spaces();
|
||||||
self.skip_comments();
|
self.skip_comments();
|
||||||
|
|
||||||
|
if let Some(token) = self.scan_text("[") {
|
||||||
|
self.cursor = token.position;
|
||||||
|
return Some(Node::OSquare);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(token) = self.scan_text("]") {
|
||||||
|
self.cursor = token.position;
|
||||||
|
return Some(Node::CSquare);
|
||||||
|
}
|
||||||
|
|
||||||
if let Some(token) = self.scan_keyword("true") {
|
if let Some(token) = self.scan_keyword("true") {
|
||||||
self.cursor = token.position;
|
self.cursor = token.position;
|
||||||
return Some(Node::Bool(token.value == "true"));
|
return Some(Node::Bool(token.value == "true"));
|
||||||
|
@ -417,4 +428,18 @@ mod test {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_arrays() -> Result<(), error::AstError> {
|
||||||
|
let mut lex = Lexer::new();
|
||||||
|
|
||||||
|
let res = lexer_run(&mut lex,
|
||||||
|
" [ ] ")?;
|
||||||
|
|
||||||
|
assert_eq!(2, res.len());
|
||||||
|
assert_eq!(Node::OSquare, *res.get(0).unwrap());
|
||||||
|
assert_eq!(Node::CSquare, *res.get(1).unwrap());
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ pub enum Node {
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
String(String),
|
String(String),
|
||||||
|
OSquare,
|
||||||
|
CSquare,
|
||||||
|
Array(Vec<Node>),
|
||||||
Semicolon
|
Semicolon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -62,34 +62,49 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(&mut self) -> ParseResult {
|
fn parse_expr(&mut self) -> ParseResult {
|
||||||
self.parse_builtin()
|
self.parse_literal()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_literal(&mut self) -> ParseResult {
|
||||||
fn parse_builtin(&mut self) -> ParseResult {
|
|
||||||
match self.lexer.next() {
|
match self.lexer.next() {
|
||||||
Some(Node::Int(value))
|
Some(Node::OSquare) => self.parse_array(),
|
||||||
|
Some(node) => self.parse_builtin(node),
|
||||||
|
None => Ok(None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_builtin(&mut self, node: Node) -> ParseResult {
|
||||||
|
match node {
|
||||||
|
Node::Int(value)
|
||||||
=> Ok(Some(Node::Int(value))),
|
=> Ok(Some(Node::Int(value))),
|
||||||
|
|
||||||
Some(Node::Float(value))
|
Node::Float(value)
|
||||||
=> Ok(Some(Node::Float(value))),
|
=> Ok(Some(Node::Float(value))),
|
||||||
|
|
||||||
Some(Node::Bool(value))
|
Node::Bool(value)
|
||||||
=> Ok(Some(Node::Bool(value))),
|
=> Ok(Some(Node::Bool(value))),
|
||||||
|
|
||||||
Some(Node::String(value))
|
Node::String(value)
|
||||||
=> Ok(Some(Node::String(value))),
|
=> Ok(Some(Node::String(value))),
|
||||||
|
|
||||||
Some(other) => {
|
_ => {
|
||||||
Err(error::AstError {
|
Err(error::AstError {
|
||||||
msg: String::from(format!("unexpected {:?}", other)),
|
msg: String::from(format!("unexpected {:?}", node)),
|
||||||
line: self.lexer.line()
|
line: self.lexer.line()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
None => Ok(None)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_array(&mut self) -> ParseResult {
|
||||||
|
let mut elements: Vec<Node> = vec![];
|
||||||
|
|
||||||
|
while let Ok(Some(expr)) = self.parse_expr() {
|
||||||
|
elements.push(expr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(Node::Array(elements)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -179,4 +194,20 @@ mod test {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arrays() -> TestResult {
|
||||||
|
test_parser(
|
||||||
|
Node::Module("mod".to_owned(), vec![
|
||||||
|
Node::Array(vec![
|
||||||
|
Node::Int(2),
|
||||||
|
Node::Float(3.2),
|
||||||
|
Node::Bool(true)
|
||||||
|
])
|
||||||
|
]),
|
||||||
|
" [2 3.2 true]; "
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,28 @@ 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) => Ok(Some(Value::String(value.clone()))),
|
Node::String(value)
|
||||||
|
=> Ok(Some(Value::String(value.clone()))),
|
||||||
|
Node::Array(nodes) => {
|
||||||
|
let mut values: Vec<Value> = vec![];
|
||||||
|
|
||||||
|
for node in nodes {
|
||||||
|
match self.run(node) {
|
||||||
|
Ok(Some(value)) => {
|
||||||
|
values.push(value);
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
return Err(EvalError {
|
||||||
|
msg: String::from("invalid array element"),
|
||||||
|
line: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Some(Value::Array(values)))
|
||||||
|
}
|
||||||
|
|
||||||
_ => Ok(None)
|
_ => Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -103,4 +124,19 @@ mod test {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn arrays() -> TestResult {
|
||||||
|
test_eval_value(
|
||||||
|
Value::Array(
|
||||||
|
vec![
|
||||||
|
Value::Int(2),
|
||||||
|
Value::Int(4),
|
||||||
|
Value::Float(6.1)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
" [2 4 6.1]; ")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ pub enum Value {
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Int(i32),
|
Int(i32),
|
||||||
Float(f64),
|
Float(f64),
|
||||||
String(String)
|
String(String),
|
||||||
|
Array(Vec<Value>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in New Issue