You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nudt-compiler-cpp/test1.sh

270 lines
7.7 KiB

#!/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
<!DOCTYPE html>
<html>
<head>
<title>语法树生成报告</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { color: #333; }
.summary { background: #f0f0f0; padding: 10px; border-radius: 5px; }
.success { color: green; }
.failure { color: red; }
.skipped { color: orange; }
table { border-collapse: collapse; width: 100%; }
th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }
th { background-color: #4CAF50; color: white; }
tr:nth-child(even) { background-color: #f2f2f2; }
.file-link { text-decoration: none; color: #0066cc; }
.file-link:hover { text-decoration: underline; }
</style>
</head>
<body>
<h1>SysY语法树生成报告</h1>
<div class="summary">
<h2>统计信息</h2>
<p>生成时间: $(date)</p>
<p>测试目录: $TEST_DIR</p>
<p>输出目录: $OUTPUT_DIR</p>
<p>总计: $TOTAL</p>
<p>成功: <span class="success">$SUCCESS</span></p>
<p>失败: <span class="failure">$FAILED</span></p>
<p>跳过: <span class="skipped">$SKIPPED</span></p>
<p>成功率: $((SUCCESS * 100 / TOTAL))%</p>
</div>
<h2>详细结果</h2>
<table>
<tr>
<th>文件</th>
<th>状态</th>
<th>输出文件</th>
<th>错误信息</th>
</tr>
EOF
# 遍历所有文件生成报告
find "$TEST_DIR" -type f -name "*.sy" -print0 | while IFS= read -r -d '' file; do
rel_path="${file#$TEST_DIR/}"
filename=$(basename "$file")
base_name="${filename%.sy}"
dir_path=$(dirname "$rel_path")
output_file="$OUTPUT_DIR/$dir_path/${base_name}.tree"
error_file="$OUTPUT_DIR/$dir_path/${base_name}.err"
status="成功"
status_class="success"
error_msg="-"
if [ ! -f "$output_file" ] || [ ! -s "$output_file" ]; then
status="失败"
status_class="failure"
if [ -f "$error_file" ] && [ -s "$error_file" ]; then
error_msg=$(head -1 "$error_file" | sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g')
fi
fi
cat >> "$REPORT_FILE" << EOF
<tr>
<td>$rel_path</td>
<td class="$status_class">$status</td>
<td><a href="$dir_path/${base_name}.tree" class="file-link">${base_name}.tree</a></td>
<td>$error_msg</td>
</tr>
EOF
done
cat >> "$REPORT_FILE" << EOF
</table>
</body>
</html>
EOF
echo -e "${GREEN}HTML报告已生成: $REPORT_FILE${NC}"