forked from NUDT-compiler/nudt-compiler-cpp
Compare commits
9 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
207df228fc | 5 days ago |
|
|
408f24c05f | 5 days ago |
|
|
4bb7007fd3 | 6 days ago |
|
|
4f0036900a | 4 weeks ago |
|
|
d8b30279e3 | 4 weeks ago |
|
|
86ce9bcf50 | 4 weeks ago |
|
|
63953bd4ae | 4 weeks ago |
|
|
9e981ce28b | 4 weeks ago |
|
|
dbc1d08957 | 4 weeks ago |
@ -0,0 +1,7 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
version = 4
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nudt-compiler-cpp"
|
||||||
|
version = "0.1.0"
|
||||||
@ -0,0 +1,6 @@
|
|||||||
|
[package]
|
||||||
|
name = "nudt-compiler-cpp"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
@ -1,17 +1,42 @@
|
|||||||
// 极简符号表:记录局部变量定义点。
|
// 符号表:记录局部变量/常量/参数定义。
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "SysYParser.h"
|
#include "SysYParser.h"
|
||||||
|
|
||||||
|
enum class BaseTypeKind { Int, Float, Void };
|
||||||
|
|
||||||
|
struct TypeDesc {
|
||||||
|
BaseTypeKind base = BaseTypeKind::Int;
|
||||||
|
std::vector<int> dims; // 为空表示标量;数组维度允许首维为 -1 表示形参不定长
|
||||||
|
bool is_const = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class SymbolKind { Var, Const, Param };
|
||||||
|
|
||||||
|
struct SymbolEntry {
|
||||||
|
SymbolKind kind = SymbolKind::Var;
|
||||||
|
SysYParser::VarDefContext* var_decl = nullptr;
|
||||||
|
SysYParser::ConstDefContext* const_decl = nullptr;
|
||||||
|
SysYParser::FuncFParamContext* param_decl = nullptr;
|
||||||
|
TypeDesc type; // 记录类型信息
|
||||||
|
bool is_const = false;
|
||||||
|
std::optional<int> const_value;
|
||||||
|
};
|
||||||
|
|
||||||
class SymbolTable {
|
class SymbolTable {
|
||||||
public:
|
public:
|
||||||
void Add(const std::string& name, SysYParser::VarDefContext* decl);
|
void EnterScope();
|
||||||
bool Contains(const std::string& name) const;
|
void ExitScope();
|
||||||
SysYParser::VarDefContext* Lookup(const std::string& name) const;
|
|
||||||
|
bool ContainsInCurrentScope(const std::string& name) const;
|
||||||
|
void Add(const std::string& name, const SymbolEntry& entry);
|
||||||
|
const SymbolEntry* Lookup(const std::string& name) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<std::string, SysYParser::VarDefContext*> table_;
|
std::vector<std::unordered_map<std::string, SymbolEntry>> scopes_;
|
||||||
};
|
};
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Reconfigure with IR pipeline enabled, build, then run Lab2 test script.
|
||||||
|
RESULT_FILE="test/test_result/run_lab2_result.log"
|
||||||
|
mkdir -p "$(dirname \"$RESULT_FILE\")"
|
||||||
|
: > "$RESULT_FILE"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "[run_lab2] start: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
|
echo "[run_lab2] logging to: $RESULT_FILE"
|
||||||
|
|
||||||
|
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCOMPILER_PARSE_ONLY=OFF
|
||||||
|
cmake --build build -j "$(nproc)"
|
||||||
|
CASE_DIR=test/test_case bash scripts/test_lab2.sh
|
||||||
|
|
||||||
|
echo "[run_lab2] end: $(date '+%Y-%m-%d %H:%M:%S')"
|
||||||
|
} 2>&1 | tee "$RESULT_FILE"
|
||||||
@ -0,0 +1,121 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Lab2 quick/full verification helper.
|
||||||
|
# Usage:
|
||||||
|
# bash scripts/test_lab2.sh
|
||||||
|
# Optional env vars:
|
||||||
|
# COMPILER=./build/bin/compiler
|
||||||
|
# CASE_DIR=test/test_case/functional
|
||||||
|
# OUT_DIR=test/test_result/lab2_ir
|
||||||
|
# LOG_FILE=test/test_result/lab2_test.log
|
||||||
|
|
||||||
|
COMPILER="${COMPILER:-./build/bin/compiler}"
|
||||||
|
CASE_DIR="${CASE_DIR:-test/test_case/functional}"
|
||||||
|
OUT_DIR="${OUT_DIR:-test/test_result/lab2_ir}"
|
||||||
|
LOG_FILE="${LOG_FILE:-test/test_result/lab2_test.log}"
|
||||||
|
VERIFY_SCRIPT="./scripts/verify_ir.sh"
|
||||||
|
|
||||||
|
if [[ ! -x "$COMPILER" ]]; then
|
||||||
|
echo "compiler not found or not executable: $COMPILER" >&2
|
||||||
|
echo "build first:" >&2
|
||||||
|
echo " cmake -S . -B build -DCMAKE_BUILD_TYPE=Release" >&2
|
||||||
|
echo " cmake --build build -j \"\$(nproc)\"" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -x "$VERIFY_SCRIPT" ]]; then
|
||||||
|
echo "verify script not found or not executable: $VERIFY_SCRIPT" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ ! -d "$CASE_DIR" ]]; then
|
||||||
|
echo "case dir not found: $CASE_DIR" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$OUT_DIR"
|
||||||
|
|
||||||
|
# Preflight: ensure compiler supports IR emission (not parse-only build).
|
||||||
|
probe_input="$CASE_DIR/simple_add.sy"
|
||||||
|
probe_err="$OUT_DIR/.lab2_probe.err"
|
||||||
|
if [[ -f "$probe_input" ]]; then
|
||||||
|
set +e
|
||||||
|
"$COMPILER" --emit-ir "$probe_input" > /dev/null 2> "$probe_err"
|
||||||
|
probe_rc=$?
|
||||||
|
set -e
|
||||||
|
if [[ $probe_rc -ne 0 ]] && grep -Eiq "parse-only|IR/汇编输出已禁用" "$probe_err"; then
|
||||||
|
echo "detected parse-only compiler build, cannot run Lab2 IR tests." >&2
|
||||||
|
echo "rebuild with IR enabled:" >&2
|
||||||
|
echo " cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCOMPILER_PARSE_ONLY=OFF" >&2
|
||||||
|
echo " cmake --build build -j \"\$(nproc)\"" >&2
|
||||||
|
rm -f "$probe_err"
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
|
rm -f "$probe_err"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mkdir -p "$(dirname "$LOG_FILE")"
|
||||||
|
: > "$LOG_FILE"
|
||||||
|
|
||||||
|
echo "[Lab2] start test" | tee -a "$LOG_FILE"
|
||||||
|
echo "compiler : $COMPILER" | tee -a "$LOG_FILE"
|
||||||
|
echo "cases : $CASE_DIR" | tee -a "$LOG_FILE"
|
||||||
|
echo "out dir : $OUT_DIR" | tee -a "$LOG_FILE"
|
||||||
|
|
||||||
|
echo "[Step 1] single sample check: simple_add.sy" | tee -a "$LOG_FILE"
|
||||||
|
sample_input="$(find "$CASE_DIR" -type f -name "simple_add.sy" -print -quit)"
|
||||||
|
if [[ -z "$sample_input" ]]; then
|
||||||
|
echo "single sample: FAIL (simple_add.sy not found under $CASE_DIR)" | tee -a "$LOG_FILE"
|
||||||
|
echo "stop here. see log: $LOG_FILE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
if "$VERIFY_SCRIPT" "$sample_input" "$OUT_DIR" --run >> "$LOG_FILE" 2>&1; then
|
||||||
|
echo "single sample: PASS" | tee -a "$LOG_FILE"
|
||||||
|
else
|
||||||
|
echo "single sample: FAIL" | tee -a "$LOG_FILE"
|
||||||
|
echo "stop here. see log: $LOG_FILE" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[Step 2] full functional regression" | tee -a "$LOG_FILE"
|
||||||
|
|
||||||
|
pass=0
|
||||||
|
fail=0
|
||||||
|
total=0
|
||||||
|
failed_list=()
|
||||||
|
|
||||||
|
while IFS= read -r -d '' sy; do
|
||||||
|
total=$((total + 1))
|
||||||
|
name="$(basename "$sy")"
|
||||||
|
echo "[$total] $name" | tee -a "$LOG_FILE"
|
||||||
|
|
||||||
|
if "$VERIFY_SCRIPT" "$sy" "$OUT_DIR" --run >> "$LOG_FILE" 2>&1; then
|
||||||
|
pass=$((pass + 1))
|
||||||
|
echo " PASS" | tee -a "$LOG_FILE"
|
||||||
|
else
|
||||||
|
fail=$((fail + 1))
|
||||||
|
failed_list+=("$sy")
|
||||||
|
echo " FAIL" | tee -a "$LOG_FILE"
|
||||||
|
fi
|
||||||
|
done < <(find "$CASE_DIR" -type f -name "*.sy" -print0 | sort -z)
|
||||||
|
|
||||||
|
echo "" | tee -a "$LOG_FILE"
|
||||||
|
echo "[Summary]" | tee -a "$LOG_FILE"
|
||||||
|
echo "total: $total" | tee -a "$LOG_FILE"
|
||||||
|
echo "pass : $pass" | tee -a "$LOG_FILE"
|
||||||
|
echo "fail : $fail" | tee -a "$LOG_FILE"
|
||||||
|
|
||||||
|
if [[ $fail -gt 0 ]]; then
|
||||||
|
echo "failed cases:" | tee -a "$LOG_FILE"
|
||||||
|
for f in "${failed_list[@]}"; do
|
||||||
|
echo " - $f" | tee -a "$LOG_FILE"
|
||||||
|
done
|
||||||
|
echo "Lab2 target is not fully met yet." | tee -a "$LOG_FILE"
|
||||||
|
echo "see details in $LOG_FILE"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "All functional cases passed. Lab2 target (functional regression) is met." | tee -a "$LOG_FILE"
|
||||||
|
echo "see details in $LOG_FILE"
|
||||||
@ -1,98 +0,0 @@
|
|||||||
// SysY 子集语法:支持形如
|
|
||||||
// int main() { int a = 1; int b = 2; return a + b; }
|
|
||||||
// 的最小返回表达式编译。
|
|
||||||
|
|
||||||
// 后续需要自行添加
|
|
||||||
|
|
||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
|
|
||||||
INT: 'int';
|
|
||||||
RETURN: 'return';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
/* Syntax rules */
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: funcDef EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
decl
|
|
||||||
: btype varDef SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: lValue (ASSIGN initValue)?
|
|
||||||
;
|
|
||||||
|
|
||||||
initValue
|
|
||||||
: exp
|
|
||||||
;
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: returnStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
returnStmt
|
|
||||||
: RETURN exp SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
exp
|
|
||||||
: LPAREN exp RPAREN # parenExp
|
|
||||||
| var # varExp
|
|
||||||
| number # numberExp
|
|
||||||
| exp ADD exp # additiveExp
|
|
||||||
;
|
|
||||||
|
|
||||||
var
|
|
||||||
: ID
|
|
||||||
;
|
|
||||||
|
|
||||||
lValue
|
|
||||||
: ID
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
;
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
// SysY 子集语法:支持形如
|
|
||||||
// int main() { int a = 1; int b = 2; return a + b; }
|
|
||||||
// 的最小返回表达式编译。
|
|
||||||
|
|
||||||
// 后续需要自行添加
|
|
||||||
|
|
||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
|
|
||||||
INT: 'int';
|
|
||||||
RETURN: 'return';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
/* Syntax rules */
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: funcDef EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
decl
|
|
||||||
: btype varDef SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: lValue (ASSIGN initValue)?
|
|
||||||
;
|
|
||||||
|
|
||||||
initValue
|
|
||||||
: exp
|
|
||||||
;
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: returnStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
returnStmt
|
|
||||||
: RETURN exp SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
exp
|
|
||||||
: LPAREN exp RPAREN # parenExp
|
|
||||||
| var # varExp
|
|
||||||
| number # numberExp
|
|
||||||
| exp ADD exp # additiveExp
|
|
||||||
;
|
|
||||||
|
|
||||||
var
|
|
||||||
: ID
|
|
||||||
;
|
|
||||||
|
|
||||||
lValue
|
|
||||||
: ID
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
;
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
int main() {
|
|
||||||
int a = 1, b = 2;
|
|
||||||
int c;
|
|
||||||
c = a + b * 3;
|
|
||||||
|
|
||||||
if (c > 5) {
|
|
||||||
c = c - 1;
|
|
||||||
} else {
|
|
||||||
c = c + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (c < 10) {
|
|
||||||
c = c + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
@ -1,98 +0,0 @@
|
|||||||
// SysY 子集语法:支持形如
|
|
||||||
// int main() { int a = 1; int b = 2; return a + b; }
|
|
||||||
// 的最小返回表达式编译。
|
|
||||||
|
|
||||||
// 后续需要自行添加
|
|
||||||
|
|
||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
|
|
||||||
INT: 'int';
|
|
||||||
RETURN: 'return';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
/* Syntax rules */
|
|
||||||
/*===-------------------------------------------===*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: funcDef EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
decl
|
|
||||||
: btype varDef SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: lValue (ASSIGN initValue)?
|
|
||||||
;
|
|
||||||
|
|
||||||
initValue
|
|
||||||
: exp
|
|
||||||
;
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: returnStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
returnStmt
|
|
||||||
: RETURN exp SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
exp
|
|
||||||
: LPAREN exp RPAREN # parenExp
|
|
||||||
| var # varExp
|
|
||||||
| number # numberExp
|
|
||||||
| exp ADD exp # additiveExp
|
|
||||||
;
|
|
||||||
|
|
||||||
var
|
|
||||||
: ID
|
|
||||||
;
|
|
||||||
|
|
||||||
lValue
|
|
||||||
: ID
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
;
|
|
||||||
@ -1,187 +0,0 @@
|
|||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
INT: 'int';
|
|
||||||
RETURN: 'return';
|
|
||||||
IF: 'if';
|
|
||||||
ELSE: 'else';
|
|
||||||
WHILE: 'while';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
SUB: '-';
|
|
||||||
MUL: '*';
|
|
||||||
DIV: '/';
|
|
||||||
|
|
||||||
LT: '<';
|
|
||||||
GT: '>';
|
|
||||||
LE: '<=';
|
|
||||||
GE: '>=';
|
|
||||||
EQ: '==';
|
|
||||||
NEQ: '!=';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
LBRACK: '[';
|
|
||||||
RBRACK: ']';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Syntax rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: (decl | funcDef)* EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 声明 ===== */
|
|
||||||
|
|
||||||
decl
|
|
||||||
: btype varDefList SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
varDefList
|
|
||||||
: varDef (COMMA varDef)*
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: ID (LBRACK number RBRACK)? (ASSIGN initValue)?
|
|
||||||
;
|
|
||||||
|
|
||||||
initValue
|
|
||||||
: exp
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 函数 ===== */
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN funcParams? RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
;
|
|
||||||
|
|
||||||
funcParams
|
|
||||||
: funcParam (COMMA funcParam)*
|
|
||||||
;
|
|
||||||
|
|
||||||
funcParam
|
|
||||||
: btype ID
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句块 ===== */
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句 ===== */
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: returnStmt
|
|
||||||
| assignStmt
|
|
||||||
| expStmt
|
|
||||||
| blockStmt
|
|
||||||
| ifStmt
|
|
||||||
| whileStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
returnStmt
|
|
||||||
: RETURN exp SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
assignStmt
|
|
||||||
: lValue ASSIGN exp SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
expStmt
|
|
||||||
: exp? SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
ifStmt
|
|
||||||
: IF LPAREN exp RPAREN stmt (ELSE stmt)?
|
|
||||||
;
|
|
||||||
|
|
||||||
whileStmt
|
|
||||||
: WHILE LPAREN exp RPAREN stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 表达式 ===== */
|
|
||||||
|
|
||||||
exp
|
|
||||||
: logicalExp
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 逻辑(先简化成关系表达式) */
|
|
||||||
logicalExp
|
|
||||||
: relationalExp
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 比较 */
|
|
||||||
relationalExp
|
|
||||||
: additiveExp ( (LT | GT | LE | GE | EQ | NEQ) additiveExp )*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 加减 */
|
|
||||||
additiveExp
|
|
||||||
: multiplicativeExp ( (ADD | SUB) multiplicativeExp )*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 乘除 */
|
|
||||||
multiplicativeExp
|
|
||||||
: unaryExp ( (MUL | DIV) unaryExp )*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 一元 */
|
|
||||||
unaryExp
|
|
||||||
: primaryExp
|
|
||||||
| ADD unaryExp
|
|
||||||
| SUB unaryExp
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 基本表达式 */
|
|
||||||
primaryExp
|
|
||||||
: LPAREN exp RPAREN
|
|
||||||
| number
|
|
||||||
| lValue
|
|
||||||
| funcCall
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 函数调用 */
|
|
||||||
funcCall
|
|
||||||
: ID LPAREN (exp (COMMA exp)*)? RPAREN
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 基础 ===== */
|
|
||||||
|
|
||||||
lValue
|
|
||||||
: ID (LBRACK exp RBRACK)?
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
;
|
|
||||||
@ -1,229 +0,0 @@
|
|||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
CONST: 'const';
|
|
||||||
INT: 'int';
|
|
||||||
FLOAT: 'float';
|
|
||||||
VOID: 'void';
|
|
||||||
RETURN: 'return';
|
|
||||||
IF: 'if';
|
|
||||||
ELSE: 'else';
|
|
||||||
WHILE: 'while';
|
|
||||||
BREAK: 'break';
|
|
||||||
CONTINUE: 'continue';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
SUB: '-';
|
|
||||||
MUL: '*';
|
|
||||||
DIV: '/';
|
|
||||||
MOD: '%';
|
|
||||||
NOT: '!';
|
|
||||||
|
|
||||||
LT: '<';
|
|
||||||
GT: '>';
|
|
||||||
LE: '<=';
|
|
||||||
GE: '>=';
|
|
||||||
EQ: '==';
|
|
||||||
NEQ: '!=';
|
|
||||||
|
|
||||||
AND: '&&';
|
|
||||||
OR: '||';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
LBRACK: '[';
|
|
||||||
RBRACK: ']';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
|
|
||||||
/* 浮点字面量要放在整数字面量前面 */
|
|
||||||
FLOATLITERAL
|
|
||||||
: [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)?
|
|
||||||
| '.' [0-9]+ ([eE] [+\-]? [0-9]+)?
|
|
||||||
| [0-9]+ [eE] [+\-]? [0-9]+
|
|
||||||
;
|
|
||||||
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Parser rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: (decl | funcDef)* EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 声明 ===== */
|
|
||||||
|
|
||||||
decl
|
|
||||||
: constDecl
|
|
||||||
| varDecl
|
|
||||||
;
|
|
||||||
|
|
||||||
constDecl
|
|
||||||
: CONST btype constDef (COMMA constDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
varDecl
|
|
||||||
: btype varDef (COMMA varDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
;
|
|
||||||
|
|
||||||
constDef
|
|
||||||
: ID constExpArrayDims ASSIGN constInitVal
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: ID arrayDims? (ASSIGN initVal)?
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 变量定义时数组维度一般要求是 exp */
|
|
||||||
arrayDims
|
|
||||||
: (LBRACK exp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
/* const 定义也支持多维 */
|
|
||||||
constExpArrayDims
|
|
||||||
: (LBRACK constExp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
constInitVal
|
|
||||||
: constExp
|
|
||||||
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
initVal
|
|
||||||
: exp
|
|
||||||
| LBRACE (initVal (COMMA initVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 函数 ===== */
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN funcFParams? RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
| VOID
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParams
|
|
||||||
: funcFParam (COMMA funcFParam)*
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParam
|
|
||||||
: btype ID
|
|
||||||
| btype ID LBRACK RBRACK (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句块 ===== */
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句 ===== */
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: lVal ASSIGN exp SEMICOLON # assignStatement
|
|
||||||
| exp? SEMICOLON # expStatement
|
|
||||||
| blockStmt # blockStatement
|
|
||||||
| IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement
|
|
||||||
| WHILE LPAREN cond RPAREN stmt # whileStatement
|
|
||||||
| BREAK SEMICOLON # breakStatement
|
|
||||||
| CONTINUE SEMICOLON # continueStatement
|
|
||||||
| RETURN exp? SEMICOLON # returnStatement
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 表达式 ===== */
|
|
||||||
|
|
||||||
exp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
|
|
||||||
cond
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
lVal
|
|
||||||
: ID (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
primaryExp
|
|
||||||
: LPAREN exp RPAREN
|
|
||||||
| lVal
|
|
||||||
| number
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
| FLOATLITERAL
|
|
||||||
;
|
|
||||||
|
|
||||||
funcRParams
|
|
||||||
: exp (COMMA exp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryExp
|
|
||||||
: primaryExp
|
|
||||||
| ID LPAREN funcRParams? RPAREN
|
|
||||||
| unaryOp unaryExp
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryOp
|
|
||||||
: ADD
|
|
||||||
| SUB
|
|
||||||
| NOT
|
|
||||||
;
|
|
||||||
|
|
||||||
mulExp
|
|
||||||
: unaryExp ((MUL | DIV | MOD) unaryExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
addExp
|
|
||||||
: mulExp ((ADD | SUB) mulExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
relExp
|
|
||||||
: addExp ((LT | GT | LE | GE) addExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
eqExp
|
|
||||||
: relExp ((EQ | NEQ) relExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lAndExp
|
|
||||||
: eqExp (AND eqExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lOrExp
|
|
||||||
: lAndExp (OR lAndExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constExp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
@ -1,229 +0,0 @@
|
|||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
CONST: 'const';
|
|
||||||
INT: 'int';
|
|
||||||
FLOAT: 'float';
|
|
||||||
VOID: 'void';
|
|
||||||
RETURN: 'return';
|
|
||||||
IF: 'if';
|
|
||||||
ELSE: 'else';
|
|
||||||
WHILE: 'while';
|
|
||||||
BREAK: 'break';
|
|
||||||
CONTINUE: 'continue';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
SUB: '-';
|
|
||||||
MUL: '*';
|
|
||||||
DIV: '/';
|
|
||||||
MOD: '%';
|
|
||||||
NOT: '!';
|
|
||||||
|
|
||||||
LT: '<';
|
|
||||||
GT: '>';
|
|
||||||
LE: '<=';
|
|
||||||
GE: '>=';
|
|
||||||
EQ: '==';
|
|
||||||
NEQ: '!=';
|
|
||||||
|
|
||||||
AND: '&&';
|
|
||||||
OR: '||';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
LBRACK: '[';
|
|
||||||
RBRACK: ']';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
|
|
||||||
/* 浮点字面量要放在整数字面量前面 */
|
|
||||||
FLOATLITERAL
|
|
||||||
: [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)?
|
|
||||||
| '.' [0-9]+ ([eE] [+\-]? [0-9]+)?
|
|
||||||
| [0-9]+ [eE] [+\-]? [0-9]+
|
|
||||||
;
|
|
||||||
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Parser rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: (decl | funcDef)* EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 声明 ===== */
|
|
||||||
|
|
||||||
decl
|
|
||||||
: constDecl
|
|
||||||
| varDecl
|
|
||||||
;
|
|
||||||
|
|
||||||
constDecl
|
|
||||||
: CONST btype constDef (COMMA constDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
varDecl
|
|
||||||
: btype varDef (COMMA varDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
;
|
|
||||||
|
|
||||||
constDef
|
|
||||||
: ID constExpArrayDims ASSIGN constInitVal
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: ID arrayDims? (ASSIGN initVal)?
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 变量定义时数组维度一般要求是 exp */
|
|
||||||
arrayDims
|
|
||||||
: (LBRACK exp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
/* const 定义也支持多维 */
|
|
||||||
constExpArrayDims
|
|
||||||
: (LBRACK constExp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
constInitVal
|
|
||||||
: constExp
|
|
||||||
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
initVal
|
|
||||||
: exp
|
|
||||||
| LBRACE (initVal (COMMA initVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 函数 ===== */
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN funcFParams? RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
| VOID
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParams
|
|
||||||
: funcFParam (COMMA funcFParam)*
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParam
|
|
||||||
: btype ID
|
|
||||||
| btype ID LBRACK RBRACK (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句块 ===== */
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句 ===== */
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: lVal ASSIGN exp SEMICOLON # assignStatement
|
|
||||||
| exp? SEMICOLON # expStatement
|
|
||||||
| blockStmt # blockStatement
|
|
||||||
| IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement
|
|
||||||
| WHILE LPAREN cond RPAREN stmt # whileStatement
|
|
||||||
| BREAK SEMICOLON # breakStatement
|
|
||||||
| CONTINUE SEMICOLON # continueStatement
|
|
||||||
| RETURN exp? SEMICOLON # returnStatement
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 表达式 ===== */
|
|
||||||
|
|
||||||
exp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
|
|
||||||
cond
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
lVal
|
|
||||||
: ID (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
primaryExp
|
|
||||||
: LPAREN exp RPAREN
|
|
||||||
| lVal
|
|
||||||
| number
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
| FLOATLITERAL
|
|
||||||
;
|
|
||||||
|
|
||||||
funcRParams
|
|
||||||
: exp (COMMA exp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryExp
|
|
||||||
: primaryExp
|
|
||||||
| ID LPAREN funcRParams? RPAREN
|
|
||||||
| unaryOp unaryExp
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryOp
|
|
||||||
: ADD
|
|
||||||
| SUB
|
|
||||||
| NOT
|
|
||||||
;
|
|
||||||
|
|
||||||
mulExp
|
|
||||||
: unaryExp ((MUL | DIV | MOD) unaryExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
addExp
|
|
||||||
: mulExp ((ADD | SUB) mulExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
relExp
|
|
||||||
: addExp ((LT | GT | LE | GE) addExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
eqExp
|
|
||||||
: relExp ((EQ | NEQ) relExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lAndExp
|
|
||||||
: eqExp (AND eqExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lOrExp
|
|
||||||
: lAndExp (OR lAndExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constExp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
@ -1,229 +0,0 @@
|
|||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
CONST: 'const';
|
|
||||||
INT: 'int';
|
|
||||||
FLOAT: 'float';
|
|
||||||
VOID: 'void';
|
|
||||||
RETURN: 'return';
|
|
||||||
IF: 'if';
|
|
||||||
ELSE: 'else';
|
|
||||||
WHILE: 'while';
|
|
||||||
BREAK: 'break';
|
|
||||||
CONTINUE: 'continue';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
SUB: '-';
|
|
||||||
MUL: '*';
|
|
||||||
DIV: '/';
|
|
||||||
MOD: '%';
|
|
||||||
NOT: '!';
|
|
||||||
|
|
||||||
LT: '<';
|
|
||||||
GT: '>';
|
|
||||||
LE: '<=';
|
|
||||||
GE: '>=';
|
|
||||||
EQ: '==';
|
|
||||||
NEQ: '!=';
|
|
||||||
|
|
||||||
AND: '&&';
|
|
||||||
OR: '||';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
LBRACK: '[';
|
|
||||||
RBRACK: ']';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
|
|
||||||
/* 浮点字面量要放在整数字面量前面 */
|
|
||||||
FLOATLITERAL
|
|
||||||
: [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)?
|
|
||||||
| '.' [0-9]+ ([eE] [+\-]? [0-9]+)?
|
|
||||||
| [0-9]+ [eE] [+\-]? [0-9]+
|
|
||||||
;
|
|
||||||
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Parser rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: (decl | funcDef)* EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 声明 ===== */
|
|
||||||
|
|
||||||
decl
|
|
||||||
: constDecl
|
|
||||||
| varDecl
|
|
||||||
;
|
|
||||||
|
|
||||||
constDecl
|
|
||||||
: CONST btype constDef (COMMA constDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
varDecl
|
|
||||||
: btype varDef (COMMA varDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
;
|
|
||||||
|
|
||||||
constDef
|
|
||||||
: ID constExpArrayDims ASSIGN constInitVal
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: ID arrayDims? (ASSIGN initVal)?
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 变量定义时数组维度一般要求是 exp */
|
|
||||||
arrayDims
|
|
||||||
: (LBRACK exp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
/* const 定义也支持多维 */
|
|
||||||
constExpArrayDims
|
|
||||||
: (LBRACK constExp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
constInitVal
|
|
||||||
: constExp
|
|
||||||
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
initVal
|
|
||||||
: exp
|
|
||||||
| LBRACE (initVal (COMMA initVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 函数 ===== */
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN funcFParams? RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
| VOID
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParams
|
|
||||||
: funcFParam (COMMA funcFParam)*
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParam
|
|
||||||
: btype ID
|
|
||||||
| btype ID LBRACK RBRACK (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句块 ===== */
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句 ===== */
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: lVal ASSIGN exp SEMICOLON # assignStatement
|
|
||||||
| exp? SEMICOLON # expStatement
|
|
||||||
| blockStmt # blockStatement
|
|
||||||
| IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement
|
|
||||||
| WHILE LPAREN cond RPAREN stmt # whileStatement
|
|
||||||
| BREAK SEMICOLON # breakStatement
|
|
||||||
| CONTINUE SEMICOLON # continueStatement
|
|
||||||
| RETURN exp? SEMICOLON # returnStatement
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 表达式 ===== */
|
|
||||||
|
|
||||||
exp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
|
|
||||||
cond
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
lVal
|
|
||||||
: ID (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
primaryExp
|
|
||||||
: LPAREN exp RPAREN
|
|
||||||
| lVal
|
|
||||||
| number
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
| FLOATLITERAL
|
|
||||||
;
|
|
||||||
|
|
||||||
funcRParams
|
|
||||||
: exp (COMMA exp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryExp
|
|
||||||
: primaryExp
|
|
||||||
| ID LPAREN funcRParams? RPAREN
|
|
||||||
| unaryOp unaryExp
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryOp
|
|
||||||
: ADD
|
|
||||||
| SUB
|
|
||||||
| NOT
|
|
||||||
;
|
|
||||||
|
|
||||||
mulExp
|
|
||||||
: unaryExp ((MUL | DIV | MOD) unaryExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
addExp
|
|
||||||
: mulExp ((ADD | SUB) mulExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
relExp
|
|
||||||
: addExp ((LT | GT | LE | GE) addExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
eqExp
|
|
||||||
: relExp ((EQ | NEQ) relExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lAndExp
|
|
||||||
: eqExp (AND eqExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lOrExp
|
|
||||||
: lAndExp (OR lAndExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constExp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
@ -1,229 +0,0 @@
|
|||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
CONST: 'const';
|
|
||||||
INT: 'int';
|
|
||||||
FLOAT: 'float';
|
|
||||||
VOID: 'void';
|
|
||||||
RETURN: 'return';
|
|
||||||
IF: 'if';
|
|
||||||
ELSE: 'else';
|
|
||||||
WHILE: 'while';
|
|
||||||
BREAK: 'break';
|
|
||||||
CONTINUE: 'continue';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
SUB: '-';
|
|
||||||
MUL: '*';
|
|
||||||
DIV: '/';
|
|
||||||
MOD: '%';
|
|
||||||
NOT: '!';
|
|
||||||
|
|
||||||
LT: '<';
|
|
||||||
GT: '>';
|
|
||||||
LE: '<=';
|
|
||||||
GE: '>=';
|
|
||||||
EQ: '==';
|
|
||||||
NEQ: '!=';
|
|
||||||
|
|
||||||
AND: '&&';
|
|
||||||
OR: '||';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
LBRACK: '[';
|
|
||||||
RBRACK: ']';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
|
|
||||||
/* 浮点字面量要放在整数字面量前面 */
|
|
||||||
FLOATLITERAL
|
|
||||||
: [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)?
|
|
||||||
| '.' [0-9]+ ([eE] [+\-]? [0-9]+)?
|
|
||||||
| [0-9]+ [eE] [+\-]? [0-9]+
|
|
||||||
;
|
|
||||||
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Parser rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: (decl | funcDef)* EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 声明 ===== */
|
|
||||||
|
|
||||||
decl
|
|
||||||
: constDecl
|
|
||||||
| varDecl
|
|
||||||
;
|
|
||||||
|
|
||||||
constDecl
|
|
||||||
: CONST btype constDef (COMMA constDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
varDecl
|
|
||||||
: btype varDef (COMMA varDef)* SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
;
|
|
||||||
|
|
||||||
constDef
|
|
||||||
: ID constExpArrayDims ASSIGN constInitVal
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: ID arrayDims? (ASSIGN initVal)?
|
|
||||||
;
|
|
||||||
|
|
||||||
/* 变量定义时数组维度一般要求是 exp */
|
|
||||||
arrayDims
|
|
||||||
: (LBRACK exp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
/* const 定义也支持多维 */
|
|
||||||
constExpArrayDims
|
|
||||||
: (LBRACK constExp RBRACK)+
|
|
||||||
;
|
|
||||||
|
|
||||||
constInitVal
|
|
||||||
: constExp
|
|
||||||
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
initVal
|
|
||||||
: exp
|
|
||||||
| LBRACE (initVal (COMMA initVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 函数 ===== */
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN funcFParams? RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
| VOID
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParams
|
|
||||||
: funcFParam (COMMA funcFParam)*
|
|
||||||
;
|
|
||||||
|
|
||||||
funcFParam
|
|
||||||
: btype ID
|
|
||||||
| btype ID LBRACK RBRACK (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句块 ===== */
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句 ===== */
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: lVal ASSIGN exp SEMICOLON # assignStatement
|
|
||||||
| exp? SEMICOLON # expStatement
|
|
||||||
| blockStmt # blockStatement
|
|
||||||
| IF LPAREN cond RPAREN stmt (ELSE stmt)? # ifStatement
|
|
||||||
| WHILE LPAREN cond RPAREN stmt # whileStatement
|
|
||||||
| BREAK SEMICOLON # breakStatement
|
|
||||||
| CONTINUE SEMICOLON # continueStatement
|
|
||||||
| RETURN exp? SEMICOLON # returnStatement
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 表达式 ===== */
|
|
||||||
|
|
||||||
exp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
|
|
||||||
cond
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
lVal
|
|
||||||
: ID (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
primaryExp
|
|
||||||
: LPAREN exp RPAREN
|
|
||||||
| lVal
|
|
||||||
| number
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
| FLOATLITERAL
|
|
||||||
;
|
|
||||||
|
|
||||||
funcRParams
|
|
||||||
: exp (COMMA exp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryExp
|
|
||||||
: primaryExp
|
|
||||||
| ID LPAREN funcRParams? RPAREN
|
|
||||||
| unaryOp unaryExp
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryOp
|
|
||||||
: ADD
|
|
||||||
| SUB
|
|
||||||
| NOT
|
|
||||||
;
|
|
||||||
|
|
||||||
mulExp
|
|
||||||
: unaryExp ((MUL | DIV | MOD) unaryExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
addExp
|
|
||||||
: mulExp ((ADD | SUB) mulExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
relExp
|
|
||||||
: addExp ((LT | GT | LE | GE) addExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
eqExp
|
|
||||||
: relExp ((EQ | NEQ) relExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lAndExp
|
|
||||||
: eqExp (AND eqExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lOrExp
|
|
||||||
: lAndExp (OR lAndExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constExp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
@ -1,260 +0,0 @@
|
|||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
CONST: 'const';
|
|
||||||
INT: 'int';
|
|
||||||
FLOAT: 'float';
|
|
||||||
VOID: 'void';
|
|
||||||
RETURN: 'return';
|
|
||||||
IF: 'if';
|
|
||||||
ELSE: 'else';
|
|
||||||
WHILE: 'while';
|
|
||||||
BREAK: 'break';
|
|
||||||
CONTINUE: 'continue';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
SUB: '-';
|
|
||||||
MUL: '*';
|
|
||||||
DIV: '/';
|
|
||||||
MOD: '%';
|
|
||||||
NOT: '!';
|
|
||||||
|
|
||||||
LT: '<';
|
|
||||||
GT: '>';
|
|
||||||
LE: '<=';
|
|
||||||
GE: '>=';
|
|
||||||
EQ: '==';
|
|
||||||
NEQ: '!=';
|
|
||||||
|
|
||||||
AND: '&&';
|
|
||||||
OR: '||';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
LBRACK: '[';
|
|
||||||
RBRACK: ']';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
|
|
||||||
/* 浮点字面量放在整数字面量前 */
|
|
||||||
FLOATLITERAL
|
|
||||||
: [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)?
|
|
||||||
| '.' [0-9]+ ([eE] [+\-]? [0-9]+)?
|
|
||||||
| [0-9]+ [eE] [+\-]? [0-9]+
|
|
||||||
;
|
|
||||||
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Parser rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: (decl | funcDef)* EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 声明 ===== */
|
|
||||||
|
|
||||||
decl
|
|
||||||
: constDecl
|
|
||||||
| varDecl
|
|
||||||
;
|
|
||||||
|
|
||||||
constDecl
|
|
||||||
: CONST btype constDefList SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
varDecl
|
|
||||||
: btype varDefList SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
;
|
|
||||||
|
|
||||||
constDefList
|
|
||||||
: constDef (COMMA constDef)*
|
|
||||||
;
|
|
||||||
|
|
||||||
varDefList
|
|
||||||
: varDef (COMMA varDef)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constDef
|
|
||||||
: ID (LBRACK constExp RBRACK)+ ASSIGN constInitVal
|
|
||||||
| ID ASSIGN constInitVal
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: ID (LBRACK exp RBRACK)* (ASSIGN initVal)?
|
|
||||||
;
|
|
||||||
|
|
||||||
constInitVal
|
|
||||||
: constExp
|
|
||||||
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
initVal
|
|
||||||
: exp
|
|
||||||
| LBRACE (initVal (COMMA initVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 函数 ===== */
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN funcParams? RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
| VOID
|
|
||||||
;
|
|
||||||
|
|
||||||
funcParams
|
|
||||||
: funcParam (COMMA funcParam)*
|
|
||||||
;
|
|
||||||
|
|
||||||
funcParam
|
|
||||||
: btype ID
|
|
||||||
| btype ID LBRACK RBRACK (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句块 ===== */
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句 ===== */
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: returnStmt
|
|
||||||
| assignStmt
|
|
||||||
| expStmt
|
|
||||||
| blockStmt
|
|
||||||
| ifStmt
|
|
||||||
| whileStmt
|
|
||||||
| breakStmt
|
|
||||||
| continueStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
returnStmt
|
|
||||||
: RETURN exp? SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
assignStmt
|
|
||||||
: lValue ASSIGN exp SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
expStmt
|
|
||||||
: exp? SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
ifStmt
|
|
||||||
: IF LPAREN cond RPAREN stmt (ELSE stmt)?
|
|
||||||
;
|
|
||||||
|
|
||||||
whileStmt
|
|
||||||
: WHILE LPAREN cond RPAREN stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
breakStmt
|
|
||||||
: BREAK SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
continueStmt
|
|
||||||
: CONTINUE SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 表达式 ===== */
|
|
||||||
|
|
||||||
exp
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
cond
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
lValue
|
|
||||||
: ID (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
primaryExp
|
|
||||||
: LPAREN exp RPAREN
|
|
||||||
| number
|
|
||||||
| lValue
|
|
||||||
;
|
|
||||||
|
|
||||||
funcCall
|
|
||||||
: ID LPAREN funcRParams? RPAREN
|
|
||||||
;
|
|
||||||
|
|
||||||
funcRParams
|
|
||||||
: exp (COMMA exp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryExp
|
|
||||||
: primaryExp
|
|
||||||
| funcCall
|
|
||||||
| unaryOp unaryExp
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryOp
|
|
||||||
: ADD
|
|
||||||
| SUB
|
|
||||||
| NOT
|
|
||||||
;
|
|
||||||
|
|
||||||
mulExp
|
|
||||||
: unaryExp ((MUL | DIV | MOD) unaryExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
addExp
|
|
||||||
: mulExp ((ADD | SUB) mulExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
relExp
|
|
||||||
: addExp ((LT | GT | LE | GE) addExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
eqExp
|
|
||||||
: relExp ((EQ | NEQ) relExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lAndExp
|
|
||||||
: eqExp (AND eqExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lOrExp
|
|
||||||
: lAndExp (OR lAndExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constExp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
| FLOATLITERAL
|
|
||||||
;
|
|
||||||
@ -1,260 +0,0 @@
|
|||||||
grammar SysY;
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Lexer rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
CONST: 'const';
|
|
||||||
INT: 'int';
|
|
||||||
FLOAT: 'float';
|
|
||||||
VOID: 'void';
|
|
||||||
RETURN: 'return';
|
|
||||||
IF: 'if';
|
|
||||||
ELSE: 'else';
|
|
||||||
WHILE: 'while';
|
|
||||||
BREAK: 'break';
|
|
||||||
CONTINUE: 'continue';
|
|
||||||
|
|
||||||
ASSIGN: '=';
|
|
||||||
ADD: '+';
|
|
||||||
SUB: '-';
|
|
||||||
MUL: '*';
|
|
||||||
DIV: '/';
|
|
||||||
MOD: '%';
|
|
||||||
NOT: '!';
|
|
||||||
|
|
||||||
LT: '<';
|
|
||||||
GT: '>';
|
|
||||||
LE: '<=';
|
|
||||||
GE: '>=';
|
|
||||||
EQ: '==';
|
|
||||||
NEQ: '!=';
|
|
||||||
|
|
||||||
AND: '&&';
|
|
||||||
OR: '||';
|
|
||||||
|
|
||||||
LPAREN: '(';
|
|
||||||
RPAREN: ')';
|
|
||||||
LBRACE: '{';
|
|
||||||
RBRACE: '}';
|
|
||||||
LBRACK: '[';
|
|
||||||
RBRACK: ']';
|
|
||||||
SEMICOLON: ';';
|
|
||||||
COMMA: ',';
|
|
||||||
|
|
||||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
|
||||||
|
|
||||||
/* 浮点字面量放在整数字面量前 */
|
|
||||||
FLOATLITERAL
|
|
||||||
: [0-9]+ '.' [0-9]* ([eE] [+\-]? [0-9]+)?
|
|
||||||
| '.' [0-9]+ ([eE] [+\-]? [0-9]+)?
|
|
||||||
| [0-9]+ [eE] [+\-]? [0-9]+
|
|
||||||
;
|
|
||||||
|
|
||||||
ILITERAL: [0-9]+;
|
|
||||||
|
|
||||||
WS: [ \t\r\n] -> skip;
|
|
||||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
|
||||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
|
||||||
|
|
||||||
|
|
||||||
/*====================*/
|
|
||||||
/* Parser rules */
|
|
||||||
/*====================*/
|
|
||||||
|
|
||||||
compUnit
|
|
||||||
: (decl | funcDef)* EOF
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 声明 ===== */
|
|
||||||
|
|
||||||
decl
|
|
||||||
: constDecl
|
|
||||||
| varDecl
|
|
||||||
;
|
|
||||||
|
|
||||||
constDecl
|
|
||||||
: CONST btype constDefList SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
varDecl
|
|
||||||
: btype varDefList SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
btype
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
;
|
|
||||||
|
|
||||||
constDefList
|
|
||||||
: constDef (COMMA constDef)*
|
|
||||||
;
|
|
||||||
|
|
||||||
varDefList
|
|
||||||
: varDef (COMMA varDef)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constDef
|
|
||||||
: ID (LBRACK constExp RBRACK)+ ASSIGN constInitVal
|
|
||||||
| ID ASSIGN constInitVal
|
|
||||||
;
|
|
||||||
|
|
||||||
varDef
|
|
||||||
: ID (LBRACK exp RBRACK)* (ASSIGN initVal)?
|
|
||||||
;
|
|
||||||
|
|
||||||
constInitVal
|
|
||||||
: constExp
|
|
||||||
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
initVal
|
|
||||||
: exp
|
|
||||||
| LBRACE (initVal (COMMA initVal)*)? RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 函数 ===== */
|
|
||||||
|
|
||||||
funcDef
|
|
||||||
: funcType ID LPAREN funcParams? RPAREN blockStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
funcType
|
|
||||||
: INT
|
|
||||||
| FLOAT
|
|
||||||
| VOID
|
|
||||||
;
|
|
||||||
|
|
||||||
funcParams
|
|
||||||
: funcParam (COMMA funcParam)*
|
|
||||||
;
|
|
||||||
|
|
||||||
funcParam
|
|
||||||
: btype ID
|
|
||||||
| btype ID LBRACK RBRACK (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句块 ===== */
|
|
||||||
|
|
||||||
blockStmt
|
|
||||||
: LBRACE blockItem* RBRACE
|
|
||||||
;
|
|
||||||
|
|
||||||
blockItem
|
|
||||||
: decl
|
|
||||||
| stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 语句 ===== */
|
|
||||||
|
|
||||||
stmt
|
|
||||||
: returnStmt
|
|
||||||
| assignStmt
|
|
||||||
| expStmt
|
|
||||||
| blockStmt
|
|
||||||
| ifStmt
|
|
||||||
| whileStmt
|
|
||||||
| breakStmt
|
|
||||||
| continueStmt
|
|
||||||
;
|
|
||||||
|
|
||||||
returnStmt
|
|
||||||
: RETURN exp? SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
assignStmt
|
|
||||||
: lValue ASSIGN exp SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
expStmt
|
|
||||||
: exp? SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
ifStmt
|
|
||||||
: IF LPAREN cond RPAREN stmt (ELSE stmt)?
|
|
||||||
;
|
|
||||||
|
|
||||||
whileStmt
|
|
||||||
: WHILE LPAREN cond RPAREN stmt
|
|
||||||
;
|
|
||||||
|
|
||||||
breakStmt
|
|
||||||
: BREAK SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
continueStmt
|
|
||||||
: CONTINUE SEMICOLON
|
|
||||||
;
|
|
||||||
|
|
||||||
/* ===== 表达式 ===== */
|
|
||||||
|
|
||||||
exp
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
cond
|
|
||||||
: lOrExp
|
|
||||||
;
|
|
||||||
|
|
||||||
lValue
|
|
||||||
: ID (LBRACK exp RBRACK)*
|
|
||||||
;
|
|
||||||
|
|
||||||
primaryExp
|
|
||||||
: LPAREN exp RPAREN
|
|
||||||
| number
|
|
||||||
| lValue
|
|
||||||
;
|
|
||||||
|
|
||||||
funcCall
|
|
||||||
: ID LPAREN funcRParams? RPAREN
|
|
||||||
;
|
|
||||||
|
|
||||||
funcRParams
|
|
||||||
: exp (COMMA exp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryExp
|
|
||||||
: primaryExp
|
|
||||||
| funcCall
|
|
||||||
| unaryOp unaryExp
|
|
||||||
;
|
|
||||||
|
|
||||||
unaryOp
|
|
||||||
: ADD
|
|
||||||
| SUB
|
|
||||||
| NOT
|
|
||||||
;
|
|
||||||
|
|
||||||
mulExp
|
|
||||||
: unaryExp ((MUL | DIV | MOD) unaryExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
addExp
|
|
||||||
: mulExp ((ADD | SUB) mulExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
relExp
|
|
||||||
: addExp ((LT | GT | LE | GE) addExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
eqExp
|
|
||||||
: relExp ((EQ | NEQ) relExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lAndExp
|
|
||||||
: eqExp (AND eqExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
lOrExp
|
|
||||||
: lAndExp (OR lAndExp)*
|
|
||||||
;
|
|
||||||
|
|
||||||
constExp
|
|
||||||
: addExp
|
|
||||||
;
|
|
||||||
|
|
||||||
number
|
|
||||||
: ILITERAL
|
|
||||||
| FLOATLITERAL
|
|
||||||
;
|
|
||||||
@ -1,31 +1,148 @@
|
|||||||
// 当前仅支持 void、i32 和 i32*。
|
// 支持 void/i1/i32/float/ptr/array/function/label。
|
||||||
#include "ir/IR.h"
|
#include "ir/IR.h"
|
||||||
|
|
||||||
namespace ir {
|
namespace ir {
|
||||||
|
|
||||||
Type::Type(Kind k) : kind_(k) {}
|
Type::Type(Kind k) : kind_(k) {}
|
||||||
|
|
||||||
|
Type::Type(Kind k, std::shared_ptr<Type> elem, size_t count)
|
||||||
|
: kind_(k), elem_type_(std::move(elem)), array_size_(count) {}
|
||||||
|
|
||||||
|
Type::Type(Kind k, std::shared_ptr<Type> ret,
|
||||||
|
std::vector<std::shared_ptr<Type>> params, bool is_vararg)
|
||||||
|
: kind_(k), ret_type_(std::move(ret)), param_types_(std::move(params)),
|
||||||
|
is_vararg_(is_vararg) {}
|
||||||
|
|
||||||
const std::shared_ptr<Type>& Type::GetVoidType() {
|
const std::shared_ptr<Type>& Type::GetVoidType() {
|
||||||
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Void);
|
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Void);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<Type>& Type::GetInt1Type() {
|
||||||
|
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Int1);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
const std::shared_ptr<Type>& Type::GetInt32Type() {
|
const std::shared_ptr<Type>& Type::GetInt32Type() {
|
||||||
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Int32);
|
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Int32);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::shared_ptr<Type>& Type::GetPtrInt32Type() {
|
const std::shared_ptr<Type>& Type::GetFloatType() {
|
||||||
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::PtrInt32);
|
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Float);
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<Type>& Type::GetLabelType() {
|
||||||
|
static const std::shared_ptr<Type> type = std::make_shared<Type>(Kind::Label);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Type> Type::GetPointerType(std::shared_ptr<Type> elem) {
|
||||||
|
if (!elem) {
|
||||||
|
throw std::runtime_error("PointerType 缺少 element type");
|
||||||
|
}
|
||||||
|
return std::make_shared<Type>(Kind::Pointer, std::move(elem), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Type> Type::GetArrayType(std::shared_ptr<Type> elem,
|
||||||
|
size_t count) {
|
||||||
|
if (!elem) {
|
||||||
|
throw std::runtime_error("ArrayType 缺少 element type");
|
||||||
|
}
|
||||||
|
return std::make_shared<Type>(Kind::Array, std::move(elem), count);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<Type> Type::GetFunctionType(
|
||||||
|
std::shared_ptr<Type> ret, std::vector<std::shared_ptr<Type>> params,
|
||||||
|
bool is_vararg) {
|
||||||
|
if (!ret) {
|
||||||
|
throw std::runtime_error("FunctionType 缺少 return type");
|
||||||
|
}
|
||||||
|
return std::make_shared<Type>(Kind::Function, std::move(ret),
|
||||||
|
std::move(params), is_vararg);
|
||||||
|
}
|
||||||
|
|
||||||
Type::Kind Type::GetKind() const { return kind_; }
|
Type::Kind Type::GetKind() const { return kind_; }
|
||||||
|
|
||||||
bool Type::IsVoid() const { return kind_ == Kind::Void; }
|
bool Type::IsVoid() const { return kind_ == Kind::Void; }
|
||||||
|
|
||||||
|
bool Type::IsInt1() const { return kind_ == Kind::Int1; }
|
||||||
|
|
||||||
bool Type::IsInt32() const { return kind_ == Kind::Int32; }
|
bool Type::IsInt32() const { return kind_ == Kind::Int32; }
|
||||||
|
|
||||||
bool Type::IsPtrInt32() const { return kind_ == Kind::PtrInt32; }
|
bool Type::IsFloat() const { return kind_ == Kind::Float; }
|
||||||
|
|
||||||
|
bool Type::IsPointer() const { return kind_ == Kind::Pointer; }
|
||||||
|
|
||||||
|
bool Type::IsArray() const { return kind_ == Kind::Array; }
|
||||||
|
|
||||||
|
bool Type::IsFunction() const { return kind_ == Kind::Function; }
|
||||||
|
|
||||||
|
bool Type::IsLabel() const { return kind_ == Kind::Label; }
|
||||||
|
|
||||||
|
const std::shared_ptr<Type>& Type::GetElementType() const {
|
||||||
|
if (!elem_type_) {
|
||||||
|
throw std::runtime_error("Type 没有 element type");
|
||||||
|
}
|
||||||
|
return elem_type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Type::GetArraySize() const {
|
||||||
|
if (!IsArray()) {
|
||||||
|
throw std::runtime_error("Type 不是 array");
|
||||||
|
}
|
||||||
|
return array_size_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::shared_ptr<Type>& Type::GetReturnType() const {
|
||||||
|
if (!IsFunction()) {
|
||||||
|
throw std::runtime_error("Type 不是 function");
|
||||||
|
}
|
||||||
|
return ret_type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::vector<std::shared_ptr<Type>>& Type::GetParamTypes() const {
|
||||||
|
if (!IsFunction()) {
|
||||||
|
throw std::runtime_error("Type 不是 function");
|
||||||
|
}
|
||||||
|
return param_types_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Type::IsVarArg() const {
|
||||||
|
if (!IsFunction()) {
|
||||||
|
throw std::runtime_error("Type 不是 function");
|
||||||
|
}
|
||||||
|
return is_vararg_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Type::Equals(const Type& other) const {
|
||||||
|
if (kind_ != other.kind_) return false;
|
||||||
|
switch (kind_) {
|
||||||
|
case Kind::Pointer:
|
||||||
|
return elem_type_ && other.elem_type_ &&
|
||||||
|
elem_type_->Equals(*other.elem_type_);
|
||||||
|
case Kind::Array:
|
||||||
|
return array_size_ == other.array_size_ && elem_type_ &&
|
||||||
|
other.elem_type_ && elem_type_->Equals(*other.elem_type_);
|
||||||
|
case Kind::Function: {
|
||||||
|
if (!ret_type_ || !other.ret_type_ ||
|
||||||
|
!ret_type_->Equals(*other.ret_type_) ||
|
||||||
|
is_vararg_ != other.is_vararg_ ||
|
||||||
|
param_types_.size() != other.param_types_.size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < param_types_.size(); ++i) {
|
||||||
|
if (!param_types_[i] || !other.param_types_[i] ||
|
||||||
|
!param_types_[i]->Equals(*other.param_types_[i])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ir
|
} // namespace ir
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -1,39 +1,170 @@
|
|||||||
#include "irgen/IRGen.h"
|
#include "irgen/IRGen.h"
|
||||||
|
|
||||||
|
#include <any>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include "SysYParser.h"
|
#include "SysYParser.h"
|
||||||
#include "ir/IR.h"
|
#include "ir/IR.h"
|
||||||
#include "utils/Log.h"
|
#include "utils/Log.h"
|
||||||
|
|
||||||
// 语句生成当前只实现了最小子集。
|
|
||||||
// 目前支持:
|
|
||||||
// - return <exp>;
|
|
||||||
//
|
|
||||||
// 还未支持:
|
|
||||||
// - 赋值语句
|
|
||||||
// - if / while 等控制流
|
|
||||||
// - 空语句、块语句嵌套分发之外的更多语句形态
|
|
||||||
|
|
||||||
std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
|
std::any IRGenImpl::visitStmt(SysYParser::StmtContext* ctx) {
|
||||||
if (!ctx) {
|
if (!ctx) return {};
|
||||||
throw std::runtime_error(FormatError("irgen", "缺少语句"));
|
if (ctx->lVal() && ctx->ASSIGN()) {
|
||||||
|
ir::Value* addr = GetLValAddress(ctx->lVal());
|
||||||
|
ir::Value* val = EvalExp(ctx->exp());
|
||||||
|
BoundDecl bound = sema_.ResolveVarUse(ctx->lVal());
|
||||||
|
const TypeDesc* ty = nullptr;
|
||||||
|
if (bound.kind == BoundDecl::Kind::Var && bound.var_decl) {
|
||||||
|
ty = sema_.GetVarType(bound.var_decl);
|
||||||
|
} else if (bound.kind == BoundDecl::Kind::Param && bound.param_decl) {
|
||||||
|
ty = sema_.GetParamType(bound.param_decl);
|
||||||
|
} else if (bound.kind == BoundDecl::Kind::Const) {
|
||||||
|
throw std::runtime_error(FormatError("irgen", "不能给常量赋值"));
|
||||||
|
}
|
||||||
|
if (!ty && ctx->lVal()->ID()) {
|
||||||
|
const auto name = ctx->lVal()->ID()->getText();
|
||||||
|
for (const auto& kv : var_storage_) {
|
||||||
|
auto* def = const_cast<SysYParser::VarDefContext*>(kv.first);
|
||||||
|
if (def && def->ID() && def->ID()->getText() == name) {
|
||||||
|
ty = sema_.GetVarType(kv.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ty) {
|
||||||
|
for (const auto& kv : const_storage_) {
|
||||||
|
auto* def = const_cast<SysYParser::ConstDefContext*>(kv.first);
|
||||||
|
if (def && def->ID() && def->ID()->getText() == name) {
|
||||||
|
throw std::runtime_error(FormatError("irgen", "不能给常量赋值"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ty) {
|
||||||
|
for (const auto& kv : param_storage_) {
|
||||||
|
auto* def = const_cast<SysYParser::FuncFParamContext*>(kv.first);
|
||||||
|
if (def && def->ID() && def->ID()->getText() == name) {
|
||||||
|
ty = sema_.GetParamType(kv.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ty) {
|
||||||
|
for (const auto& kv : global_var_storage_) {
|
||||||
|
auto* def = const_cast<SysYParser::VarDefContext*>(kv.first);
|
||||||
|
if (def && def->ID() && def->ID()->getText() == name) {
|
||||||
|
ty = sema_.GetVarType(kv.first);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ty) {
|
||||||
|
for (const auto& kv : global_const_storage_) {
|
||||||
|
auto* def = const_cast<SysYParser::ConstDefContext*>(kv.first);
|
||||||
|
if (def && def->ID() && def->ID()->getText() == name) {
|
||||||
|
throw std::runtime_error(FormatError("irgen", "不能给常量赋值"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ty) {
|
||||||
|
throw std::runtime_error(FormatError("irgen", "无法解析赋值类型"));
|
||||||
|
}
|
||||||
|
if (ty->base == BaseTypeKind::Float) {
|
||||||
|
if (val->IsInt1()) {
|
||||||
|
val = CastToFloat(CastToInt(val));
|
||||||
|
} else if (val->IsInt32()) {
|
||||||
|
val = CastToFloat(val);
|
||||||
|
}
|
||||||
|
} else if (ty->base == BaseTypeKind::Int) {
|
||||||
|
if (val->IsFloat()) {
|
||||||
|
val = CastToInt(val);
|
||||||
|
} else if (val->IsInt1()) {
|
||||||
|
val = CastToInt(val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (ctx->returnStmt()) {
|
builder_.CreateStore(val, addr);
|
||||||
return ctx->returnStmt()->accept(this);
|
return BlockFlow::Continue;
|
||||||
}
|
}
|
||||||
throw std::runtime_error(FormatError("irgen", "暂不支持的语句类型"));
|
if (ctx->block()) {
|
||||||
|
return ctx->block()->accept(this);
|
||||||
}
|
}
|
||||||
|
if (ctx->IF()) {
|
||||||
|
auto* then_bb = func_->CreateBlock("if.then");
|
||||||
|
auto* else_bb = func_->CreateBlock("if.else");
|
||||||
|
auto* merge_bb = func_->CreateBlock("if.end");
|
||||||
|
EmitCondBr(ctx->cond(), then_bb, else_bb);
|
||||||
|
|
||||||
|
builder_.SetInsertPoint(then_bb);
|
||||||
|
auto then_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
|
||||||
|
if (then_flow != BlockFlow::Terminated) {
|
||||||
|
builder_.CreateBr(merge_bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder_.SetInsertPoint(else_bb);
|
||||||
|
if (ctx->stmt(1)) {
|
||||||
|
auto else_flow = std::any_cast<BlockFlow>(ctx->stmt(1)->accept(this));
|
||||||
|
if (else_flow != BlockFlow::Terminated) {
|
||||||
|
builder_.CreateBr(merge_bb);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
builder_.CreateBr(merge_bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder_.SetInsertPoint(merge_bb);
|
||||||
|
return BlockFlow::Continue;
|
||||||
|
}
|
||||||
|
if (ctx->WHILE()) {
|
||||||
|
auto* cond_bb = func_->CreateBlock("while.cond");
|
||||||
|
auto* body_bb = func_->CreateBlock("while.body");
|
||||||
|
auto* end_bb = func_->CreateBlock("while.end");
|
||||||
|
builder_.CreateBr(cond_bb);
|
||||||
|
|
||||||
|
builder_.SetInsertPoint(cond_bb);
|
||||||
|
EmitCondBr(ctx->cond(), body_bb, end_bb);
|
||||||
|
|
||||||
std::any IRGenImpl::visitReturnStmt(SysYParser::ReturnStmtContext* ctx) {
|
builder_.SetInsertPoint(body_bb);
|
||||||
if (!ctx) {
|
PushLoop(end_bb, cond_bb);
|
||||||
throw std::runtime_error(FormatError("irgen", "缺少 return 语句"));
|
auto body_flow = std::any_cast<BlockFlow>(ctx->stmt(0)->accept(this));
|
||||||
|
PopLoop();
|
||||||
|
if (body_flow != BlockFlow::Terminated) {
|
||||||
|
builder_.CreateBr(cond_bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
builder_.SetInsertPoint(end_bb);
|
||||||
|
return BlockFlow::Continue;
|
||||||
|
}
|
||||||
|
if (ctx->BREAK()) {
|
||||||
|
auto* target = CurrentBreak();
|
||||||
|
if (!target) {
|
||||||
|
throw std::runtime_error(FormatError("irgen", "break 不在循环内"));
|
||||||
}
|
}
|
||||||
|
builder_.CreateBr(target);
|
||||||
|
return BlockFlow::Terminated;
|
||||||
|
}
|
||||||
|
if (ctx->CONTINUE()) {
|
||||||
|
auto* target = CurrentContinue();
|
||||||
|
if (!target) {
|
||||||
|
throw std::runtime_error(FormatError("irgen", "continue 不在循环内"));
|
||||||
|
}
|
||||||
|
builder_.CreateBr(target);
|
||||||
|
return BlockFlow::Terminated;
|
||||||
|
}
|
||||||
|
if (ctx->RETURN()) {
|
||||||
if (!ctx->exp()) {
|
if (!ctx->exp()) {
|
||||||
throw std::runtime_error(FormatError("irgen", "return 缺少表达式"));
|
builder_.CreateRetVoid();
|
||||||
|
return BlockFlow::Terminated;
|
||||||
|
}
|
||||||
|
ir::Value* v = EvalExp(ctx->exp());
|
||||||
|
auto ret_ty = func_->GetReturnType();
|
||||||
|
if (ret_ty->IsFloat() && v->IsInt32()) {
|
||||||
|
v = CastToFloat(v);
|
||||||
|
} else if (ret_ty->IsInt32() && v->IsFloat()) {
|
||||||
|
v = CastToInt(v);
|
||||||
}
|
}
|
||||||
ir::Value* v = EvalExpr(*ctx->exp());
|
|
||||||
builder_.CreateRet(v);
|
builder_.CreateRet(v);
|
||||||
return BlockFlow::Terminated;
|
return BlockFlow::Terminated;
|
||||||
}
|
}
|
||||||
|
if (ctx->exp()) {
|
||||||
|
EvalExp(ctx->exp());
|
||||||
|
}
|
||||||
|
return BlockFlow::Continue;
|
||||||
|
}
|
||||||
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
@ -1,4 +1,61 @@
|
|||||||
// SysY 运行库实现:
|
#include <stdio.h>
|
||||||
// - 按实验/评测规范提供 I/O 等函数实现
|
|
||||||
// - 与编译器生成的目标代码链接,支撑运行时行为
|
int getint() {
|
||||||
|
int v = 0;
|
||||||
|
if (scanf("%d", &v) != 1) return 0;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getch() { return getchar(); }
|
||||||
|
|
||||||
|
int getarray(int a[]) {
|
||||||
|
int n = 0;
|
||||||
|
if (scanf("%d", &n) != 1) return 0;
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
scanf("%d", &a[i]);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void putint(int x) { printf("%d", x); }
|
||||||
|
|
||||||
|
void putch(int x) { putchar(x); }
|
||||||
|
|
||||||
|
void putarray(int n, int a[]) {
|
||||||
|
printf("%d:", n);
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
printf(" %d", a[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
float getfloat() {
|
||||||
|
float v = 0.0f;
|
||||||
|
if (scanf("%f", &v) != 1) return 0.0f;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getfarray(float a[]) {
|
||||||
|
int n = 0;
|
||||||
|
if (scanf("%d", &n) != 1) return 0;
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
scanf("%f", &a[i]);
|
||||||
|
}
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
void putfloat(float x) { printf("%a", x); }
|
||||||
|
|
||||||
|
void putfarray(int n, float a[]) {
|
||||||
|
printf("%d:", n);
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
printf(" %a", a[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Performance timing hooks (no-op stubs for correctness testing).
|
||||||
|
void starttime() {}
|
||||||
|
|
||||||
|
void stoptime() {}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in new issue