#!/bin/bash # batch_parse_tree.sh - 批量生成SysY文件的语法树 # 设置颜色输出 RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # 默认配置 TEST_DIR="./test" # 测试文件目录 OUTPUT_DIR="./lab1_results" # 输出目录 COMPILER="./build/bin/compiler" # 编译器路径 COMPILER_OPT="--emit-parse-tree" # 编译器选项 VERBOSE=false # 是否显示详细信息 OVERWRITE=false # 是否覆盖已存在的文件 # 显示帮助信息 show_help() { cat << EOF 用法: $0 [选项] 选项: -d, --dir DIR 指定测试文件目录 (默认: ./test) -o, --output DIR 指定输出目录 (默认: ./parse_trees) -c, --compiler FILE 指定编译器路径 (默认: ./build/bin/compiler) -v, --verbose 显示详细信息 -f, --force 覆盖已存在的输出文件 -h, --help 显示帮助信息 示例: $0 # 使用默认配置 $0 -d ./testcases -o ./output # 指定目录 $0 -v -f # 显示详细信息并覆盖已有文件 EOF } # 解析命令行参数 while [[ $# -gt 0 ]]; do case $1 in -d|--dir) TEST_DIR="$2" shift 2 ;; -o|--output) OUTPUT_DIR="$2" shift 2 ;; -c|--compiler) COMPILER="$2" shift 2 ;; -v|--verbose) VERBOSE=true shift ;; -f|--force) OVERWRITE=true shift ;; -h|--help) show_help exit 0 ;; *) echo -e "${RED}错误: 未知选项 $1${NC}" show_help exit 1 ;; esac done # 检查编译器是否存在 if [ ! -f "$COMPILER" ]; then echo -e "${RED}错误: 编译器不存在: $COMPILER${NC}" echo -e "${YELLOW}提示: 请先编译项目或指定正确的编译器路径${NC}" exit 1 fi # 检查测试目录是否存在 if [ ! -d "$TEST_DIR" ]; then echo -e "${RED}错误: 测试目录不存在: $TEST_DIR${NC}" exit 1 fi # 创建输出目录 mkdir -p "$OUTPUT_DIR" # 统计变量 TOTAL=0 SUCCESS=0 FAILED=0 SKIPPED=0 # 创建日志文件 LOG_FILE="$OUTPUT_DIR/batch_parse.log" echo "批量语法树生成日志 - $(date)" > "$LOG_FILE" echo "==========================================" >> "$LOG_FILE" # 查找所有.sy文件 echo -e "${BLUE}========================================${NC}" echo -e "${BLUE}开始批量生成语法树${NC}" echo -e "${BLUE}测试目录: $TEST_DIR${NC}" echo -e "${BLUE}输出目录: $OUTPUT_DIR${NC}" echo -e "${BLUE}编译器: $COMPILER${NC}" echo -e "${BLUE}========================================${NC}" # 使用find命令查找所有.sy文件 while IFS= read -r -d '' file; do TOTAL=$((TOTAL + 1)) # 获取相对路径和文件名 rel_path="${file#$TEST_DIR/}" filename=$(basename "$file") dir_path=$(dirname "$rel_path") # 创建对应的输出目录 target_dir="$OUTPUT_DIR/$dir_path" mkdir -p "$target_dir" # 输出文件名 base_name="${filename%.sy}" output_file="$target_dir/${base_name}.tree" error_file="$target_dir/${base_name}.err" # 显示进度 if [ "$VERBOSE" = true ]; then echo -e "${YELLOW}[$TOTAL] 处理: $rel_path${NC}" else echo -ne "${YELLOW}[$TOTAL] 处理: $filename ... ${NC}" fi # 执行编译器命令 "$COMPILER" $COMPILER_OPT "$file" > "$output_file" 2> "$error_file" exit_code=$? # 检查结果 if [ $exit_code -eq 0 ] && [ -s "$output_file" ]; then if [ "$VERBOSE" = false ]; then echo -e "${GREEN}✓ 成功${NC}" else echo -e "${GREEN}✓ 成功 - 输出: $output_file${NC}" fi echo "[SUCCESS] $file -> $output_file" >> "$LOG_FILE" SUCCESS=$((SUCCESS + 1)) # 如果错误文件为空,删除它 if [ ! -s "$error_file" ]; then rm -f "$error_file" fi else if [ "$VERBOSE" = false ]; then echo -e "${RED}✗ 失败${NC}" else echo -e "${RED}✗ 失败 - 错误: $error_file${NC}" fi echo "[FAILED] $file (exit code: $exit_code)" >> "$LOG_FILE" cat "$error_file" >> "$LOG_FILE" echo "----------------------------------------" >> "$LOG_FILE" FAILED=$((FAILED + 1)) fi done < <(find "$TEST_DIR" -type f -name "*.sy" -print0) # 输出统计信息 echo -e "${BLUE}========================================${NC}" echo -e "${BLUE}处理完成${NC}" echo -e "${GREEN}成功: $SUCCESS${NC}" echo -e "${RED}失败: $FAILED${NC}" echo -e "${YELLOW}跳过: $SKIPPED${NC}" echo -e "${BLUE}总计: $TOTAL${NC}" echo -e "${BLUE}========================================${NC}" echo -e "${BLUE}日志文件: $LOG_FILE${NC}" # 如果有失败的文件,列出它们 if [ $FAILED -gt 0 ]; then echo -e "\n${RED}失败的文件列表:${NC}" grep "\[FAILED\]" "$LOG_FILE" | while read -r line; do echo " $line" done fi # 生成汇总报告 REPORT_FILE="$OUTPUT_DIR/report.html" cat > "$REPORT_FILE" << EOF
生成时间: $(date)
测试目录: $TEST_DIR
输出目录: $OUTPUT_DIR
总计: $TOTAL
成功: $SUCCESS
失败: $FAILED
跳过: $SKIPPED
成功率: $((SUCCESS * 100 / TOTAL))%
| 文件 | 状态 | 输出文件 | 错误信息 |
|---|---|---|---|
| $rel_path | $status | ${base_name}.tree | $error_msg |