feat: 添加对数组和对象字面量的尾随逗号支持,更新相关测试用例

This commit is contained in:
0264408
2026-06-16 19:40:24 +08:00
parent a7bedf6fa1
commit bf705069a5
3 changed files with 206 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
// ============================================================================
// 实用脚本集合:文本统计、数组工具、排序、数据转换
// 运行: cargo run -- examples/practical.ast
// ============================================================================
// ============================================================================
// 1. 文本统计工具
// ============================================================================
fn count_chars(s) {
return len(s)
}
fn count_words(s) {
let count = 0
let in_word = false
for (c in s) {
if (c == " " || c == "\n" || c == "\t") {
in_word = false
} else if (!in_word) {
count = count + 1
in_word = true
}
}
return count
}
fn text_stats(text) {
print("=== Text Stats ===")
print("chars:", count_chars(text))
print("words:", count_words(text))
}
let sample = "hello world from Aster scripting language"
text_stats(sample)
// ============================================================================
// 2. 数组工具函数 (map / filter / reduce)
// ============================================================================
fn map(arr, func) {
let result = []
for (x in arr) {
push(result, func(x))
}
return result
}
fn filter(arr, pred) {
let result = []
for (x in arr) {
if (pred(x)) {
push(result, x)
}
}
return result
}
fn reduce(arr, func, init) {
let acc = init
for (x in arr) {
acc = func(acc, x)
}
return acc
}
let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
let doubled = map(nums, fn(x) { return x * 2 })
print("map (*2):", doubled)
let evens = filter(nums, fn(x) { return x % 2 == 0 })
print("filter (even):", evens)
let sum = reduce(nums, fn(a, b) { return a + b }, 0)
print("reduce (sum):", sum)
// 链式: 偶数平方和
let even_squares = map(
filter(nums, fn(x) { return x % 2 == 0 }),
fn(x) { return x * x }
)
let sum_squares = reduce(even_squares, fn(a, b) { return a + b }, 0)
print("sum of even squares:", sum_squares)
// ============================================================================
// 3. 冒泡排序
// ============================================================================
fn sort(arr) {
let n = len(arr)
let i = 0
while (i < n - 1) {
let j = 0
while (j < n - i - 1) {
if (arr[j] > arr[j + 1]) {
let tmp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = tmp
}
j = j + 1
}
i = i + 1
}
return arr
}
let unsorted = [42, 17, 8, 99, 3, 56]
print("unsorted:", unsorted)
print("sorted:", sort(unsorted))
// ============================================================================
// 4. 数据转换 (类 JSON 处理)
// ============================================================================
let users = [
{ name: "Alice", age: 28, active: true },
{ name: "Bob", age: 35, active: false },
{ name: "Carol", age: 22, active: true },
{ name: "Dave", age: 40, active: true },
]
// 找出活跃用户的名字,按年龄排序
let active = filter(users, fn(u) { return u["active"] })
print("active users:", len(active))
// 计算平均年龄
let total_age = reduce(users, fn(acc, u) { return acc + u["age"] }, 0)
print("avg age:", total_age / len(users))
// 生成名字列表
let names = map(users, fn(u) { return u["name"] })
print("names:", names)
// ============================================================================
// 5. 斐波那契 (递归 + 迭代 + 缓存对比)
// ============================================================================
fn fib_rec(n) {
if (n <= 1) { return n }
return fib_rec(n - 1) + fib_rec(n - 2)
}
fn fib_iter(n) {
if (n <= 1) { return n }
let a = 0
let b = 1
let i = 2
while (i <= n) {
let tmp = a + b
a = b
b = tmp
i = i + 1
}
return b
}
print("fib_rec(20):", fib_rec(20))
print("fib_iter(20):", fib_iter(20))
// ============================================================================
// 6. 回文检测
// ============================================================================
fn is_palindrome(s) {
let n = len(s)
let i = 0
while (i < n / 2) {
if (s[i] != s[n - 1 - i]) {
return false
}
i = i + 1
}
return true
}
print("is_palindrome('radar'):", is_palindrome("radar"))
print("is_palindrome('hello'):", is_palindrome("hello"))
+8
View File
@@ -567,6 +567,10 @@ impl Parser {
if !self.match_kind(&[TokenKind::Comma]) {
break;
}
// Allow trailing comma
if self.check(&TokenKind::RightBrace) {
break;
}
}
}
self.consume(TokenKind::RightBrace, "Expected '}' after object literal")?;
@@ -581,6 +585,10 @@ impl Parser {
if !self.match_kind(&[TokenKind::Comma]) {
break;
}
// Allow trailing comma
if self.check(&TokenKind::RightBracket) {
break;
}
}
}
self.consume(TokenKind::RightBracket, "Expected ']' after array literal")?;
+16
View File
@@ -551,6 +551,22 @@
}
}
#[test]
fn parse_array_trailing_comma() {
match parse_expr("[1, 2, 3,]") {
Expr::ArrayLiteral { elements } => assert_eq!(elements.len(), 3),
e => panic!("Expected ArrayLiteral, got {:?}", e),
}
}
#[test]
fn parse_object_trailing_comma() {
match parse_expr("{a: 1, b: 2,}") {
Expr::ObjectLiteral { properties } => assert_eq!(properties.len(), 2),
e => panic!("Expected ObjectLiteral, got {:?}", e),
}
}
// ----- statements -----
#[test]