feat: 新增对象字面量和属性访问表达式

This commit is contained in:
0264408
2026-02-10 17:13:40 +08:00
parent 5c5ca8600a
commit 521c7006d9
11 changed files with 188 additions and 66 deletions
+48 -20
View File
@@ -154,14 +154,11 @@ impl Parser {
if self.match_kind(&[TokenKind::Equal]) {
let value = self.assignment();
if let Expr::Variable(name) = expr {
return Expr::Assign {
name,
value: Box::new(value),
};
} else {
panic!("Invalid assignment target.");
}
return match expr {
Expr::Variable(name) => Expr::Assign { name, value: Box::new(value) },
Expr::Get { object, name } => Expr::Set { object, name, value: Box::new(value) },
_ => panic!("Invalid assignment target."),
};
}
expr
@@ -299,21 +296,31 @@ impl Parser {
fn call(&mut self) -> Expr {
let mut expr = self.primary();
while self.match_kind(&[TokenKind::LeftParen]) {
let mut arguments = Vec::new();
if !self.check(&TokenKind::RightParen) {
loop {
arguments.push(self.expression());
if !self.match_kind(&[TokenKind::Comma]) {
break;
loop {
if self.match_kind(&[TokenKind::LeftParen]) {
let mut arguments = Vec::new();
if !self.check(&TokenKind::RightParen) {
loop {
arguments.push(self.expression());
if !self.match_kind(&[TokenKind::Comma]) {
break;
}
}
}
self.consume(TokenKind::RightParen, "Expected ')' after arguments.").unwrap();
expr = Expr::Call {
callee: Box::new(expr),
arguments,
};
} else if self.match_kind(&[TokenKind::Dot]) {
let name = self.consume_ident("Expected property name after '.'.").unwrap();
expr = Expr::Get {
object: Box::new(expr),
name,
};
} else {
break;
}
self.consume(TokenKind::RightParen, "Expected ')' after arguments.").unwrap();
expr = Expr::Call {
callee: Box::new(expr),
arguments,
};
}
expr
@@ -363,6 +370,10 @@ impl Parser {
return expr;
}
if self.match_kind(&[TokenKind::LeftBrace]) {
return self.object_literal();
}
panic!("Expected expression at line {}", self.peek().line);
}
@@ -428,4 +439,21 @@ impl Parser {
fn previous(&self) -> &Token {
&self.tokens[self.current - 1]
}
fn object_literal(&mut self) -> Expr {
let mut properties = Vec::new();
if !self.check(&TokenKind::RightBrace) {
loop {
let name = self.consume_ident("Expected property name in object literal").unwrap();
self.consume(TokenKind::Colon, "Expected ':' after property name in object literal").unwrap();
let value = self.expression();
properties.push((name, value));
if !self.match_kind(&[TokenKind::Comma]) {
break;
}
}
}
self.consume(TokenKind::RightBrace, "Expected '}' after object literal").unwrap();
Expr::ObjectLiteral { properties }
}
}