Add map literals
Map literals share the brackets with lists, but they use colons to delimit keys and values. Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
@@ -931,7 +931,7 @@ impl Parser {
|
||||
}
|
||||
Ok(expr)
|
||||
} else if self.mat(TokenKind::LBracket)? {
|
||||
self.list()
|
||||
self.list_or_map()
|
||||
} else {
|
||||
Err(self.error(format!("unexpected token {:?}", self.current.kind)))
|
||||
}
|
||||
@@ -986,12 +986,34 @@ impl Parser {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn list(&mut self) -> Result<ExprP> {
|
||||
fn list_or_map(&mut self) -> Result<ExprP> {
|
||||
let lbracket = self.prev.clone().unwrap();
|
||||
let mut exprs = Vec::new();
|
||||
|
||||
// check if it's a map
|
||||
if self.mat(TokenKind::Colon)? {
|
||||
let rbracket = self
|
||||
.expect("expected ']' after empty map body", TokenKind::RBracket)?
|
||||
.clone();
|
||||
return Ok(Box::new(MapExpr {
|
||||
lbracket,
|
||||
pairs: vec![],
|
||||
rbracket,
|
||||
}));
|
||||
}
|
||||
|
||||
if !self.check(TokenKind::RBracket) {
|
||||
exprs.push(self.expr()?);
|
||||
let expr = self.expr()?;
|
||||
|
||||
// check if it's a map
|
||||
if self.mat(TokenKind::Colon)? {
|
||||
let value = self.expr()?;
|
||||
let pairs = vec![(expr, value)];
|
||||
return self.finish_map(lbracket, pairs);
|
||||
}
|
||||
|
||||
exprs.push(expr);
|
||||
|
||||
while self.mat(TokenKind::Comma)? {
|
||||
// allow trailing comma
|
||||
if self.check(TokenKind::RBracket) {
|
||||
@@ -1011,6 +1033,29 @@ impl Parser {
|
||||
rbracket,
|
||||
}))
|
||||
}
|
||||
|
||||
fn finish_map(&mut self, lbracket: Token, mut pairs: Vec<(ExprP, ExprP)>) -> Result<ExprP> {
|
||||
while self.mat(TokenKind::Comma)? {
|
||||
// trailing comma
|
||||
if self.check(TokenKind::RBracket) {
|
||||
break;
|
||||
}
|
||||
let key = self.expr()?;
|
||||
self.expect("expected ':' after map key", TokenKind::Colon)?;
|
||||
let value = self.expr()?;
|
||||
pairs.push((key, value));
|
||||
}
|
||||
|
||||
let rbracket = self
|
||||
.expect("expect ']' after map pairs", TokenKind::RBracket)?
|
||||
.clone();
|
||||
|
||||
Ok(Box::new(MapExpr {
|
||||
lbracket,
|
||||
pairs,
|
||||
rbracket,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
Reference in New Issue
Block a user