forked from NUDT-compiler/nudt-compiler-cpp
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.
270 lines
7.7 KiB
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/&/\&/g; s/</\</g; s/>/\>/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}" |