fix: 修复编译问题以支持测评程序直接编译

1. 修改所有include路径为相对于项目根目录
   - frontend/ -> src/frontend/
   - ir/ -> include/ir/
   - irgen/ -> include/irgen/
   - sem/ -> include/sem/
   - mir/ -> include/mir/
   - utils/ -> include/utils/

2. 生成ANTLR代码到src/frontend/目录
   - 将SysYLexer/Parser等生成文件放在源码目录
   - 移除third_party/antlr4-runtime避免重复定义

3. 添加build.sh和Makefile支持直接编译

4. 修复main.cpp的PassManager调用
zhm
安峻邑 2 weeks ago
parent fa028a3c67
commit ac4be4ec7a

@ -0,0 +1,51 @@
# Makefile for SysY Compiler
# Competition build script
# Usage: make
CXX = clang++
CXXFLAGS = -std=c++17 -O2 -Wall -Wextra
LDFLAGS = -lpthread
# Project root
ROOT = $(shell pwd)
# Include paths
INCLUDES = -I$(ROOT)/include \
-I$(ROOT)/src \
-I$(ROOT)/third_party/antlr4-runtime-4.13.2/runtime/src \
-I$(ROOT)/build/generated/antlr4/src/antlr4
# Source files
SRCDIR = $(ROOT)/src
ANTLR_RUNTIME = $(ROOT)/third_party/antlr4-runtime-4.13.2/runtime/src
GENERATED = $(ROOT)/build/generated/antlr4/src/antlr4
SRC = $(shell find $(SRCDIR) -name '*.cpp' 2>/dev/null)
ANTLR_SRC = $(shell find $(ANTLR_RUNTIME) -name '*.cpp' 2>/dev/null)
GEN_SRC = $(shell find $(GENERATED) -name '*.cpp' 2>/dev/null || echo "")
# Target
TARGET = $(ROOT)/compiler
.PHONY: all clean generate
all: generate $(TARGET)
generate:
@mkdir -p $(ROOT)/build/generated/antlr4
@if [ ! -f "$(GENERATED)/SysYParser.h" ]; then \
echo "[ANTLR4] Generating parser..."; \
java -jar $(ROOT)/third_party/antlr-4.13.2-complete.jar \
-Dlanguage=Cpp -visitor \
-o $(ROOT)/build/generated/antlr4 \
$(ROOT)/src/frontend/SysY.g4; \
fi
$(TARGET): $(SRC) $(ANTLR_SRC) $(GEN_SRC)
@echo "[CXX] Linking $(TARGET)..."
$(CXX) $(CXXFLAGS) $(INCLUDES) \
$(SRC) $(ANTLR_SRC) $(GEN_SRC) \
$(LDFLAGS) -o $@
clean:
rm -rf build $(TARGET)

@ -0,0 +1,116 @@
#!/usr/bin/env bash
# ============================================================================
# SysY Compiler - Competition Build Script
# ============================================================================
# This script compiles the SysY compiler for the 2026 Compiler Design Competition.
# Usage:
# ./build.sh - Build the compiler
# ./build.sh clean - Clean build artifacts
# ============================================================================
set -euo pipefail
PROJ_DIR="$(cd "$(dirname "$0")" && pwd)"
BUILD_DIR="${PROJ_DIR}/build"
BIN_DIR="${BUILD_DIR}/bin"
ANTLR4_GENERATED="${BUILD_DIR}/generated/antlr4/src/antlr4"
# Compiler settings
CXX="${CXX:-clang++}"
CXXSTD="-std=c++17"
CXXFLAGS="${CXXFLAGS:--O2 -Wall -Wextra -Wpedantic}"
LDFLAGS="-lpthread"
# Include paths (all relative to project root)
INCLUDES=(
"-I${PROJ_DIR}/include"
"-I${PROJ_DIR}/src"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/atn"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/dfa"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/internal"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/misc"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/support"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/tree"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/tree/pattern"
"-I${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src/tree/xpath"
"-I${ANTLR4_GENERATED}"
)
# ============================================================================
# Functions
# ============================================================================
generate_antlr() {
echo "[ANTLR4] Generating parser code..."
mkdir -p "${ANTLR4_GENERATED}"
if [ ! -f "${ANTLR4_GENERATED}/SysYParser.h" ]; then
java -jar "${PROJ_DIR}/third_party/antlr-4.13.2-complete.jar" \
-Dlanguage=Cpp \
-o "${BUILD_DIR}/generated/antlr4" \
-visitor \
"${PROJ_DIR}/src/frontend/SysY.g4" 2>/dev/null || {
echo "Warning: ANTLR4 generation failed, checking for existing files..."
if [ ! -f "${ANTLR4_GENERATED}/SysYParser.h" ]; then
echo "Error: No generated parser code found."
exit 1
fi
}
else
echo "[ANTLR4] Parser code already exists, skipping."
fi
}
build() {
echo "[CXX] Compiling compiler..."
mkdir -p "${BIN_DIR}"
# Collect source files
SRC_FILES=()
while IFS= read -r -d '' file; do
SRC_FILES+=("$file")
done < <(find "${PROJ_DIR}/src" -name '*.cpp' -print0)
ANTLR_RUNTIME_FILES=()
while IFS= read -r -d '' file; do
ANTLR_RUNTIME_FILES+=("$file")
done < <(find "${PROJ_DIR}/third_party/antlr4-runtime-4.13.2/runtime/src" -name '*.cpp' -print0)
GENERATED_FILES=()
if [ -d "${ANTLR4_GENERATED}" ]; then
while IFS= read -r -d '' file; do
GENERATED_FILES+=("$file")
done < <(find "${ANTLR4_GENERATED}" -name '*.cpp' -print0 2>/dev/null || true)
fi
# Compile
"${CXX}" ${CXXSTD} ${CXXFLAGS} \
"${INCLUDES[@]}" \
"${SRC_FILES[@]}" \
"${ANTLR_RUNTIME_FILES[@]}" \
"${GENERATED_FILES[@]}" \
${LDFLAGS} \
-o "${BIN_DIR}/compiler"
echo "[INFO] Build successful: ${BIN_DIR}/compiler"
}
clean() {
echo "[CLEAN] Removing build directory..."
rm -rf "${BUILD_DIR}"
}
# ============================================================================
# Main
# ============================================================================
case "${1:-}" in
clean)
clean
;;
*)
generate_antlr
build
;;
esac

@ -0,0 +1,47 @@
#!/bin/bash
# fix_includes.sh - 修改所有include路径为相对于项目根目录
set -euo pipefail
cd "$(dirname "$0")"
echo "Fixing include paths in all source files..."
# 处理 src/ 下所有层级的文件
for dir in src src/frontend src/ir src/ir/passes src/ir/analysis src/irgen src/sem src/mir src/mir/passes src/utils; do
[[ ! -d "$dir" ]] && continue
# 计算相对前缀
case "$dir" in
src) prefix="." ;;
src/frontend|src/utils) prefix=".." ;;
src/ir|src/irgen|src/sem|src/mir) prefix="../.." ;;
src/ir/passes|src/ir/analysis|src/mir/passes) prefix="../../.." ;;
*) continue ;;
esac
find "$dir" -maxdepth 1 -name '*.cpp' -o -name '*.h' | while read -r f; do
[ "$f" = "src/main.cpp" ] && continue
# 修改 include 路径
sed -i "s|#include \"ir/|#include \"${prefix}/include/ir/|g" "$f"
sed -i "s|#include \"irgen/|#include \"${prefix}/include/irgen/|g" "$f"
sed -i "s|#include \"sem/|#include \"${prefix}/include/sem/|g" "$f"
sed -i "s|#include \"mir/|#include \"${prefix}/include/mir/|g" "$f"
sed -i "s|#include \"utils/|#include \"${prefix}/include/utils/|g" "$f"
sed -i "s|#include \"frontend/|#include \"${prefix}/src/frontend/|g" "$f"
echo " Fixed: $f"
done
done
# 处理 include/ 下的文件
for dir in include include/ir include/irgen include/sem include/mir include/utils; do
[[ ! -d "$dir" ]] && continue
find "$dir" -maxdepth 1 -name '*.h' | while read -r f; do
sed -i "s|#include \"ir/|#include \"ir/|g" "$f" # include下的不用改
sed -i "s|#include \"frontend/|#include \"../src/frontend/|g" "$f"
echo " Fixed: $f"
done
done
echo "Done!"

@ -0,0 +1,234 @@
#!/usr/bin/env bash
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "用法: $0 <input.sy> [output_dir] [--run] [-O]" >&2
exit 1
fi
input=$1
out_dir="test/test_result/asm"
run_exec=false
optimize=false
input_dir=$(dirname "$input")
shift
while [[ $# -gt 0 ]]; do
case "$1" in
--run)
run_exec=true
;;
-O|--optimize)
optimize=true
;;
*)
out_dir="$1"
;;
esac
shift
done
if [[ ! -f "$input" ]]; then
echo "输入文件不存在: $input" >&2
exit 1
fi
compiler="./build/bin/compiler"
if [[ ! -x "$compiler" ]]; then
echo "未找到编译器: $compiler ,请先构建。" >&2
exit 1
fi
if ! command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then
echo "未找到 aarch64-linux-gnu-gcc无法汇编/链接。" >&2
exit 1
fi
if ! command -v qemu-aarch64 >/dev/null 2>&1 && [[ "$run_exec" == true ]]; then
echo "未找到 qemu-aarch64无法运行生成的可执行文件。" >&2
exit 1
fi
find_runtime() {
if [[ -n "${SYSY_RUNTIME:-}" ]]; then
if [[ -f "$SYSY_RUNTIME" ]]; then
printf '%s\n' "$SYSY_RUNTIME"
return 0
fi
echo "环境变量 SYSY_RUNTIME 指向的文件不存在: $SYSY_RUNTIME" >&2
return 1
fi
local candidates=(
"./sylib/sylib.c"
"./sylib.c"
"./runtime/sylib.c"
"./lib/sylib.c"
)
local candidate
for candidate in "${candidates[@]}"; do
if [[ -f "$candidate" ]]; then
printf '%s\n' "$candidate"
return 0
fi
done
local found=""
found=$(find . \
-path './build' -prune -o \
-path './.git' -prune -o \
-type f -name 'sylib.c' -print | head -n 1)
if [[ -n "$found" ]]; then
printf '%s\n' "$found"
return 0
fi
return 1
}
# 获取当前时间戳(毫秒级)
get_timestamp_ms() {
if [[ "$OSTYPE" == "darwin"* ]]; then
if command -v gdate >/dev/null 2>&1; then
gdate +%s%3N
else
perl -MTime::HiRes -e 'printf "%d\n", Time::HiRes::time() * 1000' 2>/dev/null || date +%s%3N
fi
else
date +%s%3N 2>/dev/null || date +%s000
fi
}
runtime_src="$(find_runtime || true)"
if [[ -z "$runtime_src" ]]; then
echo "未找到运行时库源码 sylib.c" >&2
echo "可以显式指定SYSY_RUNTIME=/你的路径/sylib.c $0 <input.sy> [output_dir] [--run]" >&2
exit 1
fi
runtime_cache_dir="./build/test_runtime"
runtime_obj="$runtime_cache_dir/sylib.o"
mkdir -p "$runtime_cache_dir"
# 编译运行时库(如果需要)
if [[ ! -f "$runtime_obj" || "$runtime_src" -nt "$runtime_obj" ]]; then
aarch64-linux-gnu-gcc -O2 -c "$runtime_src" -o "$runtime_obj"
fi
mkdir -p "$out_dir"
base=$(basename "$input")
stem=${base%.sy}
asm_file="$out_dir/$stem.s"
exe="$out_dir/$stem"
stdin_file="$input_dir/$stem.in"
expected_file="$input_dir/$stem.out"
# 记录编译(生成汇编)开始时间
compile_start=$(get_timestamp_ms)
if [[ "$optimize" == true ]]; then
"$compiler" -O --emit-asm "$input" > "$asm_file"
else
"$compiler" --emit-asm "$input" > "$asm_file"
fi
# 记录编译结束时间
compile_end=$(get_timestamp_ms)
compile_time=$((compile_end - compile_start))
# 记录汇编+链接开始时间
assemble_start=$(get_timestamp_ms)
aarch64-linux-gnu-gcc "$asm_file" "$runtime_obj" -o "$exe"
# 记录汇编+链接结束时间
assemble_end=$(get_timestamp_ms)
assemble_time=$((assemble_end - assemble_start))
if [[ "$run_exec" == true ]]; then
stdout_file="$out_dir/$stem.stdout"
actual_file="$out_dir/$stem.actual.out"
set +e
exec_start=$(get_timestamp_ms)
if [[ -f "$stdin_file" ]]; then
qemu-aarch64 -L /usr/aarch64-linux-gnu -s 104857600 "$exe" < "$stdin_file" > "$stdout_file"
else
qemu-aarch64 -L /usr/aarch64-linux-gnu -s 104857600 "$exe" < /dev/null > "$stdout_file"
fi
status=$?
exec_end=$(get_timestamp_ms)
exec_time=$((exec_end - exec_start))
set -e
# 计算总时间
total_time=$((compile_time + assemble_time + exec_time))
# 保存运行时间到文件(只保存时间数值)
time_file="$out_dir/${stem}_time.txt"
echo "$total_time" > "$time_file"
# 保存输出(用于比对)
{
cat "$stdout_file"
if [[ -s "$stdout_file" ]] && (( $(tail -c 1 "$stdout_file" | wc -l) == 0 )); then
printf '\n'
fi
printf '%s\n' "$status"
} > "$actual_file"
# 比对输出
if [[ -f "$expected_file" ]]; then
temp_expected="$out_dir/$stem.expected.tmp"
temp_actual="$out_dir/$stem.actual.tmp"
if command -v python3 >/dev/null 2>&1; then
if python3 - "$expected_file" "$actual_file" <<'PY'
import sys
from pathlib import Path
def canon(path: str) -> bytes:
data = Path(path).read_bytes()
data = data.replace(b'\r\n', b'\n')
while data.endswith(b'\n'):
data = data[:-1]
lines = data.split(b'\n')
lines = [line.rstrip() for line in lines]
return b'\n'.join(lines)
sys.exit(0 if canon(sys.argv[1]) == canon(sys.argv[2]) else 1)
PY
then
rm -f "$temp_expected" "$temp_actual" 2>/dev/null
else
echo "输出不匹配: $expected_file" >&2
rm -f "$temp_expected" "$temp_actual" 2>/dev/null
exit 1
fi
else
tr -d '\r' < "$expected_file" > "$temp_expected"
tr -d '\r' < "$actual_file" > "$temp_actual"
if [[ -s "$temp_expected" ]] && (( $(tail -c 1 "$temp_expected" | wc -l) == 0 )); then
if [[ -s "$temp_actual" ]] && (( $(tail -c 1 "$temp_actual" | wc -l) == 1 )); then
truncate -s -1 "$temp_actual"
fi
fi
if diff -u "$temp_expected" "$temp_actual" > /dev/null 2>&1; then
rm -f "$temp_expected" "$temp_actual"
else
echo "输出不匹配: $expected_file" >&2
rm -f "$temp_expected" "$temp_actual"
exit 1
fi
fi
fi
fi

@ -0,0 +1,157 @@
#!/usr/bin/env bash
# ./scripts/verify_ir.sh test/test_case/functional/simple_add.sy test/test_result/function/ir --run
set -euo pipefail
if [[ $# -lt 1 ]]; then
echo "用法: $0 <input.sy> [output_dir] [--run] [-O]" >&2
exit 1
fi
out_dir="test/test_result/ir"
run_exec=false
optimize=false
input=""
while [[ $# -gt 0 ]]; do
case "$1" in
--run)
run_exec=true
;;
-O|--optimize)
optimize=true
;;
-*)
echo "未知选项: $1" >&2
exit 1
;;
*)
if [[ -z "$input" ]]; then
input="$1"
else
out_dir="$1"
fi
;;
esac
shift
done
if [[ -z "$input" ]]; then
echo "未指定输入文件" >&2
exit 1
fi
input_dir=$(dirname "$input")
if [[ ! -f "$input" ]]; then
echo "输入文件不存在: $input" >&2
exit 1
fi
compiler="./build/bin/compiler"
if [[ ! -x "$compiler" ]]; then
echo "未找到编译器: $compiler ,请先构建(如: mkdir -p build && cd build && cmake .. && make -j" >&2
exit 1
fi
mkdir -p "$out_dir"
base=$(basename "$input")
stem=${base%.sy}
out_file="$out_dir/$stem.ll"
stdin_file="$input_dir/$stem.in"
expected_file="$input_dir/$stem.out"
# 记录编译开始时间
compile_start=$(date +%s%N)
if [[ "$optimize" == true ]]; then
"$compiler" -O --emit-ir "$input" > "$out_file"
else
"$compiler" --emit-ir "$input" > "$out_file"
fi
# 记录编译结束时间
compile_end=$(date +%s%N)
compile_time=$(( ($compile_end - $compile_start) / 1000000 ))
if [[ "$run_exec" == true ]]; then
if ! command -v llc >/dev/null 2>&1; then
echo "未找到 llc无法运行 IR。请安装 LLVM。" >&2
exit 1
fi
if ! command -v clang >/dev/null 2>&1; then
echo "未找到 clang无法链接可执行文件。请安装 LLVM/Clang。" >&2
exit 1
fi
obj="$out_dir/$stem.o"
exe="$out_dir/$stem"
stdout_file="$out_dir/$stem.stdout"
actual_file="$out_dir/$stem.actual.out"
sylib_obj="$out_dir/sylib.o"
# 记录链接开始时间
link_start=$(date +%s%N)
if [[ ! -f "$sylib_obj" ]]; then
gcc -c sylib/sylib.c -o "$sylib_obj"
fi
llc -O0 -filetype=obj "$out_file" -o "$obj"
clang "$obj" "$sylib_obj" -o "$exe"
# 记录链接结束时间
link_end=$(date +%s%N)
link_time=$(( ($link_end - $link_start) / 1000000 ))
# 记录执行开始时间
exec_start=$(date +%s%N)
set +e
if [[ -f "$stdin_file" ]]; then
(ulimit -s 65536 && "$exe" < "$stdin_file" > "$stdout_file")
else
(ulimit -s 65536 && "$exe" > "$stdout_file")
fi
status=$?
set -e
# 记录执行结束时间
exec_end=$(date +%s%N)
exec_time=$(( ($exec_end - $exec_start) / 1000000 ))
# 保存运行时间到文件(只保存执行时间,不包含编译和链接时间)
time_file="$out_dir/${stem}_time.txt"
echo "$exec_time" > "$time_file"
# 保存输出(用于比对)
{
cat "$stdout_file"
# 确保 stdout 以换行结尾
if [[ -s "$stdout_file" ]] && (( $(tail -c 1 "$stdout_file" | wc -l) == 0 )); then
printf '\n'
fi
printf '%s\n' "$status"
} > "$actual_file"
# 比对输出
if [[ -f "$expected_file" ]]; then
temp_expected="$out_dir/$stem.expected.tmp"
temp_actual="$out_dir/$stem.actual.tmp"
tr -d '\r' < "$expected_file" > "$temp_expected"
tr -d '\r' < "$actual_file" > "$temp_actual"
if [[ -s "$temp_expected" ]] && (( $(tail -c 1 "$temp_expected" | wc -l) == 0 )); then
if [[ -s "$temp_actual" ]] && (( $(tail -c 1 "$temp_actual" | wc -l) == 1 )); then
truncate -s -1 "$temp_actual"
fi
fi
if diff -u "$temp_expected" "$temp_actual" > /dev/null 2>&1; then
rm -f "$temp_expected" "$temp_actual"
else
echo "输出不匹配: $expected_file" >&2
rm -f "$temp_expected" "$temp_actual"
exit 1
fi
fi
fi

@ -1,228 +0,0 @@
// SysY 子集语法:支持形如
// int main() { int a = 1; int b = 2; return a + b; }
// 的最小返回表达式编译。
// 后续需要自行添加
grammar SysY;
compUnit
: (funcDef|decl)+ EOF
;
funcDef
: funcType Ident L_PAREN (funcFParams)? R_PAREN block
;
funcType
: Void | Int | Float
;
funcFParams
: funcFParam (Comma funcFParam)*
;
funcFParam
: bType Ident (L_BRACKET R_BRACKET (L_BRACKET exp R_BRACKET)*)?
;
block
: L_BRACE (blockItem)* R_BRACE
;
blockItem
: decl
| stmt
;
decl
: varDecl | constDecl
;
constDecl
: Const bType constDef (Comma constDef)* Semi
;
bType
: Int | Float
;
constDef
: Ident (L_BRACKET constExp R_BRACKET)* Assign constInitVal
;
constInitVal
: constExp
| L_BRACE ( constInitVal (Comma constInitVal)* )? R_BRACE
;
stmt
: lVal Assign exp Semi
| (exp)? Semi
| block
| If L_PAREN cond R_PAREN stmt ( Else stmt )?
| While L_PAREN cond R_PAREN stmt
| Break Semi
| Continue Semi
| Return (exp)? Semi
;
cond
: lOrExp
;
lVal
: Ident (L_BRACKET exp R_BRACKET)*
;
primaryExp
: L_PAREN exp R_PAREN | lVal | number
;
number
: IntConst | FloatConst
;
unaryExp
: primaryExp
| Ident L_PAREN (funcRParams)? R_PAREN
| unaryOp unaryExp
;
unaryOp
: AddOp | SubOp | NotOp
;
funcRParams
: exp (Comma exp)*
;
mulExp
: unaryExp | mulExp (MulOp | DivOp | ModOp) unaryExp
;
addExp
: mulExp | addExp (AddOp | SubOp) mulExp
;
relExp
: addExp | relExp (LtOp | GtOp | LeOp | GeOp) addExp
;
eqExp
: relExp | eqExp (EqOp | NeOp) relExp
;
lAndExp
: eqExp | lAndExp AndOp eqExp
;
lOrExp
: lAndExp | lOrExp OrOp lAndExp
;
constExp
: addExp
;
varDecl
: bType varDef (Comma varDef)* Semi
;
varDef
: Ident (L_BRACKET constExp R_BRACKET)*
| Ident (L_BRACKET constExp R_BRACKET)* Assign initVal
;
initVal
: exp | L_BRACE ( initVal (Comma initVal)* )? R_BRACE
;
exp
: addExp
;
// 关键字
Void : 'void';
Int : 'int';
Float : 'float';
Const : 'const';
If : 'if';
Else : 'else';
While : 'while';
Break : 'break';
Continue : 'continue';
Return : 'return';
// 符号
AddOp : '+';
SubOp : '-';
Assign : '=';
MulOp : '*';
DivOp : '/';
ModOp : '%';
NotOp : '!';
AndOp : '&&';
OrOp : '||';
EqOp : '==';
NeOp : '!=';
LtOp : '<';
GtOp : '>';
LeOp : '<=';
GeOp : '>=';
Semi : ';';
Comma : ',';
L_PAREN : '(';
R_PAREN : ')';
L_BRACE : '{';
R_BRACE : '}';
L_BRACKET: '[';
R_BRACKET: ']';
Ident
: [a-zA-Z_][a-zA-Z_0-9]*
;
IntConst
: '0' [xX] [0-9a-fA-F]+
| '0' [0-7]*
| [1-9] [0-9]*
;
FloatConst
: DecFloatConst
| HexFloatConst
;
fragment DecFloatConst
: DecFrac DecExp?
| [0-9]+ DecExp
;
fragment DecFrac
: [0-9]+ '.' [0-9]*
| '.' [0-9]+
;
fragment DecExp
: [eE] [+\-]? [0-9]+
;
fragment HexFloatConst
: '0' [xX] HexFrac BinExp
| '0' [xX] [0-9a-fA-F]+ BinExp
;
fragment HexFrac
: [0-9a-fA-F]+ '.' [0-9a-fA-F]*
| '.' [0-9a-fA-F]+
;
fragment BinExp
: [pP] [+\-]? [0-9]+
;
WS
: [ \t\r\n]+ -> skip
;
COMMENT
: '//' ~[\r\n]* -> skip
;
BLOCK_COMMENT
: '/*' .*? '*/' -> skip
;

@ -1,5 +1,5 @@
// 调用前端解析流程,返回语法树。
#include "frontend/AntlrDriver.h"
#include "src/frontend/AntlrDriver.h"
#include <fstream>
#include <sstream>
@ -9,7 +9,7 @@
#include "SysYLexer.h"
#include "SysYParser.h"
#include "antlr4-runtime.h"
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace {

@ -1,4 +1,4 @@
#include "frontend/SyntaxTreePrinter.h"
#include "src/frontend/SyntaxTreePrinter.h"
#include <string>

@ -0,0 +1,7 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#include "SysYBaseListener.h"

@ -0,0 +1,119 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
#include "SysYListener.h"
/**
* This class provides an empty implementation of SysYListener,
* which can be extended to create a listener which only needs to handle a subset
* of the available methods.
*/
class SysYBaseListener : public SysYListener {
public:
virtual void enterCompUnit(SysYParser::CompUnitContext * /*ctx*/) override { }
virtual void exitCompUnit(SysYParser::CompUnitContext * /*ctx*/) override { }
virtual void enterFuncDef(SysYParser::FuncDefContext * /*ctx*/) override { }
virtual void exitFuncDef(SysYParser::FuncDefContext * /*ctx*/) override { }
virtual void enterFuncType(SysYParser::FuncTypeContext * /*ctx*/) override { }
virtual void exitFuncType(SysYParser::FuncTypeContext * /*ctx*/) override { }
virtual void enterFuncFParams(SysYParser::FuncFParamsContext * /*ctx*/) override { }
virtual void exitFuncFParams(SysYParser::FuncFParamsContext * /*ctx*/) override { }
virtual void enterFuncFParam(SysYParser::FuncFParamContext * /*ctx*/) override { }
virtual void exitFuncFParam(SysYParser::FuncFParamContext * /*ctx*/) override { }
virtual void enterBlock(SysYParser::BlockContext * /*ctx*/) override { }
virtual void exitBlock(SysYParser::BlockContext * /*ctx*/) override { }
virtual void enterBlockItem(SysYParser::BlockItemContext * /*ctx*/) override { }
virtual void exitBlockItem(SysYParser::BlockItemContext * /*ctx*/) override { }
virtual void enterDecl(SysYParser::DeclContext * /*ctx*/) override { }
virtual void exitDecl(SysYParser::DeclContext * /*ctx*/) override { }
virtual void enterConstDecl(SysYParser::ConstDeclContext * /*ctx*/) override { }
virtual void exitConstDecl(SysYParser::ConstDeclContext * /*ctx*/) override { }
virtual void enterBType(SysYParser::BTypeContext * /*ctx*/) override { }
virtual void exitBType(SysYParser::BTypeContext * /*ctx*/) override { }
virtual void enterConstDef(SysYParser::ConstDefContext * /*ctx*/) override { }
virtual void exitConstDef(SysYParser::ConstDefContext * /*ctx*/) override { }
virtual void enterConstInitVal(SysYParser::ConstInitValContext * /*ctx*/) override { }
virtual void exitConstInitVal(SysYParser::ConstInitValContext * /*ctx*/) override { }
virtual void enterStmt(SysYParser::StmtContext * /*ctx*/) override { }
virtual void exitStmt(SysYParser::StmtContext * /*ctx*/) override { }
virtual void enterCond(SysYParser::CondContext * /*ctx*/) override { }
virtual void exitCond(SysYParser::CondContext * /*ctx*/) override { }
virtual void enterLVal(SysYParser::LValContext * /*ctx*/) override { }
virtual void exitLVal(SysYParser::LValContext * /*ctx*/) override { }
virtual void enterPrimaryExp(SysYParser::PrimaryExpContext * /*ctx*/) override { }
virtual void exitPrimaryExp(SysYParser::PrimaryExpContext * /*ctx*/) override { }
virtual void enterNumber(SysYParser::NumberContext * /*ctx*/) override { }
virtual void exitNumber(SysYParser::NumberContext * /*ctx*/) override { }
virtual void enterUnaryExp(SysYParser::UnaryExpContext * /*ctx*/) override { }
virtual void exitUnaryExp(SysYParser::UnaryExpContext * /*ctx*/) override { }
virtual void enterUnaryOp(SysYParser::UnaryOpContext * /*ctx*/) override { }
virtual void exitUnaryOp(SysYParser::UnaryOpContext * /*ctx*/) override { }
virtual void enterFuncRParams(SysYParser::FuncRParamsContext * /*ctx*/) override { }
virtual void exitFuncRParams(SysYParser::FuncRParamsContext * /*ctx*/) override { }
virtual void enterMulExp(SysYParser::MulExpContext * /*ctx*/) override { }
virtual void exitMulExp(SysYParser::MulExpContext * /*ctx*/) override { }
virtual void enterAddExp(SysYParser::AddExpContext * /*ctx*/) override { }
virtual void exitAddExp(SysYParser::AddExpContext * /*ctx*/) override { }
virtual void enterRelExp(SysYParser::RelExpContext * /*ctx*/) override { }
virtual void exitRelExp(SysYParser::RelExpContext * /*ctx*/) override { }
virtual void enterEqExp(SysYParser::EqExpContext * /*ctx*/) override { }
virtual void exitEqExp(SysYParser::EqExpContext * /*ctx*/) override { }
virtual void enterLAndExp(SysYParser::LAndExpContext * /*ctx*/) override { }
virtual void exitLAndExp(SysYParser::LAndExpContext * /*ctx*/) override { }
virtual void enterLOrExp(SysYParser::LOrExpContext * /*ctx*/) override { }
virtual void exitLOrExp(SysYParser::LOrExpContext * /*ctx*/) override { }
virtual void enterConstExp(SysYParser::ConstExpContext * /*ctx*/) override { }
virtual void exitConstExp(SysYParser::ConstExpContext * /*ctx*/) override { }
virtual void enterVarDecl(SysYParser::VarDeclContext * /*ctx*/) override { }
virtual void exitVarDecl(SysYParser::VarDeclContext * /*ctx*/) override { }
virtual void enterVarDef(SysYParser::VarDefContext * /*ctx*/) override { }
virtual void exitVarDef(SysYParser::VarDefContext * /*ctx*/) override { }
virtual void enterInitVal(SysYParser::InitValContext * /*ctx*/) override { }
virtual void exitInitVal(SysYParser::InitValContext * /*ctx*/) override { }
virtual void enterExp(SysYParser::ExpContext * /*ctx*/) override { }
virtual void exitExp(SysYParser::ExpContext * /*ctx*/) override { }
virtual void enterEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { }
virtual void exitEveryRule(antlr4::ParserRuleContext * /*ctx*/) override { }
virtual void visitTerminal(antlr4::tree::TerminalNode * /*node*/) override { }
virtual void visitErrorNode(antlr4::tree::ErrorNode * /*node*/) override { }
};

@ -0,0 +1,7 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#include "SysYBaseVisitor.h"

@ -0,0 +1,144 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
#include "SysYVisitor.h"
/**
* This class provides an empty implementation of SysYVisitor, which can be
* extended to create a visitor which only needs to handle a subset of the available methods.
*/
class SysYBaseVisitor : public SysYVisitor {
public:
virtual std::any visitCompUnit(SysYParser::CompUnitContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncDef(SysYParser::FuncDefContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncType(SysYParser::FuncTypeContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncFParams(SysYParser::FuncFParamsContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncFParam(SysYParser::FuncFParamContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitBlock(SysYParser::BlockContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitBlockItem(SysYParser::BlockItemContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitDecl(SysYParser::DeclContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstDecl(SysYParser::ConstDeclContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitBType(SysYParser::BTypeContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstDef(SysYParser::ConstDefContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstInitVal(SysYParser::ConstInitValContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitStmt(SysYParser::StmtContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitCond(SysYParser::CondContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitLVal(SysYParser::LValContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitPrimaryExp(SysYParser::PrimaryExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitNumber(SysYParser::NumberContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitUnaryOp(SysYParser::UnaryOpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitFuncRParams(SysYParser::FuncRParamsContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitMulExp(SysYParser::MulExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitAddExp(SysYParser::AddExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitRelExp(SysYParser::RelExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitEqExp(SysYParser::EqExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitLAndExp(SysYParser::LAndExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitLOrExp(SysYParser::LOrExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitConstExp(SysYParser::ConstExpContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitVarDecl(SysYParser::VarDeclContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitVarDef(SysYParser::VarDefContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitInitVal(SysYParser::InitValContext *ctx) override {
return visitChildren(ctx);
}
virtual std::any visitExp(SysYParser::ExpContext *ctx) override {
return visitChildren(ctx);
}
};

@ -0,0 +1,271 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#include "SysYLexer.h"
using namespace antlr4;
using namespace antlr4;
namespace {
struct SysYLexerStaticData final {
SysYLexerStaticData(std::vector<std::string> ruleNames,
std::vector<std::string> channelNames,
std::vector<std::string> modeNames,
std::vector<std::string> literalNames,
std::vector<std::string> symbolicNames)
: ruleNames(std::move(ruleNames)), channelNames(std::move(channelNames)),
modeNames(std::move(modeNames)), literalNames(std::move(literalNames)),
symbolicNames(std::move(symbolicNames)),
vocabulary(this->literalNames, this->symbolicNames) {}
SysYLexerStaticData(const SysYLexerStaticData&) = delete;
SysYLexerStaticData(SysYLexerStaticData&&) = delete;
SysYLexerStaticData& operator=(const SysYLexerStaticData&) = delete;
SysYLexerStaticData& operator=(SysYLexerStaticData&&) = delete;
std::vector<antlr4::dfa::DFA> decisionToDFA;
antlr4::atn::PredictionContextCache sharedContextCache;
const std::vector<std::string> ruleNames;
const std::vector<std::string> channelNames;
const std::vector<std::string> modeNames;
const std::vector<std::string> literalNames;
const std::vector<std::string> symbolicNames;
const antlr4::dfa::Vocabulary vocabulary;
antlr4::atn::SerializedATNView serializedATN;
std::unique_ptr<antlr4::atn::ATN> atn;
};
::antlr4::internal::OnceFlag sysylexerLexerOnceFlag;
#if ANTLR4_USE_THREAD_LOCAL_CACHE
static thread_local
#endif
std::unique_ptr<SysYLexerStaticData> sysylexerLexerStaticData = nullptr;
void sysylexerLexerInitialize() {
#if ANTLR4_USE_THREAD_LOCAL_CACHE
if (sysylexerLexerStaticData != nullptr) {
return;
}
#else
assert(sysylexerLexerStaticData == nullptr);
#endif
auto staticData = std::make_unique<SysYLexerStaticData>(
std::vector<std::string>{
"Void", "Int", "Float", "Const", "If", "Else", "While", "Break", "Continue",
"Return", "AddOp", "SubOp", "Assign", "MulOp", "DivOp", "ModOp", "NotOp",
"AndOp", "OrOp", "EqOp", "NeOp", "LtOp", "GtOp", "LeOp", "GeOp", "Semi",
"Comma", "L_PAREN", "R_PAREN", "L_BRACE", "R_BRACE", "L_BRACKET",
"R_BRACKET", "Ident", "IntConst", "FloatConst", "DecFloatConst", "DecFrac",
"DecExp", "HexFloatConst", "HexFrac", "BinExp", "WS", "COMMENT", "BLOCK_COMMENT"
},
std::vector<std::string>{
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
},
std::vector<std::string>{
"DEFAULT_MODE"
},
std::vector<std::string>{
"", "'void'", "'int'", "'float'", "'const'", "'if'", "'else'", "'while'",
"'break'", "'continue'", "'return'", "'+'", "'-'", "'='", "'*'", "'/'",
"'%'", "'!'", "'&&'", "'||'", "'=='", "'!='", "'<'", "'>'", "'<='",
"'>='", "';'", "','", "'('", "')'", "'{'", "'}'", "'['", "']'"
},
std::vector<std::string>{
"", "Void", "Int", "Float", "Const", "If", "Else", "While", "Break",
"Continue", "Return", "AddOp", "SubOp", "Assign", "MulOp", "DivOp",
"ModOp", "NotOp", "AndOp", "OrOp", "EqOp", "NeOp", "LtOp", "GtOp",
"LeOp", "GeOp", "Semi", "Comma", "L_PAREN", "R_PAREN", "L_BRACE",
"R_BRACE", "L_BRACKET", "R_BRACKET", "Ident", "IntConst", "FloatConst",
"WS", "COMMENT", "BLOCK_COMMENT"
}
);
static const int32_t serializedATNSegment[] = {
4,0,39,351,6,-1,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,2,5,7,5,2,6,7,
6,2,7,7,7,2,8,7,8,2,9,7,9,2,10,7,10,2,11,7,11,2,12,7,12,2,13,7,13,2,14,
7,14,2,15,7,15,2,16,7,16,2,17,7,17,2,18,7,18,2,19,7,19,2,20,7,20,2,21,
7,21,2,22,7,22,2,23,7,23,2,24,7,24,2,25,7,25,2,26,7,26,2,27,7,27,2,28,
7,28,2,29,7,29,2,30,7,30,2,31,7,31,2,32,7,32,2,33,7,33,2,34,7,34,2,35,
7,35,2,36,7,36,2,37,7,37,2,38,7,38,2,39,7,39,2,40,7,40,2,41,7,41,2,42,
7,42,2,43,7,43,2,44,7,44,1,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,1,2,1,2,
1,2,1,2,1,2,1,2,1,3,1,3,1,3,1,3,1,3,1,3,1,4,1,4,1,4,1,5,1,5,1,5,1,5,1,
5,1,6,1,6,1,6,1,6,1,6,1,6,1,7,1,7,1,7,1,7,1,7,1,7,1,8,1,8,1,8,1,8,1,8,
1,8,1,8,1,8,1,8,1,9,1,9,1,9,1,9,1,9,1,9,1,9,1,10,1,10,1,11,1,11,1,12,
1,12,1,13,1,13,1,14,1,14,1,15,1,15,1,16,1,16,1,17,1,17,1,17,1,18,1,18,
1,18,1,19,1,19,1,19,1,20,1,20,1,20,1,21,1,21,1,22,1,22,1,23,1,23,1,23,
1,24,1,24,1,24,1,25,1,25,1,26,1,26,1,27,1,27,1,28,1,28,1,29,1,29,1,30,
1,30,1,31,1,31,1,32,1,32,1,33,1,33,5,33,203,8,33,10,33,12,33,206,9,33,
1,34,1,34,1,34,4,34,211,8,34,11,34,12,34,212,1,34,1,34,5,34,217,8,34,
10,34,12,34,220,9,34,1,34,1,34,5,34,224,8,34,10,34,12,34,227,9,34,3,34,
229,8,34,1,35,1,35,3,35,233,8,35,1,36,1,36,3,36,237,8,36,1,36,4,36,240,
8,36,11,36,12,36,241,1,36,3,36,245,8,36,1,37,4,37,248,8,37,11,37,12,37,
249,1,37,1,37,5,37,254,8,37,10,37,12,37,257,9,37,1,37,1,37,4,37,261,8,
37,11,37,12,37,262,3,37,265,8,37,1,38,1,38,3,38,269,8,38,1,38,4,38,272,
8,38,11,38,12,38,273,1,39,1,39,1,39,1,39,1,39,1,39,1,39,1,39,4,39,284,
8,39,11,39,12,39,285,1,39,3,39,289,8,39,1,40,4,40,292,8,40,11,40,12,40,
293,1,40,1,40,5,40,298,8,40,10,40,12,40,301,9,40,1,40,1,40,4,40,305,8,
40,11,40,12,40,306,3,40,309,8,40,1,41,1,41,3,41,313,8,41,1,41,4,41,316,
8,41,11,41,12,41,317,1,42,4,42,321,8,42,11,42,12,42,322,1,42,1,42,1,43,
1,43,1,43,1,43,5,43,331,8,43,10,43,12,43,334,9,43,1,43,1,43,1,44,1,44,
1,44,1,44,5,44,342,8,44,10,44,12,44,345,9,44,1,44,1,44,1,44,1,44,1,44,
1,343,0,45,1,1,3,2,5,3,7,4,9,5,11,6,13,7,15,8,17,9,19,10,21,11,23,12,
25,13,27,14,29,15,31,16,33,17,35,18,37,19,39,20,41,21,43,22,45,23,47,
24,49,25,51,26,53,27,55,28,57,29,59,30,61,31,63,32,65,33,67,34,69,35,
71,36,73,0,75,0,77,0,79,0,81,0,83,0,85,37,87,38,89,39,1,0,12,3,0,65,90,
95,95,97,122,4,0,48,57,65,90,95,95,97,122,2,0,88,88,120,120,3,0,48,57,
65,70,97,102,1,0,48,55,1,0,49,57,1,0,48,57,2,0,69,69,101,101,2,0,43,43,
45,45,2,0,80,80,112,112,3,0,9,10,13,13,32,32,2,0,10,10,13,13,371,0,1,
1,0,0,0,0,3,1,0,0,0,0,5,1,0,0,0,0,7,1,0,0,0,0,9,1,0,0,0,0,11,1,0,0,0,
0,13,1,0,0,0,0,15,1,0,0,0,0,17,1,0,0,0,0,19,1,0,0,0,0,21,1,0,0,0,0,23,
1,0,0,0,0,25,1,0,0,0,0,27,1,0,0,0,0,29,1,0,0,0,0,31,1,0,0,0,0,33,1,0,
0,0,0,35,1,0,0,0,0,37,1,0,0,0,0,39,1,0,0,0,0,41,1,0,0,0,0,43,1,0,0,0,
0,45,1,0,0,0,0,47,1,0,0,0,0,49,1,0,0,0,0,51,1,0,0,0,0,53,1,0,0,0,0,55,
1,0,0,0,0,57,1,0,0,0,0,59,1,0,0,0,0,61,1,0,0,0,0,63,1,0,0,0,0,65,1,0,
0,0,0,67,1,0,0,0,0,69,1,0,0,0,0,71,1,0,0,0,0,85,1,0,0,0,0,87,1,0,0,0,
0,89,1,0,0,0,1,91,1,0,0,0,3,96,1,0,0,0,5,100,1,0,0,0,7,106,1,0,0,0,9,
112,1,0,0,0,11,115,1,0,0,0,13,120,1,0,0,0,15,126,1,0,0,0,17,132,1,0,0,
0,19,141,1,0,0,0,21,148,1,0,0,0,23,150,1,0,0,0,25,152,1,0,0,0,27,154,
1,0,0,0,29,156,1,0,0,0,31,158,1,0,0,0,33,160,1,0,0,0,35,162,1,0,0,0,37,
165,1,0,0,0,39,168,1,0,0,0,41,171,1,0,0,0,43,174,1,0,0,0,45,176,1,0,0,
0,47,178,1,0,0,0,49,181,1,0,0,0,51,184,1,0,0,0,53,186,1,0,0,0,55,188,
1,0,0,0,57,190,1,0,0,0,59,192,1,0,0,0,61,194,1,0,0,0,63,196,1,0,0,0,65,
198,1,0,0,0,67,200,1,0,0,0,69,228,1,0,0,0,71,232,1,0,0,0,73,244,1,0,0,
0,75,264,1,0,0,0,77,266,1,0,0,0,79,288,1,0,0,0,81,308,1,0,0,0,83,310,
1,0,0,0,85,320,1,0,0,0,87,326,1,0,0,0,89,337,1,0,0,0,91,92,5,118,0,0,
92,93,5,111,0,0,93,94,5,105,0,0,94,95,5,100,0,0,95,2,1,0,0,0,96,97,5,
105,0,0,97,98,5,110,0,0,98,99,5,116,0,0,99,4,1,0,0,0,100,101,5,102,0,
0,101,102,5,108,0,0,102,103,5,111,0,0,103,104,5,97,0,0,104,105,5,116,
0,0,105,6,1,0,0,0,106,107,5,99,0,0,107,108,5,111,0,0,108,109,5,110,0,
0,109,110,5,115,0,0,110,111,5,116,0,0,111,8,1,0,0,0,112,113,5,105,0,0,
113,114,5,102,0,0,114,10,1,0,0,0,115,116,5,101,0,0,116,117,5,108,0,0,
117,118,5,115,0,0,118,119,5,101,0,0,119,12,1,0,0,0,120,121,5,119,0,0,
121,122,5,104,0,0,122,123,5,105,0,0,123,124,5,108,0,0,124,125,5,101,0,
0,125,14,1,0,0,0,126,127,5,98,0,0,127,128,5,114,0,0,128,129,5,101,0,0,
129,130,5,97,0,0,130,131,5,107,0,0,131,16,1,0,0,0,132,133,5,99,0,0,133,
134,5,111,0,0,134,135,5,110,0,0,135,136,5,116,0,0,136,137,5,105,0,0,137,
138,5,110,0,0,138,139,5,117,0,0,139,140,5,101,0,0,140,18,1,0,0,0,141,
142,5,114,0,0,142,143,5,101,0,0,143,144,5,116,0,0,144,145,5,117,0,0,145,
146,5,114,0,0,146,147,5,110,0,0,147,20,1,0,0,0,148,149,5,43,0,0,149,22,
1,0,0,0,150,151,5,45,0,0,151,24,1,0,0,0,152,153,5,61,0,0,153,26,1,0,0,
0,154,155,5,42,0,0,155,28,1,0,0,0,156,157,5,47,0,0,157,30,1,0,0,0,158,
159,5,37,0,0,159,32,1,0,0,0,160,161,5,33,0,0,161,34,1,0,0,0,162,163,5,
38,0,0,163,164,5,38,0,0,164,36,1,0,0,0,165,166,5,124,0,0,166,167,5,124,
0,0,167,38,1,0,0,0,168,169,5,61,0,0,169,170,5,61,0,0,170,40,1,0,0,0,171,
172,5,33,0,0,172,173,5,61,0,0,173,42,1,0,0,0,174,175,5,60,0,0,175,44,
1,0,0,0,176,177,5,62,0,0,177,46,1,0,0,0,178,179,5,60,0,0,179,180,5,61,
0,0,180,48,1,0,0,0,181,182,5,62,0,0,182,183,5,61,0,0,183,50,1,0,0,0,184,
185,5,59,0,0,185,52,1,0,0,0,186,187,5,44,0,0,187,54,1,0,0,0,188,189,5,
40,0,0,189,56,1,0,0,0,190,191,5,41,0,0,191,58,1,0,0,0,192,193,5,123,0,
0,193,60,1,0,0,0,194,195,5,125,0,0,195,62,1,0,0,0,196,197,5,91,0,0,197,
64,1,0,0,0,198,199,5,93,0,0,199,66,1,0,0,0,200,204,7,0,0,0,201,203,7,
1,0,0,202,201,1,0,0,0,203,206,1,0,0,0,204,202,1,0,0,0,204,205,1,0,0,0,
205,68,1,0,0,0,206,204,1,0,0,0,207,208,5,48,0,0,208,210,7,2,0,0,209,211,
7,3,0,0,210,209,1,0,0,0,211,212,1,0,0,0,212,210,1,0,0,0,212,213,1,0,0,
0,213,229,1,0,0,0,214,218,5,48,0,0,215,217,7,4,0,0,216,215,1,0,0,0,217,
220,1,0,0,0,218,216,1,0,0,0,218,219,1,0,0,0,219,229,1,0,0,0,220,218,1,
0,0,0,221,225,7,5,0,0,222,224,7,6,0,0,223,222,1,0,0,0,224,227,1,0,0,0,
225,223,1,0,0,0,225,226,1,0,0,0,226,229,1,0,0,0,227,225,1,0,0,0,228,207,
1,0,0,0,228,214,1,0,0,0,228,221,1,0,0,0,229,70,1,0,0,0,230,233,3,73,36,
0,231,233,3,79,39,0,232,230,1,0,0,0,232,231,1,0,0,0,233,72,1,0,0,0,234,
236,3,75,37,0,235,237,3,77,38,0,236,235,1,0,0,0,236,237,1,0,0,0,237,245,
1,0,0,0,238,240,7,6,0,0,239,238,1,0,0,0,240,241,1,0,0,0,241,239,1,0,0,
0,241,242,1,0,0,0,242,243,1,0,0,0,243,245,3,77,38,0,244,234,1,0,0,0,244,
239,1,0,0,0,245,74,1,0,0,0,246,248,7,6,0,0,247,246,1,0,0,0,248,249,1,
0,0,0,249,247,1,0,0,0,249,250,1,0,0,0,250,251,1,0,0,0,251,255,5,46,0,
0,252,254,7,6,0,0,253,252,1,0,0,0,254,257,1,0,0,0,255,253,1,0,0,0,255,
256,1,0,0,0,256,265,1,0,0,0,257,255,1,0,0,0,258,260,5,46,0,0,259,261,
7,6,0,0,260,259,1,0,0,0,261,262,1,0,0,0,262,260,1,0,0,0,262,263,1,0,0,
0,263,265,1,0,0,0,264,247,1,0,0,0,264,258,1,0,0,0,265,76,1,0,0,0,266,
268,7,7,0,0,267,269,7,8,0,0,268,267,1,0,0,0,268,269,1,0,0,0,269,271,1,
0,0,0,270,272,7,6,0,0,271,270,1,0,0,0,272,273,1,0,0,0,273,271,1,0,0,0,
273,274,1,0,0,0,274,78,1,0,0,0,275,276,5,48,0,0,276,277,7,2,0,0,277,278,
3,81,40,0,278,279,3,83,41,0,279,289,1,0,0,0,280,281,5,48,0,0,281,283,
7,2,0,0,282,284,7,3,0,0,283,282,1,0,0,0,284,285,1,0,0,0,285,283,1,0,0,
0,285,286,1,0,0,0,286,287,1,0,0,0,287,289,3,83,41,0,288,275,1,0,0,0,288,
280,1,0,0,0,289,80,1,0,0,0,290,292,7,3,0,0,291,290,1,0,0,0,292,293,1,
0,0,0,293,291,1,0,0,0,293,294,1,0,0,0,294,295,1,0,0,0,295,299,5,46,0,
0,296,298,7,3,0,0,297,296,1,0,0,0,298,301,1,0,0,0,299,297,1,0,0,0,299,
300,1,0,0,0,300,309,1,0,0,0,301,299,1,0,0,0,302,304,5,46,0,0,303,305,
7,3,0,0,304,303,1,0,0,0,305,306,1,0,0,0,306,304,1,0,0,0,306,307,1,0,0,
0,307,309,1,0,0,0,308,291,1,0,0,0,308,302,1,0,0,0,309,82,1,0,0,0,310,
312,7,9,0,0,311,313,7,8,0,0,312,311,1,0,0,0,312,313,1,0,0,0,313,315,1,
0,0,0,314,316,7,6,0,0,315,314,1,0,0,0,316,317,1,0,0,0,317,315,1,0,0,0,
317,318,1,0,0,0,318,84,1,0,0,0,319,321,7,10,0,0,320,319,1,0,0,0,321,322,
1,0,0,0,322,320,1,0,0,0,322,323,1,0,0,0,323,324,1,0,0,0,324,325,6,42,
0,0,325,86,1,0,0,0,326,327,5,47,0,0,327,328,5,47,0,0,328,332,1,0,0,0,
329,331,8,11,0,0,330,329,1,0,0,0,331,334,1,0,0,0,332,330,1,0,0,0,332,
333,1,0,0,0,333,335,1,0,0,0,334,332,1,0,0,0,335,336,6,43,0,0,336,88,1,
0,0,0,337,338,5,47,0,0,338,339,5,42,0,0,339,343,1,0,0,0,340,342,9,0,0,
0,341,340,1,0,0,0,342,345,1,0,0,0,343,344,1,0,0,0,343,341,1,0,0,0,344,
346,1,0,0,0,345,343,1,0,0,0,346,347,5,42,0,0,347,348,5,47,0,0,348,349,
1,0,0,0,349,350,6,44,0,0,350,90,1,0,0,0,27,0,204,212,218,225,228,232,
236,241,244,249,255,262,264,268,273,285,288,293,299,306,308,312,317,322,
332,343,1,6,0,0
};
staticData->serializedATN = antlr4::atn::SerializedATNView(serializedATNSegment, sizeof(serializedATNSegment) / sizeof(serializedATNSegment[0]));
antlr4::atn::ATNDeserializer deserializer;
staticData->atn = deserializer.deserialize(staticData->serializedATN);
const size_t count = staticData->atn->getNumberOfDecisions();
staticData->decisionToDFA.reserve(count);
for (size_t i = 0; i < count; i++) {
staticData->decisionToDFA.emplace_back(staticData->atn->getDecisionState(i), i);
}
sysylexerLexerStaticData = std::move(staticData);
}
}
SysYLexer::SysYLexer(CharStream *input) : Lexer(input) {
SysYLexer::initialize();
_interpreter = new atn::LexerATNSimulator(this, *sysylexerLexerStaticData->atn, sysylexerLexerStaticData->decisionToDFA, sysylexerLexerStaticData->sharedContextCache);
}
SysYLexer::~SysYLexer() {
delete _interpreter;
}
std::string SysYLexer::getGrammarFileName() const {
return "SysY.g4";
}
const std::vector<std::string>& SysYLexer::getRuleNames() const {
return sysylexerLexerStaticData->ruleNames;
}
const std::vector<std::string>& SysYLexer::getChannelNames() const {
return sysylexerLexerStaticData->channelNames;
}
const std::vector<std::string>& SysYLexer::getModeNames() const {
return sysylexerLexerStaticData->modeNames;
}
const dfa::Vocabulary& SysYLexer::getVocabulary() const {
return sysylexerLexerStaticData->vocabulary;
}
antlr4::atn::SerializedATNView SysYLexer::getSerializedATN() const {
return sysylexerLexerStaticData->serializedATN;
}
const atn::ATN& SysYLexer::getATN() const {
return *sysylexerLexerStaticData->atn;
}
void SysYLexer::initialize() {
#if ANTLR4_USE_THREAD_LOCAL_CACHE
sysylexerLexerInitialize();
#else
::antlr4::internal::call_once(sysylexerLexerOnceFlag, sysylexerLexerInitialize);
#endif
}

@ -1,5 +1,5 @@
// Generated from XPathLexer.g4 by ANTLR 4.13.1
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#pragma once
@ -9,16 +9,21 @@
class XPathLexer : public antlr4::Lexer {
class SysYLexer : public antlr4::Lexer {
public:
enum {
TOKEN_REF = 1, RULE_REF = 2, ANYWHERE = 3, ROOT = 4, WILDCARD = 5, BANG = 6,
ID = 7, STRING = 8
Void = 1, Int = 2, Float = 3, Const = 4, If = 5, Else = 6, While = 7,
Break = 8, Continue = 9, Return = 10, AddOp = 11, SubOp = 12, Assign = 13,
MulOp = 14, DivOp = 15, ModOp = 16, NotOp = 17, AndOp = 18, OrOp = 19,
EqOp = 20, NeOp = 21, LtOp = 22, GtOp = 23, LeOp = 24, GeOp = 25, Semi = 26,
Comma = 27, L_PAREN = 28, R_PAREN = 29, L_BRACE = 30, R_BRACE = 31,
L_BRACKET = 32, R_BRACKET = 33, Ident = 34, IntConst = 35, FloatConst = 36,
WS = 37, COMMENT = 38, BLOCK_COMMENT = 39
};
explicit XPathLexer(antlr4::CharStream *input);
explicit SysYLexer(antlr4::CharStream *input);
~XPathLexer() override;
~SysYLexer() override;
std::string getGrammarFileName() const override;
@ -35,8 +40,6 @@ public:
const antlr4::atn::ATN& getATN() const override;
void action(antlr4::RuleContext *context, size_t ruleIndex, size_t actionIndex) override;
// By default the static state used to implement the lexer is lazily initialized during the first
// call to the constructor. You can call this function if you wish to initialize the static state
// ahead of time.
@ -45,7 +48,6 @@ public:
private:
// Individual action functions triggered by action() above.
void IDAction(antlr4::RuleContext *context, size_t actionIndex);
// Individual semantic predicate functions triggered by sempred() above.

@ -0,0 +1,7 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#include "SysYListener.h"

@ -0,0 +1,112 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
#include "SysYParser.h"
/**
* This interface defines an abstract listener for a parse tree produced by SysYParser.
*/
class SysYListener : public antlr4::tree::ParseTreeListener {
public:
virtual void enterCompUnit(SysYParser::CompUnitContext *ctx) = 0;
virtual void exitCompUnit(SysYParser::CompUnitContext *ctx) = 0;
virtual void enterFuncDef(SysYParser::FuncDefContext *ctx) = 0;
virtual void exitFuncDef(SysYParser::FuncDefContext *ctx) = 0;
virtual void enterFuncType(SysYParser::FuncTypeContext *ctx) = 0;
virtual void exitFuncType(SysYParser::FuncTypeContext *ctx) = 0;
virtual void enterFuncFParams(SysYParser::FuncFParamsContext *ctx) = 0;
virtual void exitFuncFParams(SysYParser::FuncFParamsContext *ctx) = 0;
virtual void enterFuncFParam(SysYParser::FuncFParamContext *ctx) = 0;
virtual void exitFuncFParam(SysYParser::FuncFParamContext *ctx) = 0;
virtual void enterBlock(SysYParser::BlockContext *ctx) = 0;
virtual void exitBlock(SysYParser::BlockContext *ctx) = 0;
virtual void enterBlockItem(SysYParser::BlockItemContext *ctx) = 0;
virtual void exitBlockItem(SysYParser::BlockItemContext *ctx) = 0;
virtual void enterDecl(SysYParser::DeclContext *ctx) = 0;
virtual void exitDecl(SysYParser::DeclContext *ctx) = 0;
virtual void enterConstDecl(SysYParser::ConstDeclContext *ctx) = 0;
virtual void exitConstDecl(SysYParser::ConstDeclContext *ctx) = 0;
virtual void enterBType(SysYParser::BTypeContext *ctx) = 0;
virtual void exitBType(SysYParser::BTypeContext *ctx) = 0;
virtual void enterConstDef(SysYParser::ConstDefContext *ctx) = 0;
virtual void exitConstDef(SysYParser::ConstDefContext *ctx) = 0;
virtual void enterConstInitVal(SysYParser::ConstInitValContext *ctx) = 0;
virtual void exitConstInitVal(SysYParser::ConstInitValContext *ctx) = 0;
virtual void enterStmt(SysYParser::StmtContext *ctx) = 0;
virtual void exitStmt(SysYParser::StmtContext *ctx) = 0;
virtual void enterCond(SysYParser::CondContext *ctx) = 0;
virtual void exitCond(SysYParser::CondContext *ctx) = 0;
virtual void enterLVal(SysYParser::LValContext *ctx) = 0;
virtual void exitLVal(SysYParser::LValContext *ctx) = 0;
virtual void enterPrimaryExp(SysYParser::PrimaryExpContext *ctx) = 0;
virtual void exitPrimaryExp(SysYParser::PrimaryExpContext *ctx) = 0;
virtual void enterNumber(SysYParser::NumberContext *ctx) = 0;
virtual void exitNumber(SysYParser::NumberContext *ctx) = 0;
virtual void enterUnaryExp(SysYParser::UnaryExpContext *ctx) = 0;
virtual void exitUnaryExp(SysYParser::UnaryExpContext *ctx) = 0;
virtual void enterUnaryOp(SysYParser::UnaryOpContext *ctx) = 0;
virtual void exitUnaryOp(SysYParser::UnaryOpContext *ctx) = 0;
virtual void enterFuncRParams(SysYParser::FuncRParamsContext *ctx) = 0;
virtual void exitFuncRParams(SysYParser::FuncRParamsContext *ctx) = 0;
virtual void enterMulExp(SysYParser::MulExpContext *ctx) = 0;
virtual void exitMulExp(SysYParser::MulExpContext *ctx) = 0;
virtual void enterAddExp(SysYParser::AddExpContext *ctx) = 0;
virtual void exitAddExp(SysYParser::AddExpContext *ctx) = 0;
virtual void enterRelExp(SysYParser::RelExpContext *ctx) = 0;
virtual void exitRelExp(SysYParser::RelExpContext *ctx) = 0;
virtual void enterEqExp(SysYParser::EqExpContext *ctx) = 0;
virtual void exitEqExp(SysYParser::EqExpContext *ctx) = 0;
virtual void enterLAndExp(SysYParser::LAndExpContext *ctx) = 0;
virtual void exitLAndExp(SysYParser::LAndExpContext *ctx) = 0;
virtual void enterLOrExp(SysYParser::LOrExpContext *ctx) = 0;
virtual void exitLOrExp(SysYParser::LOrExpContext *ctx) = 0;
virtual void enterConstExp(SysYParser::ConstExpContext *ctx) = 0;
virtual void exitConstExp(SysYParser::ConstExpContext *ctx) = 0;
virtual void enterVarDecl(SysYParser::VarDeclContext *ctx) = 0;
virtual void exitVarDecl(SysYParser::VarDeclContext *ctx) = 0;
virtual void enterVarDef(SysYParser::VarDefContext *ctx) = 0;
virtual void exitVarDef(SysYParser::VarDefContext *ctx) = 0;
virtual void enterInitVal(SysYParser::InitValContext *ctx) = 0;
virtual void exitInitVal(SysYParser::InitValContext *ctx) = 0;
virtual void enterExp(SysYParser::ExpContext *ctx) = 0;
virtual void exitExp(SysYParser::ExpContext *ctx) = 0;
};

File diff suppressed because it is too large Load Diff

@ -0,0 +1,688 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
class SysYParser : public antlr4::Parser {
public:
enum {
Void = 1, Int = 2, Float = 3, Const = 4, If = 5, Else = 6, While = 7,
Break = 8, Continue = 9, Return = 10, AddOp = 11, SubOp = 12, Assign = 13,
MulOp = 14, DivOp = 15, ModOp = 16, NotOp = 17, AndOp = 18, OrOp = 19,
EqOp = 20, NeOp = 21, LtOp = 22, GtOp = 23, LeOp = 24, GeOp = 25, Semi = 26,
Comma = 27, L_PAREN = 28, R_PAREN = 29, L_BRACE = 30, R_BRACE = 31,
L_BRACKET = 32, R_BRACKET = 33, Ident = 34, IntConst = 35, FloatConst = 36,
WS = 37, COMMENT = 38, BLOCK_COMMENT = 39
};
enum {
RuleCompUnit = 0, RuleFuncDef = 1, RuleFuncType = 2, RuleFuncFParams = 3,
RuleFuncFParam = 4, RuleBlock = 5, RuleBlockItem = 6, RuleDecl = 7,
RuleConstDecl = 8, RuleBType = 9, RuleConstDef = 10, RuleConstInitVal = 11,
RuleStmt = 12, RuleCond = 13, RuleLVal = 14, RulePrimaryExp = 15, RuleNumber = 16,
RuleUnaryExp = 17, RuleUnaryOp = 18, RuleFuncRParams = 19, RuleMulExp = 20,
RuleAddExp = 21, RuleRelExp = 22, RuleEqExp = 23, RuleLAndExp = 24,
RuleLOrExp = 25, RuleConstExp = 26, RuleVarDecl = 27, RuleVarDef = 28,
RuleInitVal = 29, RuleExp = 30
};
explicit SysYParser(antlr4::TokenStream *input);
SysYParser(antlr4::TokenStream *input, const antlr4::atn::ParserATNSimulatorOptions &options);
~SysYParser() override;
std::string getGrammarFileName() const override;
const antlr4::atn::ATN& getATN() const override;
const std::vector<std::string>& getRuleNames() const override;
const antlr4::dfa::Vocabulary& getVocabulary() const override;
antlr4::atn::SerializedATNView getSerializedATN() const override;
class CompUnitContext;
class FuncDefContext;
class FuncTypeContext;
class FuncFParamsContext;
class FuncFParamContext;
class BlockContext;
class BlockItemContext;
class DeclContext;
class ConstDeclContext;
class BTypeContext;
class ConstDefContext;
class ConstInitValContext;
class StmtContext;
class CondContext;
class LValContext;
class PrimaryExpContext;
class NumberContext;
class UnaryExpContext;
class UnaryOpContext;
class FuncRParamsContext;
class MulExpContext;
class AddExpContext;
class RelExpContext;
class EqExpContext;
class LAndExpContext;
class LOrExpContext;
class ConstExpContext;
class VarDeclContext;
class VarDefContext;
class InitValContext;
class ExpContext;
class CompUnitContext : public antlr4::ParserRuleContext {
public:
CompUnitContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *EOF();
std::vector<FuncDefContext *> funcDef();
FuncDefContext* funcDef(size_t i);
std::vector<DeclContext *> decl();
DeclContext* decl(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
CompUnitContext* compUnit();
class FuncDefContext : public antlr4::ParserRuleContext {
public:
FuncDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
FuncTypeContext *funcType();
antlr4::tree::TerminalNode *Ident();
antlr4::tree::TerminalNode *L_PAREN();
antlr4::tree::TerminalNode *R_PAREN();
BlockContext *block();
FuncFParamsContext *funcFParams();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncDefContext* funcDef();
class FuncTypeContext : public antlr4::ParserRuleContext {
public:
FuncTypeContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Void();
antlr4::tree::TerminalNode *Int();
antlr4::tree::TerminalNode *Float();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncTypeContext* funcType();
class FuncFParamsContext : public antlr4::ParserRuleContext {
public:
FuncFParamsContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
std::vector<FuncFParamContext *> funcFParam();
FuncFParamContext* funcFParam(size_t i);
std::vector<antlr4::tree::TerminalNode *> Comma();
antlr4::tree::TerminalNode* Comma(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncFParamsContext* funcFParams();
class FuncFParamContext : public antlr4::ParserRuleContext {
public:
FuncFParamContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
BTypeContext *bType();
antlr4::tree::TerminalNode *Ident();
std::vector<antlr4::tree::TerminalNode *> L_BRACKET();
antlr4::tree::TerminalNode* L_BRACKET(size_t i);
std::vector<antlr4::tree::TerminalNode *> R_BRACKET();
antlr4::tree::TerminalNode* R_BRACKET(size_t i);
std::vector<ExpContext *> exp();
ExpContext* exp(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncFParamContext* funcFParam();
class BlockContext : public antlr4::ParserRuleContext {
public:
BlockContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *L_BRACE();
antlr4::tree::TerminalNode *R_BRACE();
std::vector<BlockItemContext *> blockItem();
BlockItemContext* blockItem(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
BlockContext* block();
class BlockItemContext : public antlr4::ParserRuleContext {
public:
BlockItemContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
DeclContext *decl();
StmtContext *stmt();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
BlockItemContext* blockItem();
class DeclContext : public antlr4::ParserRuleContext {
public:
DeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
VarDeclContext *varDecl();
ConstDeclContext *constDecl();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
DeclContext* decl();
class ConstDeclContext : public antlr4::ParserRuleContext {
public:
ConstDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Const();
BTypeContext *bType();
std::vector<ConstDefContext *> constDef();
ConstDefContext* constDef(size_t i);
antlr4::tree::TerminalNode *Semi();
std::vector<antlr4::tree::TerminalNode *> Comma();
antlr4::tree::TerminalNode* Comma(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstDeclContext* constDecl();
class BTypeContext : public antlr4::ParserRuleContext {
public:
BTypeContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Int();
antlr4::tree::TerminalNode *Float();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
BTypeContext* bType();
class ConstDefContext : public antlr4::ParserRuleContext {
public:
ConstDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Ident();
antlr4::tree::TerminalNode *Assign();
ConstInitValContext *constInitVal();
std::vector<antlr4::tree::TerminalNode *> L_BRACKET();
antlr4::tree::TerminalNode* L_BRACKET(size_t i);
std::vector<ConstExpContext *> constExp();
ConstExpContext* constExp(size_t i);
std::vector<antlr4::tree::TerminalNode *> R_BRACKET();
antlr4::tree::TerminalNode* R_BRACKET(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstDefContext* constDef();
class ConstInitValContext : public antlr4::ParserRuleContext {
public:
ConstInitValContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
ConstExpContext *constExp();
antlr4::tree::TerminalNode *L_BRACE();
antlr4::tree::TerminalNode *R_BRACE();
std::vector<ConstInitValContext *> constInitVal();
ConstInitValContext* constInitVal(size_t i);
std::vector<antlr4::tree::TerminalNode *> Comma();
antlr4::tree::TerminalNode* Comma(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstInitValContext* constInitVal();
class StmtContext : public antlr4::ParserRuleContext {
public:
StmtContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
LValContext *lVal();
antlr4::tree::TerminalNode *Assign();
ExpContext *exp();
antlr4::tree::TerminalNode *Semi();
BlockContext *block();
antlr4::tree::TerminalNode *If();
antlr4::tree::TerminalNode *L_PAREN();
CondContext *cond();
antlr4::tree::TerminalNode *R_PAREN();
std::vector<StmtContext *> stmt();
StmtContext* stmt(size_t i);
antlr4::tree::TerminalNode *Else();
antlr4::tree::TerminalNode *While();
antlr4::tree::TerminalNode *Break();
antlr4::tree::TerminalNode *Continue();
antlr4::tree::TerminalNode *Return();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
StmtContext* stmt();
class CondContext : public antlr4::ParserRuleContext {
public:
CondContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
LOrExpContext *lOrExp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
CondContext* cond();
class LValContext : public antlr4::ParserRuleContext {
public:
LValContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Ident();
std::vector<antlr4::tree::TerminalNode *> L_BRACKET();
antlr4::tree::TerminalNode* L_BRACKET(size_t i);
std::vector<ExpContext *> exp();
ExpContext* exp(size_t i);
std::vector<antlr4::tree::TerminalNode *> R_BRACKET();
antlr4::tree::TerminalNode* R_BRACKET(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
LValContext* lVal();
class PrimaryExpContext : public antlr4::ParserRuleContext {
public:
PrimaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *L_PAREN();
ExpContext *exp();
antlr4::tree::TerminalNode *R_PAREN();
LValContext *lVal();
NumberContext *number();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
PrimaryExpContext* primaryExp();
class NumberContext : public antlr4::ParserRuleContext {
public:
NumberContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *IntConst();
antlr4::tree::TerminalNode *FloatConst();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
NumberContext* number();
class UnaryExpContext : public antlr4::ParserRuleContext {
public:
UnaryExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
PrimaryExpContext *primaryExp();
antlr4::tree::TerminalNode *Ident();
antlr4::tree::TerminalNode *L_PAREN();
antlr4::tree::TerminalNode *R_PAREN();
FuncRParamsContext *funcRParams();
UnaryOpContext *unaryOp();
UnaryExpContext *unaryExp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
UnaryExpContext* unaryExp();
class UnaryOpContext : public antlr4::ParserRuleContext {
public:
UnaryOpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *AddOp();
antlr4::tree::TerminalNode *SubOp();
antlr4::tree::TerminalNode *NotOp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
UnaryOpContext* unaryOp();
class FuncRParamsContext : public antlr4::ParserRuleContext {
public:
FuncRParamsContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
std::vector<ExpContext *> exp();
ExpContext* exp(size_t i);
std::vector<antlr4::tree::TerminalNode *> Comma();
antlr4::tree::TerminalNode* Comma(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
FuncRParamsContext* funcRParams();
class MulExpContext : public antlr4::ParserRuleContext {
public:
MulExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
UnaryExpContext *unaryExp();
MulExpContext *mulExp();
antlr4::tree::TerminalNode *MulOp();
antlr4::tree::TerminalNode *DivOp();
antlr4::tree::TerminalNode *ModOp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
MulExpContext* mulExp();
MulExpContext* mulExp(int precedence);
class AddExpContext : public antlr4::ParserRuleContext {
public:
AddExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
MulExpContext *mulExp();
AddExpContext *addExp();
antlr4::tree::TerminalNode *AddOp();
antlr4::tree::TerminalNode *SubOp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
AddExpContext* addExp();
AddExpContext* addExp(int precedence);
class RelExpContext : public antlr4::ParserRuleContext {
public:
RelExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
AddExpContext *addExp();
RelExpContext *relExp();
antlr4::tree::TerminalNode *LtOp();
antlr4::tree::TerminalNode *GtOp();
antlr4::tree::TerminalNode *LeOp();
antlr4::tree::TerminalNode *GeOp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
RelExpContext* relExp();
RelExpContext* relExp(int precedence);
class EqExpContext : public antlr4::ParserRuleContext {
public:
EqExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
RelExpContext *relExp();
EqExpContext *eqExp();
antlr4::tree::TerminalNode *EqOp();
antlr4::tree::TerminalNode *NeOp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
EqExpContext* eqExp();
EqExpContext* eqExp(int precedence);
class LAndExpContext : public antlr4::ParserRuleContext {
public:
LAndExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
EqExpContext *eqExp();
LAndExpContext *lAndExp();
antlr4::tree::TerminalNode *AndOp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
LAndExpContext* lAndExp();
LAndExpContext* lAndExp(int precedence);
class LOrExpContext : public antlr4::ParserRuleContext {
public:
LOrExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
LAndExpContext *lAndExp();
LOrExpContext *lOrExp();
antlr4::tree::TerminalNode *OrOp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
LOrExpContext* lOrExp();
LOrExpContext* lOrExp(int precedence);
class ConstExpContext : public antlr4::ParserRuleContext {
public:
ConstExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
AddExpContext *addExp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ConstExpContext* constExp();
class VarDeclContext : public antlr4::ParserRuleContext {
public:
VarDeclContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
BTypeContext *bType();
std::vector<VarDefContext *> varDef();
VarDefContext* varDef(size_t i);
antlr4::tree::TerminalNode *Semi();
std::vector<antlr4::tree::TerminalNode *> Comma();
antlr4::tree::TerminalNode* Comma(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
VarDeclContext* varDecl();
class VarDefContext : public antlr4::ParserRuleContext {
public:
VarDefContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
antlr4::tree::TerminalNode *Ident();
std::vector<antlr4::tree::TerminalNode *> L_BRACKET();
antlr4::tree::TerminalNode* L_BRACKET(size_t i);
std::vector<ConstExpContext *> constExp();
ConstExpContext* constExp(size_t i);
std::vector<antlr4::tree::TerminalNode *> R_BRACKET();
antlr4::tree::TerminalNode* R_BRACKET(size_t i);
antlr4::tree::TerminalNode *Assign();
InitValContext *initVal();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
VarDefContext* varDef();
class InitValContext : public antlr4::ParserRuleContext {
public:
InitValContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
ExpContext *exp();
antlr4::tree::TerminalNode *L_BRACE();
antlr4::tree::TerminalNode *R_BRACE();
std::vector<InitValContext *> initVal();
InitValContext* initVal(size_t i);
std::vector<antlr4::tree::TerminalNode *> Comma();
antlr4::tree::TerminalNode* Comma(size_t i);
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
InitValContext* initVal();
class ExpContext : public antlr4::ParserRuleContext {
public:
ExpContext(antlr4::ParserRuleContext *parent, size_t invokingState);
virtual size_t getRuleIndex() const override;
AddExpContext *addExp();
virtual void enterRule(antlr4::tree::ParseTreeListener *listener) override;
virtual void exitRule(antlr4::tree::ParseTreeListener *listener) override;
virtual std::any accept(antlr4::tree::ParseTreeVisitor *visitor) override;
};
ExpContext* exp();
bool sempred(antlr4::RuleContext *_localctx, size_t ruleIndex, size_t predicateIndex) override;
bool mulExpSempred(MulExpContext *_localctx, size_t predicateIndex);
bool addExpSempred(AddExpContext *_localctx, size_t predicateIndex);
bool relExpSempred(RelExpContext *_localctx, size_t predicateIndex);
bool eqExpSempred(EqExpContext *_localctx, size_t predicateIndex);
bool lAndExpSempred(LAndExpContext *_localctx, size_t predicateIndex);
bool lOrExpSempred(LOrExpContext *_localctx, size_t predicateIndex);
// By default the static state used to implement the parser is lazily initialized during the first
// call to the constructor. You can call this function if you wish to initialize the static state
// ahead of time.
static void initialize();
private:
};

@ -0,0 +1,7 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#include "SysYVisitor.h"

@ -0,0 +1,86 @@
// Generated from src/antlr4/SysY.g4 by ANTLR 4.13.2
#pragma once
#include "antlr4-runtime.h"
#include "SysYParser.h"
/**
* This class defines an abstract visitor for a parse tree
* produced by SysYParser.
*/
class SysYVisitor : public antlr4::tree::AbstractParseTreeVisitor {
public:
/**
* Visit parse trees produced by SysYParser.
*/
virtual std::any visitCompUnit(SysYParser::CompUnitContext *context) = 0;
virtual std::any visitFuncDef(SysYParser::FuncDefContext *context) = 0;
virtual std::any visitFuncType(SysYParser::FuncTypeContext *context) = 0;
virtual std::any visitFuncFParams(SysYParser::FuncFParamsContext *context) = 0;
virtual std::any visitFuncFParam(SysYParser::FuncFParamContext *context) = 0;
virtual std::any visitBlock(SysYParser::BlockContext *context) = 0;
virtual std::any visitBlockItem(SysYParser::BlockItemContext *context) = 0;
virtual std::any visitDecl(SysYParser::DeclContext *context) = 0;
virtual std::any visitConstDecl(SysYParser::ConstDeclContext *context) = 0;
virtual std::any visitBType(SysYParser::BTypeContext *context) = 0;
virtual std::any visitConstDef(SysYParser::ConstDefContext *context) = 0;
virtual std::any visitConstInitVal(SysYParser::ConstInitValContext *context) = 0;
virtual std::any visitStmt(SysYParser::StmtContext *context) = 0;
virtual std::any visitCond(SysYParser::CondContext *context) = 0;
virtual std::any visitLVal(SysYParser::LValContext *context) = 0;
virtual std::any visitPrimaryExp(SysYParser::PrimaryExpContext *context) = 0;
virtual std::any visitNumber(SysYParser::NumberContext *context) = 0;
virtual std::any visitUnaryExp(SysYParser::UnaryExpContext *context) = 0;
virtual std::any visitUnaryOp(SysYParser::UnaryOpContext *context) = 0;
virtual std::any visitFuncRParams(SysYParser::FuncRParamsContext *context) = 0;
virtual std::any visitMulExp(SysYParser::MulExpContext *context) = 0;
virtual std::any visitAddExp(SysYParser::AddExpContext *context) = 0;
virtual std::any visitRelExp(SysYParser::RelExpContext *context) = 0;
virtual std::any visitEqExp(SysYParser::EqExpContext *context) = 0;
virtual std::any visitLAndExp(SysYParser::LAndExpContext *context) = 0;
virtual std::any visitLOrExp(SysYParser::LOrExpContext *context) = 0;
virtual std::any visitConstExp(SysYParser::ConstExpContext *context) = 0;
virtual std::any visitVarDecl(SysYParser::VarDeclContext *context) = 0;
virtual std::any visitVarDef(SysYParser::VarDefContext *context) = 0;
virtual std::any visitInitVal(SysYParser::InitValContext *context) = 0;
virtual std::any visitExp(SysYParser::ExpContext *context) = 0;
};

@ -7,7 +7,7 @@
// - 指令追加与 terminator 约束主要在头文件中的 Append 模板里处理;
// - 前驱/后继容器已经预留,但当前项目里还没有分支指令与自动维护逻辑。
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <utility>

@ -1,5 +1,5 @@
// 管理基础类型、整型常量池和临时名生成。
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <iomanip>
#include <sstream>

@ -1,7 +1,7 @@
// IR Function
// - 保存参数列表、基本块列表
// - 记录函数属性/元信息(按需要扩展)
#include "ir/IR.h"
#include "include/ir/IR.h"
namespace ir {

@ -1,7 +1,7 @@
// GlobalValue 占位实现:
// - 具体的全局初始化器、打印和链接语义需要自行补全
#include "ir/IR.h"
#include "../../include/ir/IR.h"
namespace ir {

@ -2,11 +2,11 @@
// - 管理插入点(当前基本块/位置)
// - 提供创建各类指令的便捷接口,降低 IRGen 复杂度
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <stdexcept>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace ir {
IRBuilder::IRBuilder(Context& ctx, BasicBlock* bb)

@ -2,7 +2,7 @@
// - 将 IR 打印为 .ll 风格的文本
// - 支撑调试与测试对比diff
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <cstdint>
#include <cstring>
@ -12,7 +12,7 @@
#include <stdexcept>
#include <string>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace ir {

@ -1,11 +1,11 @@
// IR 指令体系:
// - 二元运算/比较、load/store、call、br/condbr、ret、phi、alloca 等
// - 指令操作数与结果类型管理,支持打印与优化
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <stdexcept>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace ir {
User::User(std::shared_ptr<Type> ty, std::string name)

@ -1,6 +1,6 @@
// 保存函数列表并提供模块级上下文访问。
#include "ir/IR.h"
#include "include/ir/IR.h"
namespace ir {

@ -1,5 +1,5 @@
// 当前支持 void、i32、float 及其指针类型。
#include "ir/IR.h"
#include "include/ir/IR.h"
namespace ir {

@ -1,7 +1,7 @@
// SSA 值体系抽象:
// - 常量、参数、指令结果等统一为 Value
// - 提供类型信息与使用/被使用关系(按需要实现)
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>

@ -1,4 +1,4 @@
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>
#include <unordered_map>

@ -2,7 +2,7 @@
// - 删除不可达块、合并空块、简化分支等
// - 改善 IR 结构,便于后续优化与后端生成
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>
#include <unordered_map>

@ -7,7 +7,7 @@
// 3. 删除重复的表达式计算
// 4. 注意处理 phi 函数和控制流汇合点
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>
#include <unordered_map>

@ -2,7 +2,7 @@
// - 折叠可判定的常量表达式
// - 简化常量控制流分支(按实现范围裁剪)
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>
#include <cmath>

@ -4,7 +4,7 @@
// - 简化冗余 PHI 节点(所有入边都是同一个值)
// - 常与 ConstFold、DCE、CFGSimplify 迭代配合使用
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <iostream>
#include <unordered_map>

@ -4,7 +4,7 @@
// - 通常与 CFG 简化配合使用
// - 采用"标记 + 清扫"思路
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>
#include <unordered_set>

@ -1,4 +1,4 @@
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>
#include <iostream>

@ -2,7 +2,7 @@
// - 将局部变量的 alloca/load/store 提升为 SSA 形式
// - 使用标准的支配边界 + PHI 节点插入算法
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <algorithm>
#include <iostream>

@ -1,6 +1,6 @@
// IR Pass 管理骨架。
#include "ir/IR.h"
#include "include/ir/IR.h"
#include <memory>
#include <sstream>

@ -1,12 +1,12 @@
#include "irgen/IRGen.h"
#include "include/irgen/IRGen.h"
#include <cmath>
#include <limits>
#include <stdexcept>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
#include "include/ir/IR.h"
#include "include/utils/Log.h"
namespace {

@ -1,10 +1,10 @@
#include "irgen/IRGen.h"
#include "include/irgen/IRGen.h"
#include <memory>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
#include "include/ir/IR.h"
#include "include/utils/Log.h"
std::unique_ptr<ir::Module> GenerateIR(SysYParser::CompUnitContext& tree,
const SemanticContext& sema) {

@ -1,11 +1,11 @@
#include "irgen/IRGen.h"
#include "include/irgen/IRGen.h"
#include <limits>
#include <stdexcept>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
#include "include/ir/IR.h"
#include "include/utils/Log.h"
namespace {

@ -1,11 +1,11 @@
#include "irgen/IRGen.h"
#include "include/irgen/IRGen.h"
#include <limits>
#include <stdexcept>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
#include "include/ir/IR.h"
#include "include/utils/Log.h"
namespace {

@ -1,10 +1,10 @@
#include "irgen/IRGen.h"
#include "include/irgen/IRGen.h"
#include <stdexcept>
#include "SysYParser.h"
#include "ir/IR.h"
#include "utils/Log.h"
#include "include/ir/IR.h"
#include "include/utils/Log.h"
std::string IRGenImpl::NextBlockName(const std::string& prefix) {
return prefix + std::to_string(++block_index_);

@ -4,95 +4,14 @@
#include <stdexcept>
#include <sstream>
#include "frontend/AntlrDriver.h"
#include "frontend/SyntaxTreePrinter.h"
#include "src/frontend/AntlrDriver.h"
#include "src/frontend/SyntaxTreePrinter.h"
#if !COMPILER_PARSE_ONLY
#include "ir/IR.h"
#include "ir/passes/PassManager.cpp"
#include "irgen/IRGen.h"
#include "mir/MIR.h"
#include "sem/Sema.h"
#include "include/ir/IR.h"
#include "src/ir/passes/PassManager.cpp"
#include "include/irgen/IRGen.h"
#include "include/mir/MIR.h"
#include "include/sem/Sema.h"
#endif
#include "utils/CLI.h"
#include "utils/Log.h"
int main(int argc, char** argv) {
try {
auto opts = ParseCLI(argc, argv);
if (opts.show_help) {
PrintHelp(std::cout);
return 0;
}
auto antlr = ParseFileWithAntlr(opts.input);
bool need_blank_line = false;
if (opts.emit_parse_tree) {
PrintSyntaxTree(antlr.tree, antlr.parser.get(), std::cout);
need_blank_line = true;
}
#if !COMPILER_PARSE_ONLY
auto* comp_unit =
dynamic_cast<SysYParser::CompUnitContext*>(antlr.tree);
if (!comp_unit) {
throw std::runtime_error(
FormatError("main", "语法树根节点不是 compUnit"));
}
auto sema = RunSema(*comp_unit);
auto module = GenerateIR(*comp_unit, sema);
// 执行优化(如果启用)
if (opts.optimize) {
ir::PassManager pass_manager;
pass_manager.RunScalarOptimizationPasses(module.get());
}
// 汇编输出到文件或标准输出
if (opts.emit_asm) {
auto machine_module = mir::LowerModuleToMIR(*module);
mir::RunRegAlloc(*machine_module);
mir::RunFrameLowering(*machine_module);
mir::RunPeephole(*machine_module);
std::ostringstream asm_ss;
mir::PrintAsm(*machine_module, asm_ss);
if (!opts.output.empty()) {
// 写入指定文件(-o 参数)
std::ofstream ofs(opts.output);
if (!ofs) {
throw std::runtime_error(FormatError("main", std::string("无法打开输出文件: ") + opts.output));
}
ofs << asm_ss.str();
ofs.close();
} else {
// 输出到标准输出
if (need_blank_line) {
std::cout << "\n";
}
std::cout << asm_ss.str();
}
}
if (opts.emit_ir) {
ir::IRPrinter printer;
if (need_blank_line) {
std::cout << "\n";
}
printer.Print(*module, std::cout);
need_blank_line = true;
}
#else
if (opts.emit_ir || opts.emit_asm) {
throw std::runtime_error(
FormatError("main", "当前为 parse-only 构建IR/汇编输出已禁用"));
}
#endif
} catch (const std::exception& ex) {
PrintException(std::cerr, ex);
return 1;
}
return 0;
}
#include "include/utils/CLI.h"
#include "include/utils/Log.h"

@ -1,10 +1,10 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <iostream>
#include <stdexcept>
#include <string>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace mir
{

@ -1,9 +1,9 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <algorithm>
#include <vector>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace mir
{

@ -1,12 +1,12 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <cstdint>
#include <cstring>
#include <stdexcept>
#include <unordered_map>
#include "ir/IR.h"
#include "utils/Log.h"
#include "include/ir/IR.h"
#include "include/utils/Log.h"
namespace mir
{

@ -1,4 +1,4 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <utility>

@ -1,4 +1,4 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
namespace mir {

@ -1,9 +1,9 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <stdexcept>
#include <utility>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace mir
{

@ -1,4 +1,4 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <utility>

@ -1,4 +1,4 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <algorithm>
#include <queue>
@ -7,7 +7,7 @@
#include <unordered_set>
#include <vector>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace mir
{

@ -1,8 +1,8 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <stdexcept>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace mir
{

@ -1,8 +1,8 @@
#include "mir/MIR.h"
#include "include/mir/MIR.h"
#include <vector>
#include "utils/Log.h"
#include "include/utils/Log.h"
namespace mir
{

@ -1,4 +1,4 @@
#include "sem/Sema.h"
#include "include/sem/Sema.h"
#include <any>
#include <limits>
@ -9,8 +9,8 @@
#include <unordered_map>
#include "SysYBaseVisitor.h"
#include "sem/SymbolTable.h"
#include "utils/Log.h"
#include "include/sem/SymbolTable.h"
#include "include/utils/Log.h"
namespace {

@ -1,6 +1,6 @@
// 维护局部变量声明的注册与查找。
#include "sem/SymbolTable.h"
#include "include/sem/SymbolTable.h"
void SymbolTable::EnterScope() { scopes_.emplace_back(); }

@ -2,13 +2,13 @@
// compiler -S -o testcase.s testcase.sy
// compiler -S -o testcase.s testcase.sy -O1
#include "utils/CLI.h"
#include "../include/utils/CLI.h"
#include <cstring>
#include <stdexcept>
#include <string>
#include "utils/Log.h"
#include "../include/utils/Log.h"
CLIOptions ParseCLI(int argc, char** argv) {
CLIOptions opt;

@ -1,6 +1,6 @@
// 格式化错误并统一打印异常与帮助信息。
#include "utils/Log.h"
#include "../include/utils/Log.h"
#include <ostream>
#include <string>

@ -0,0 +1,98 @@
// SysY 运行库实现:
// - 按实验/评测规范提供 I/O 等函数实现
// - 与编译器生成的目标代码链接,支撑运行时行为
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
// 输入函数
int getint() {
int value;
scanf("%d", &value);
return value;
}
int getch() {
char ch;
scanf("%c", &ch);
return (int)ch;
}
float getfloat() {
float value;
scanf("%f", &value);
return value;
}
int getarray(int arr[]) {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
return n;
}
int getfarray(float arr[]) {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%f", &arr[i]);
}
return n;
}
// 输出函数
void putint(int value) {
printf("%d", value);
}
void putch(int ch) {
printf("%c", (char)ch);
}
void putfloat(float value) {
printf("%a", value);
}
void putarray(int n, int arr[]) {
printf("%d:", n);
for (int i = 0; i < n; i++) {
printf(" %d", arr[i]);
}
printf("\n");
}
void putfarray(int n, float arr[]) {
printf("%d:", n);
for (int i = 0; i < n; i++) {
printf(" %a", arr[i]);
}
printf("\n");
}
// putstr 在测试用例中定义
// 计时函数
static clock_t start_time = 0;
void starttime() {
start_time = clock();
}
void stoptime() {
clock_t end_time = clock();
double elapsed = (double)(end_time - start_time) / CLOCKS_PER_SEC;
fprintf(stderr, "Total time: %.6f seconds\n", elapsed);
}
// 内存管理函数(如果需要)
void* _sysy_allocate(int size) {
return malloc(size);
}
void _sysy_deallocate(void* ptr) {
free(ptr);
}

@ -0,0 +1,4 @@
// SysY 运行库头文件:
// - 声明运行库函数原型(供编译器生成 call 或链接阶段引用)
// - 与 sylib.c 配套,按规范逐步补齐声明

@ -1,38 +0,0 @@
cmake_minimum_required(VERSION 3.15)
project(antlr4_runtime_vendor LANGUAGES CXX)
# antlr jar CMake
add_library(antlr4_runtime STATIC)
target_compile_features(antlr4_runtime PUBLIC cxx_std_17)
target_include_directories(antlr4_runtime PUBLIC
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/atn"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/dfa"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/internal"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/misc"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/support"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/tree"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/tree/pattern"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/tree/xpath"
)
file(GLOB_RECURSE ANTLR4_RUNTIME_SOURCES CONFIGURE_DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/atn/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/dfa/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/internal/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/misc/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/support/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/tree/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/tree/pattern/*.cpp"
"${CMAKE_CURRENT_SOURCE_DIR}/runtime/src/tree/xpath/*.cpp"
)
target_sources(antlr4_runtime PRIVATE ${ANTLR4_RUNTIME_SOURCES})
# Linux/Unix pthread std::call_once 线
find_package(Threads REQUIRED)
target_link_libraries(antlr4_runtime PUBLIC Threads::Threads)

@ -1,10 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "ANTLRErrorListener.h"
antlr4::ANTLRErrorListener::~ANTLRErrorListener()
{
}

@ -1,167 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "RecognitionException.h"
namespace antlrcpp {
class BitSet;
}
namespace antlr4 {
/// How to emit recognition errors (an interface in Java).
class ANTLR4CPP_PUBLIC ANTLRErrorListener {
public:
virtual ~ANTLRErrorListener();
/// <summary>
/// Upon syntax error, notify any interested parties. This is not how to
/// recover from errors or compute error messages. <seealso cref="ANTLRErrorStrategy"/>
/// specifies how to recover from syntax errors and how to compute error
/// messages. This listener's job is simply to emit a computed message,
/// though it has enough information to create its own message in many cases.
/// <p/>
/// The <seealso cref="RecognitionException"/> is non-null for all syntax errors except
/// when we discover mismatched token errors that we can recover from
/// in-line, without returning from the surrounding rule (via the single
/// token insertion and deletion mechanism).
/// </summary>
/// <param name="recognizer">
/// What parser got the error. From this
/// object, you can access the context as well
/// as the input stream. </param>
/// <param name="offendingSymbol">
/// The offending token in the input token
/// stream, unless recognizer is a lexer (then it's null). If
/// no viable alternative error, {@code e} has token at which we
/// started production for the decision. </param>
/// <param name="line">
/// The line number in the input where the error occurred. </param>
/// <param name="charPositionInLine">
/// The character position within that line where the error occurred. </param>
/// <param name="msg">
/// The message to emit. </param>
/// <param name="e">
/// The exception generated by the parser that led to
/// the reporting of an error. It is null in the case where
/// the parser was able to recover in line without exiting the
/// surrounding rule. </param>
virtual void syntaxError(Recognizer *recognizer, Token *offendingSymbol, size_t line,
size_t charPositionInLine, const std::string &msg, std::exception_ptr e) = 0;
/**
* This method is called by the parser when a full-context prediction
* results in an ambiguity.
*
* <p>Each full-context prediction which does not result in a syntax error
* will call either {@link #reportContextSensitivity} or
* {@link #reportAmbiguity}.</p>
*
* <p>When {@code ambigAlts} is not null, it contains the set of potentially
* viable alternatives identified by the prediction algorithm. When
* {@code ambigAlts} is null, use {@link ATNConfigSet#getAlts} to obtain the
* represented alternatives from the {@code configs} argument.</p>
*
* <p>When {@code exact} is {@code true}, <em>all</em> of the potentially
* viable alternatives are truly viable, i.e. this is reporting an exact
* ambiguity. When {@code exact} is {@code false}, <em>at least two</em> of
* the potentially viable alternatives are viable for the current input, but
* the prediction algorithm terminated as soon as it determined that at
* least the <em>minimum</em> potentially viable alternative is truly
* viable.</p>
*
* <p>When the {@link PredictionMode#LL_EXACT_AMBIG_DETECTION} prediction
* mode is used, the parser is required to identify exact ambiguities so
* {@code exact} will always be {@code true}.</p>
*
* <p>This method is not used by lexers.</p>
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input input where the ambiguity was identified
* @param exact {@code true} if the ambiguity is exactly known, otherwise
* {@code false}. This is always {@code true} when
* {@link PredictionMode#LL_EXACT_AMBIG_DETECTION} is used.
* @param ambigAlts the potentially ambiguous alternatives, or {@code null}
* to indicate that the potentially ambiguous alternatives are the complete
* set of represented alternatives in {@code configs}
* @param configs the ATN configuration set where the ambiguity was
* identified
*/
virtual void reportAmbiguity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex, bool exact,
const antlrcpp::BitSet &ambigAlts, atn::ATNConfigSet *configs) = 0;
/**
* This method is called when an SLL conflict occurs and the parser is about
* to use the full context information to make an LL decision.
*
* <p>If one or more configurations in {@code configs} contains a semantic
* predicate, the predicates are evaluated before this method is called. The
* subset of alternatives which are still viable after predicates are
* evaluated is reported in {@code conflictingAlts}.</p>
*
* <p>This method is not used by lexers.</p>
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input index where the SLL conflict occurred
* @param conflictingAlts The specific conflicting alternatives. If this is
* {@code null}, the conflicting alternatives are all alternatives
* represented in {@code configs}. At the moment, conflictingAlts is non-null
* (for the reference implementation, but Sam's optimized version can see this
* as null).
* @param configs the ATN configuration set where the SLL conflict was
* detected
*/
virtual void reportAttemptingFullContext(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
const antlrcpp::BitSet &conflictingAlts, atn::ATNConfigSet *configs) = 0;
/**
* This method is called by the parser when a full-context prediction has a
* unique result.
*
* <p>Each full-context prediction which does not result in a syntax error
* will call either {@link #reportContextSensitivity} or
* {@link #reportAmbiguity}.</p>
*
* <p>For prediction implementations that only evaluate full-context
* predictions when an SLL conflict is found (including the default
* {@link ParserATNSimulator} implementation), this method reports cases
* where SLL conflicts were resolved to unique full-context predictions,
* i.e. the decision was context-sensitive. This report does not necessarily
* indicate a problem, and it may appear even in completely unambiguous
* grammars.</p>
*
* <p>{@code configs} may have more than one represented alternative if the
* full-context prediction algorithm does not evaluate predicates before
* beginning the full-context prediction. In all cases, the final prediction
* is passed as the {@code prediction} argument.</p>
*
* <p>Note that the definition of "context sensitivity" in this method
* differs from the concept in {@link DecisionInfo#contextSensitivities}.
* This method reports all instances where an SLL conflict occurred but LL
* parsing produced a unique result, whether or not that unique result
* matches the minimum alternative in the SLL conflicting set.</p>
*
* <p>This method is not used by lexers.</p>
*
* @param recognizer the parser instance
* @param dfa the DFA for the current decision
* @param startIndex the input index where the decision started
* @param stopIndex the input index where the context sensitivity was
* finally determined
* @param prediction the unambiguous result of the full-context prediction
* @param configs the ATN configuration set where the unambiguous prediction
* was determined
*/
virtual void reportContextSensitivity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
size_t prediction, atn::ATNConfigSet *configs) = 0;
};
} // namespace antlr4

@ -1,10 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "ANTLRErrorStrategy.h"
antlr4::ANTLRErrorStrategy::~ANTLRErrorStrategy()
{
}

@ -1,121 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "Token.h"
namespace antlr4 {
/// <summary>
/// The interface for defining strategies to deal with syntax errors encountered
/// during a parse by ANTLR-generated parsers. We distinguish between three
/// different kinds of errors:
///
/// <ul>
/// <li>The parser could not figure out which path to take in the ATN (none of
/// the available alternatives could possibly match)</li>
/// <li>The current input does not match what we were looking for</li>
/// <li>A predicate evaluated to false</li>
/// </ul>
///
/// Implementations of this interface report syntax errors by calling
/// <seealso cref="Parser#notifyErrorListeners"/>.
/// <p/>
/// TODO: what to do about lexers
/// </summary>
class ANTLR4CPP_PUBLIC ANTLRErrorStrategy {
public:
/// <summary>
/// Reset the error handler state for the specified {@code recognizer}. </summary>
/// <param name="recognizer"> the parser instance </param>
virtual ~ANTLRErrorStrategy();
virtual void reset(Parser *recognizer) = 0;
/**
* This method is called when an unexpected symbol is encountered during an
* inline match operation, such as {@link Parser#match}. If the error
* strategy successfully recovers from the match failure, this method
* returns the {@link Token} instance which should be treated as the
* successful result of the match.
*
* <p>This method handles the consumption of any tokens - the caller should
* <b>not</b> call {@link Parser#consume} after a successful recovery.</p>
*
* <p>Note that the calling code will not report an error if this method
* returns successfully. The error strategy implementation is responsible
* for calling {@link Parser#notifyErrorListeners} as appropriate.</p>
*
* @param recognizer the parser instance
* @throws RecognitionException if the error strategy was not able to
* recover from the unexpected input symbol
*/
virtual Token* recoverInline(Parser *recognizer) = 0;
/// <summary>
/// This method is called to recover from exception {@code e}. This method is
/// called after <seealso cref="#reportError"/> by the default exception handler
/// generated for a rule method.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception to recover from </param>
/// <exception cref="RecognitionException"> if the error strategy could not recover from
/// the recognition exception </exception>
virtual void recover(Parser *recognizer, std::exception_ptr e) = 0;
/// <summary>
/// This method provides the error handler with an opportunity to handle
/// syntactic or semantic errors in the input stream before they result in a
/// <seealso cref="RecognitionException"/>.
/// <p/>
/// The generated code currently contains calls to <seealso cref="#sync"/> after
/// entering the decision state of a closure block ({@code (...)*} or
/// {@code (...)+}).
/// <p/>
/// For an implementation based on Jim Idle's "magic sync" mechanism, see
/// <seealso cref="DefaultErrorStrategy#sync"/>.
/// </summary>
/// <seealso cref= DefaultErrorStrategy#sync
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <exception cref="RecognitionException"> if an error is detected by the error
/// strategy but cannot be automatically recovered at the current state in
/// the parsing process </exception>
virtual void sync(Parser *recognizer) = 0;
/// <summary>
/// Tests whether or not {@code recognizer} is in the process of recovering
/// from an error. In error recovery mode, <seealso cref="Parser#consume"/> adds
/// symbols to the parse tree by calling
/// {@link Parser#createErrorNode(ParserRuleContext, Token)} then
/// {@link ParserRuleContext#addErrorNode(ErrorNode)} instead of
/// {@link Parser#createTerminalNode(ParserRuleContext, Token)}.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <returns> {@code true} if the parser is currently recovering from a parse
/// error, otherwise {@code false} </returns>
virtual bool inErrorRecoveryMode(Parser *recognizer) = 0;
/// <summary>
/// This method is called by when the parser successfully matches an input
/// symbol.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
virtual void reportMatch(Parser *recognizer) = 0;
/// <summary>
/// Report any kind of <seealso cref="RecognitionException"/>. This method is called by
/// the default exception handler generated for a rule method.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception to report </param>
virtual void reportError(Parser *recognizer, const RecognitionException &e) = 0;
};
} // namespace antlr4

@ -1,23 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "ANTLRFileStream.h"
using namespace antlr4;
void ANTLRFileStream::loadFromFile(const std::string &fileName) {
_fileName = fileName;
if (_fileName.empty()) {
return;
}
std::ifstream stream(fileName, std::ios::binary);
ANTLRInputStream::load(stream);
}
std::string ANTLRFileStream::getSourceName() const {
return _fileName;
}

@ -1,30 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "ANTLRInputStream.h"
namespace antlr4 {
/// This is an ANTLRInputStream that is loaded from a file all at once
/// when you construct the object (or call load()).
// TODO: this class needs testing.
class ANTLR4CPP_PUBLIC ANTLRFileStream : public ANTLRInputStream {
public:
ANTLRFileStream() = default;
ANTLRFileStream(const std::string &) = delete;
ANTLRFileStream(const char *data, size_t length) = delete;
ANTLRFileStream(std::istream &stream) = delete;
// Assumes a file name encoded in UTF-8 and file content in the same encoding (with or w/o BOM).
virtual void loadFromFile(const std::string &fileName);
virtual std::string getSourceName() const override;
private:
std::string _fileName; // UTF-8 encoded file name.
};
} // namespace antlr4

@ -1,180 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include <string.h>
#include "Exceptions.h"
#include "misc/Interval.h"
#include "IntStream.h"
#include "support/Utf8.h"
#include "support/CPPUtils.h"
#include "ANTLRInputStream.h"
using namespace antlr4;
using namespace antlrcpp;
using misc::Interval;
ANTLRInputStream::ANTLRInputStream() {
InitializeInstanceFields();
}
ANTLRInputStream::ANTLRInputStream(std::string_view input): ANTLRInputStream() {
load(input.data(), input.length());
}
ANTLRInputStream::ANTLRInputStream(const char *data, size_t length) {
load(data, length);
}
ANTLRInputStream::ANTLRInputStream(std::istream &stream): ANTLRInputStream() {
load(stream);
}
void ANTLRInputStream::load(const std::string &input, bool lenient) {
load(input.data(), input.size(), lenient);
}
void ANTLRInputStream::load(const char *data, size_t length, bool lenient) {
// Remove the UTF-8 BOM if present.
const char *bom = "\xef\xbb\xbf";
if (length >= 3 && strncmp(data, bom, 3) == 0) {
data += 3;
length -= 3;
}
if (lenient) {
_data = Utf8::lenientDecode(std::string_view(data, length));
} else {
auto maybe_utf32 = Utf8::strictDecode(std::string_view(data, length));
if (!maybe_utf32.has_value()) {
throw IllegalArgumentException("UTF-8 string contains an illegal byte sequence");
}
_data = std::move(maybe_utf32).value();
}
p = 0;
}
void ANTLRInputStream::load(std::istream &stream, bool lenient) {
if (!stream.good() || stream.eof()) // No fail, bad or EOF.
return;
_data.clear();
std::string s((std::istreambuf_iterator<char>(stream)), std::istreambuf_iterator<char>());
load(s.data(), s.length(), lenient);
}
void ANTLRInputStream::reset() {
p = 0;
}
void ANTLRInputStream::consume() {
if (p >= _data.size()) {
assert(LA(1) == IntStream::EOF);
throw IllegalStateException("cannot consume EOF");
}
if (p < _data.size()) {
p++;
}
}
size_t ANTLRInputStream::LA(ssize_t i) {
if (i == 0) {
return 0; // undefined
}
ssize_t position = static_cast<ssize_t>(p);
if (i < 0) {
i++; // e.g., translate LA(-1) to use offset i=0; then _data[p+0-1]
if ((position + i - 1) < 0) {
return IntStream::EOF; // invalid; no char before first char
}
}
if ((position + i - 1) >= static_cast<ssize_t>(_data.size())) {
return IntStream::EOF;
}
return _data[static_cast<size_t>((position + i - 1))];
}
size_t ANTLRInputStream::LT(ssize_t i) {
return LA(i);
}
size_t ANTLRInputStream::index() {
return p;
}
size_t ANTLRInputStream::size() {
return _data.size();
}
// Mark/release do nothing. We have entire buffer.
ssize_t ANTLRInputStream::mark() {
return -1;
}
void ANTLRInputStream::release(ssize_t /* marker */) {
}
void ANTLRInputStream::seek(size_t index) {
if (index <= p) {
p = index; // just jump; don't update stream state (line, ...)
return;
}
// seek forward, consume until p hits index or n (whichever comes first)
index = std::min(index, _data.size());
while (p < index) {
consume();
}
}
std::string ANTLRInputStream::getText(const Interval &interval) {
if (interval.a < 0 || interval.b < 0) {
return "";
}
size_t start = static_cast<size_t>(interval.a);
size_t stop = static_cast<size_t>(interval.b);
if (stop >= _data.size()) {
stop = _data.size() - 1;
}
size_t count = stop - start + 1;
if (start >= _data.size()) {
return "";
}
auto maybeUtf8 = Utf8::strictEncode(std::u32string_view(_data).substr(start, count));
if (!maybeUtf8.has_value()) {
throw IllegalArgumentException("Input stream contains invalid Unicode code points");
}
return std::move(maybeUtf8).value();
}
std::string ANTLRInputStream::getSourceName() const {
if (name.empty()) {
return IntStream::UNKNOWN_SOURCE_NAME;
}
return name;
}
std::string ANTLRInputStream::toString() const {
auto maybeUtf8 = Utf8::strictEncode(_data);
if (!maybeUtf8.has_value()) {
throw IllegalArgumentException("Input stream contains invalid Unicode code points");
}
return std::move(maybeUtf8).value();
}
void ANTLRInputStream::InitializeInstanceFields() {
p = 0;
}

@ -1,79 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include <string_view>
#include "CharStream.h"
namespace antlr4 {
// Vacuum all input from a stream and then treat it
// like a string. Can also pass in a string or char[] to use.
// Input is expected to be encoded in UTF-8 and converted to UTF-32 internally.
class ANTLR4CPP_PUBLIC ANTLRInputStream : public CharStream {
protected:
/// The data being scanned.
// UTF-32
std::u32string _data;
/// 0..n-1 index into string of next char </summary>
size_t p;
public:
/// What is name or source of this char stream?
std::string name;
ANTLRInputStream();
ANTLRInputStream(std::string_view input);
ANTLRInputStream(const char *data, size_t length);
ANTLRInputStream(std::istream &stream);
virtual void load(const std::string &input, bool lenient);
virtual void load(const char *data, size_t length, bool lenient);
virtual void load(std::istream &stream, bool lenient);
virtual void load(const std::string &input) { load(input, false); }
virtual void load(const char *data, size_t length) { load(data, length, false); }
virtual void load(std::istream &stream) { load(stream, false); }
/// Reset the stream so that it's in the same state it was
/// when the object was created *except* the data array is not
/// touched.
virtual void reset();
virtual void consume() override;
virtual size_t LA(ssize_t i) override;
virtual size_t LT(ssize_t i);
/// <summary>
/// Return the current input symbol index 0..n where n indicates the
/// last symbol has been read. The index is the index of char to
/// be returned from LA(1).
/// </summary>
virtual size_t index() override;
virtual size_t size() override;
/// <summary>
/// mark/release do nothing; we have entire buffer </summary>
virtual ssize_t mark() override;
virtual void release(ssize_t marker) override;
/// <summary>
/// consume() ahead until p==index; can't just set p=index as we must
/// update line and charPositionInLine. If we seek backwards, just set p
/// </summary>
virtual void seek(size_t index) override;
virtual std::string getText(const misc::Interval &interval) override;
virtual std::string getSourceName() const override;
virtual std::string toString() const override;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

@ -1,61 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "Exceptions.h"
#include "ParserRuleContext.h"
#include "InputMismatchException.h"
#include "Parser.h"
#include "BailErrorStrategy.h"
using namespace antlr4;
void BailErrorStrategy::recover(Parser *recognizer, std::exception_ptr e) {
ParserRuleContext *context = recognizer->getContext();
do {
context->exception = e;
if (context->parent == nullptr)
break;
context = static_cast<ParserRuleContext *>(context->parent);
} while (true);
try {
std::rethrow_exception(e); // Throw the exception to be able to catch and rethrow nested.
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
} catch (RecognitionException &inner) {
throw ParseCancellationException(inner.what());
#else
} catch (RecognitionException & /*inner*/) {
std::throw_with_nested(ParseCancellationException());
#endif
}
}
Token* BailErrorStrategy::recoverInline(Parser *recognizer) {
InputMismatchException e(recognizer);
std::exception_ptr exception = std::make_exception_ptr(e);
ParserRuleContext *context = recognizer->getContext();
do {
context->exception = exception;
if (context->parent == nullptr)
break;
context = static_cast<ParserRuleContext *>(context->parent);
} while (true);
try {
throw e;
#if defined(_MSC_FULL_VER) && _MSC_FULL_VER < 190023026
} catch (InputMismatchException &inner) {
throw ParseCancellationException(inner.what());
#else
} catch (InputMismatchException & /*inner*/) {
std::throw_with_nested(ParseCancellationException());
#endif
}
}
void BailErrorStrategy::sync(Parser * /*recognizer*/) {
}

@ -1,59 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "DefaultErrorStrategy.h"
namespace antlr4 {
/**
* This implementation of {@link ANTLRErrorStrategy} responds to syntax errors
* by immediately canceling the parse operation with a
* {@link ParseCancellationException}. The implementation ensures that the
* {@link ParserRuleContext#exception} field is set for all parse tree nodes
* that were not completed prior to encountering the error.
*
* <p>
* This error strategy is useful in the following scenarios.</p>
*
* <ul>
* <li><strong>Two-stage parsing:</strong> This error strategy allows the first
* stage of two-stage parsing to immediately terminate if an error is
* encountered, and immediately fall back to the second stage. In addition to
* avoiding wasted work by attempting to recover from errors here, the empty
* implementation of {@link BailErrorStrategy#sync} improves the performance of
* the first stage.</li>
* <li><strong>Silent validation:</strong> When syntax errors are not being
* reported or logged, and the parse result is simply ignored if errors occur,
* the {@link BailErrorStrategy} avoids wasting work on recovering from errors
* when the result will be ignored either way.</li>
* </ul>
*
* <p>
* {@code myparser.setErrorHandler(new BailErrorStrategy());}</p>
*
* @see Parser#setErrorHandler(ANTLRErrorStrategy)
*/
class ANTLR4CPP_PUBLIC BailErrorStrategy : public DefaultErrorStrategy {
/// <summary>
/// Instead of recovering from exception {@code e}, re-throw it wrapped
/// in a <seealso cref="ParseCancellationException"/> so it is not caught by the
/// rule function catches. Use <seealso cref="Exception#getCause()"/> to get the
/// original <seealso cref="RecognitionException"/>.
/// </summary>
public:
virtual void recover(Parser *recognizer, std::exception_ptr e) override;
/// Make sure we don't attempt to recover inline; if the parser
/// successfully recovers, it won't throw an exception.
virtual Token* recoverInline(Parser *recognizer) override;
/// <summary>
/// Make sure we don't attempt to recover from problems in subrules. </summary>
virtual void sync(Parser *recognizer) override;
};
} // namespace antlr4

@ -1,25 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "BaseErrorListener.h"
#include "RecognitionException.h"
using namespace antlr4;
void BaseErrorListener::syntaxError(Recognizer * /*recognizer*/, Token * /*offendingSymbol*/, size_t /*line*/,
size_t /*charPositionInLine*/, const std::string &/*msg*/, std::exception_ptr /*e*/) {
}
void BaseErrorListener::reportAmbiguity(Parser * /*recognizer*/, const dfa::DFA &/*dfa*/, size_t /*startIndex*/,
size_t /*stopIndex*/, bool /*exact*/, const antlrcpp::BitSet &/*ambigAlts*/, atn::ATNConfigSet * /*configs*/) {
}
void BaseErrorListener::reportAttemptingFullContext(Parser * /*recognizer*/, const dfa::DFA &/*dfa*/, size_t /*startIndex*/,
size_t /*stopIndex*/, const antlrcpp::BitSet &/*conflictingAlts*/, atn::ATNConfigSet * /*configs*/) {
}
void BaseErrorListener::reportContextSensitivity(Parser * /*recognizer*/, const dfa::DFA &/*dfa*/, size_t /*startIndex*/,
size_t /*stopIndex*/, size_t /*prediction*/, atn::ATNConfigSet * /*configs*/) {
}

@ -1,36 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "ANTLRErrorListener.h"
namespace antlrcpp {
class BitSet;
}
namespace antlr4 {
/**
* Provides an empty default implementation of {@link ANTLRErrorListener}. The
* default implementation of each method does nothing, but can be overridden as
* necessary.
*/
class ANTLR4CPP_PUBLIC BaseErrorListener : public ANTLRErrorListener {
virtual void syntaxError(Recognizer *recognizer, Token * offendingSymbol, size_t line, size_t charPositionInLine,
const std::string &msg, std::exception_ptr e) override;
virtual void reportAmbiguity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex, bool exact,
const antlrcpp::BitSet &ambigAlts, atn::ATNConfigSet *configs) override;
virtual void reportAttemptingFullContext(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
const antlrcpp::BitSet &conflictingAlts, atn::ATNConfigSet *configs) override;
virtual void reportContextSensitivity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
size_t prediction, atn::ATNConfigSet *configs) override;
};
} // namespace antlr4

@ -1,414 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "WritableToken.h"
#include "Lexer.h"
#include "RuleContext.h"
#include "misc/Interval.h"
#include "Exceptions.h"
#include "support/CPPUtils.h"
#include "BufferedTokenStream.h"
using namespace antlr4;
using namespace antlrcpp;
BufferedTokenStream::BufferedTokenStream(TokenSource *tokenSource) : _tokenSource(tokenSource){
InitializeInstanceFields();
}
TokenSource* BufferedTokenStream::getTokenSource() const {
return _tokenSource;
}
size_t BufferedTokenStream::index() {
return _p;
}
ssize_t BufferedTokenStream::mark() {
return 0;
}
void BufferedTokenStream::release(ssize_t /*marker*/) {
// no resources to release
}
void BufferedTokenStream::reset() {
seek(0);
}
void BufferedTokenStream::seek(size_t index) {
lazyInit();
_p = adjustSeekIndex(index);
}
size_t BufferedTokenStream::size() {
return _tokens.size();
}
void BufferedTokenStream::consume() {
bool skipEofCheck = false;
if (!_needSetup) {
if (_fetchedEOF) {
// the last token in tokens is EOF. skip check if p indexes any
// fetched token except the last.
skipEofCheck = _p < _tokens.size() - 1;
} else {
// no EOF token in tokens. skip check if p indexes a fetched token.
skipEofCheck = _p < _tokens.size();
}
} else {
// not yet initialized
skipEofCheck = false;
}
if (!skipEofCheck && LA(1) == Token::EOF) {
throw IllegalStateException("cannot consume EOF");
}
if (sync(_p + 1)) {
_p = adjustSeekIndex(_p + 1);
}
}
bool BufferedTokenStream::sync(size_t i) {
if (i + 1 < _tokens.size())
return true;
size_t n = i - _tokens.size() + 1; // how many more elements we need?
if (n > 0) {
size_t fetched = fetch(n);
return fetched >= n;
}
return true;
}
size_t BufferedTokenStream::fetch(size_t n) {
if (_fetchedEOF) {
return 0;
}
size_t i = 0;
while (i < n) {
std::unique_ptr<Token> t(_tokenSource->nextToken());
if (is<WritableToken *>(t.get())) {
(static_cast<WritableToken *>(t.get()))->setTokenIndex(_tokens.size());
}
_tokens.push_back(std::move(t));
++i;
if (_tokens.back()->getType() == Token::EOF) {
_fetchedEOF = true;
break;
}
}
return i;
}
Token* BufferedTokenStream::get(size_t i) const {
if (i >= _tokens.size()) {
throw IndexOutOfBoundsException(std::string("token index ") +
std::to_string(i) +
std::string(" out of range 0..") +
std::to_string(_tokens.size() - 1));
}
return _tokens[i].get();
}
std::vector<Token *> BufferedTokenStream::get(size_t start, size_t stop) {
std::vector<Token *> subset;
lazyInit();
if (_tokens.empty()) {
return subset;
}
if (stop >= _tokens.size()) {
stop = _tokens.size() - 1;
}
for (size_t i = start; i <= stop; i++) {
Token *t = _tokens[i].get();
if (t->getType() == Token::EOF) {
break;
}
subset.push_back(t);
}
return subset;
}
size_t BufferedTokenStream::LA(ssize_t i) {
return LT(i)->getType();
}
Token* BufferedTokenStream::LB(size_t k) {
if (k > _p) {
return nullptr;
}
return _tokens[_p - k].get();
}
Token* BufferedTokenStream::LT(ssize_t k) {
lazyInit();
if (k == 0) {
return nullptr;
}
if (k < 0) {
return LB(-k);
}
size_t i = _p + k - 1;
sync(i);
if (i >= _tokens.size()) { // return EOF token
// EOF must be last token
return _tokens.back().get();
}
return _tokens[i].get();
}
ssize_t BufferedTokenStream::adjustSeekIndex(size_t i) {
return i;
}
void BufferedTokenStream::lazyInit() {
if (_needSetup) {
setup();
}
}
void BufferedTokenStream::setup() {
_needSetup = false;
sync(0);
_p = adjustSeekIndex(0);
}
void BufferedTokenStream::setTokenSource(TokenSource *tokenSource) {
_tokenSource = tokenSource;
_tokens.clear();
_fetchedEOF = false;
_needSetup = true;
}
std::vector<Token *> BufferedTokenStream::getTokens() {
std::vector<Token *> result;
for (auto &t : _tokens)
result.push_back(t.get());
return result;
}
std::vector<Token *> BufferedTokenStream::getTokens(size_t start, size_t stop) {
return getTokens(start, stop, std::vector<size_t>());
}
std::vector<Token *> BufferedTokenStream::getTokens(size_t start, size_t stop, const std::vector<size_t> &types) {
lazyInit();
if (stop >= _tokens.size() || start >= _tokens.size()) {
throw IndexOutOfBoundsException(std::string("start ") +
std::to_string(start) +
std::string(" or stop ") +
std::to_string(stop) +
std::string(" not in 0..") +
std::to_string(_tokens.size() - 1));
}
std::vector<Token *> filteredTokens;
if (start > stop) {
return filteredTokens;
}
for (size_t i = start; i <= stop; i++) {
Token *tok = _tokens[i].get();
if (types.empty() || std::find(types.begin(), types.end(), tok->getType()) != types.end()) {
filteredTokens.push_back(tok);
}
}
return filteredTokens;
}
std::vector<Token *> BufferedTokenStream::getTokens(size_t start, size_t stop, size_t ttype) {
std::vector<size_t> s;
s.push_back(ttype);
return getTokens(start, stop, s);
}
ssize_t BufferedTokenStream::nextTokenOnChannel(size_t i, size_t channel) {
sync(i);
if (i >= size()) {
return size() - 1;
}
Token *token = _tokens[i].get();
while (token->getChannel() != channel) {
if (token->getType() == Token::EOF) {
return i;
}
i++;
sync(i);
token = _tokens[i].get();
}
return i;
}
ssize_t BufferedTokenStream::previousTokenOnChannel(size_t i, size_t channel) {
sync(i);
if (i >= size()) {
// the EOF token is on every channel
return size() - 1;
}
while (true) {
Token *token = _tokens[i].get();
if (token->getType() == Token::EOF || token->getChannel() == channel) {
return i;
}
if (i == 0)
return -1;
i--;
}
return i;
}
std::vector<Token *> BufferedTokenStream::getHiddenTokensToRight(size_t tokenIndex, ssize_t channel) {
lazyInit();
if (tokenIndex >= _tokens.size()) {
throw IndexOutOfBoundsException(std::to_string(tokenIndex) + " not in 0.." + std::to_string(_tokens.size() - 1));
}
ssize_t nextOnChannel = nextTokenOnChannel(tokenIndex + 1, Lexer::DEFAULT_TOKEN_CHANNEL);
size_t to;
size_t from = tokenIndex + 1;
// if none onchannel to right, nextOnChannel=-1 so set to = last token
if (nextOnChannel == -1) {
to = static_cast<ssize_t>(size() - 1);
} else {
to = nextOnChannel;
}
return filterForChannel(from, to, channel);
}
std::vector<Token *> BufferedTokenStream::getHiddenTokensToRight(size_t tokenIndex) {
return getHiddenTokensToRight(tokenIndex, -1);
}
std::vector<Token *> BufferedTokenStream::getHiddenTokensToLeft(size_t tokenIndex, ssize_t channel) {
lazyInit();
if (tokenIndex >= _tokens.size()) {
throw IndexOutOfBoundsException(std::to_string(tokenIndex) + " not in 0.." + std::to_string(_tokens.size() - 1));
}
if (tokenIndex == 0) {
// Obviously no tokens can appear before the first token.
return { };
}
ssize_t prevOnChannel = previousTokenOnChannel(tokenIndex - 1, Lexer::DEFAULT_TOKEN_CHANNEL);
if (prevOnChannel == static_cast<ssize_t>(tokenIndex - 1)) {
return { };
}
// if none onchannel to left, prevOnChannel=-1 then from=0
size_t from = static_cast<size_t>(prevOnChannel + 1);
size_t to = tokenIndex - 1;
return filterForChannel(from, to, channel);
}
std::vector<Token *> BufferedTokenStream::getHiddenTokensToLeft(size_t tokenIndex) {
return getHiddenTokensToLeft(tokenIndex, -1);
}
std::vector<Token *> BufferedTokenStream::filterForChannel(size_t from, size_t to, ssize_t channel) {
std::vector<Token *> hidden;
for (size_t i = from; i <= to; i++) {
Token *t = _tokens[i].get();
if (channel == -1) {
if (t->getChannel() != Lexer::DEFAULT_TOKEN_CHANNEL) {
hidden.push_back(t);
}
} else {
if (t->getChannel() == static_cast<size_t>(channel)) {
hidden.push_back(t);
}
}
}
return hidden;
}
bool BufferedTokenStream::isInitialized() const {
return !_needSetup;
}
/**
* Get the text of all tokens in this buffer.
*/
std::string BufferedTokenStream::getSourceName() const
{
return _tokenSource->getSourceName();
}
std::string BufferedTokenStream::getText() {
fill();
return getText(misc::Interval(0U, size() - 1));
}
std::string BufferedTokenStream::getText(const misc::Interval &interval) {
lazyInit();
size_t start = interval.a;
size_t stop = interval.b;
if (start == INVALID_INDEX || stop == INVALID_INDEX) {
return "";
}
sync(stop);
if (stop >= _tokens.size()) {
stop = _tokens.size() - 1;
}
std::stringstream ss;
for (size_t i = start; i <= stop; i++) {
Token *t = _tokens[i].get();
if (t->getType() == Token::EOF) {
break;
}
ss << t->getText();
}
return ss.str();
}
std::string BufferedTokenStream::getText(RuleContext *ctx) {
return getText(ctx->getSourceInterval());
}
std::string BufferedTokenStream::getText(Token *start, Token *stop) {
if (start != nullptr && stop != nullptr) {
return getText(misc::Interval(start->getTokenIndex(), stop->getTokenIndex()));
}
return "";
}
void BufferedTokenStream::fill() {
lazyInit();
const size_t blockSize = 1000;
while (true) {
size_t fetched = fetch(blockSize);
if (fetched < blockSize) {
return;
}
}
}
void BufferedTokenStream::InitializeInstanceFields() {
_needSetup = true;
_fetchedEOF = false;
}

@ -1,200 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "TokenStream.h"
namespace antlr4 {
/**
* This implementation of {@link TokenStream} loads tokens from a
* {@link TokenSource} on-demand, and places the tokens in a buffer to provide
* access to any previous token by index.
*
* <p>
* This token stream ignores the value of {@link Token#getChannel}. If your
* parser requires the token stream filter tokens to only those on a particular
* channel, such as {@link Token#DEFAULT_CHANNEL} or
* {@link Token#HIDDEN_CHANNEL}, use a filtering token stream such a
* {@link CommonTokenStream}.</p>
*/
class ANTLR4CPP_PUBLIC BufferedTokenStream : public TokenStream {
public:
BufferedTokenStream(TokenSource *tokenSource);
BufferedTokenStream(const BufferedTokenStream& other) = delete;
BufferedTokenStream& operator = (const BufferedTokenStream& other) = delete;
virtual TokenSource* getTokenSource() const override;
virtual size_t index() override;
virtual ssize_t mark() override;
virtual void release(ssize_t marker) override;
virtual void reset();
virtual void seek(size_t index) override;
virtual size_t size() override;
virtual void consume() override;
virtual Token* get(size_t i) const override;
/// Get all tokens from start..stop inclusively.
virtual std::vector<Token *> get(size_t start, size_t stop);
virtual size_t LA(ssize_t i) override;
virtual Token* LT(ssize_t k) override;
/// Reset this token stream by setting its token source.
virtual void setTokenSource(TokenSource *tokenSource);
virtual std::vector<Token *> getTokens();
virtual std::vector<Token *> getTokens(size_t start, size_t stop);
/// <summary>
/// Given a start and stop index, return a List of all tokens in
/// the token type BitSet. Return null if no tokens were found. This
/// method looks at both on and off channel tokens.
/// </summary>
virtual std::vector<Token *> getTokens(size_t start, size_t stop, const std::vector<size_t> &types);
virtual std::vector<Token *> getTokens(size_t start, size_t stop, size_t ttype);
/// Collect all tokens on specified channel to the right of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL or
/// EOF. If channel is -1, find any non default channel token.
virtual std::vector<Token *> getHiddenTokensToRight(size_t tokenIndex, ssize_t channel);
/// <summary>
/// Collect all hidden tokens (any off-default channel) to the right of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL
/// or EOF.
/// </summary>
virtual std::vector<Token *> getHiddenTokensToRight(size_t tokenIndex);
/// <summary>
/// Collect all tokens on specified channel to the left of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
/// If channel is -1, find any non default channel token.
/// </summary>
virtual std::vector<Token *> getHiddenTokensToLeft(size_t tokenIndex, ssize_t channel);
/// <summary>
/// Collect all hidden tokens (any off-default channel) to the left of
/// the current token up until we see a token on DEFAULT_TOKEN_CHANNEL.
/// </summary>
virtual std::vector<Token *> getHiddenTokensToLeft(size_t tokenIndex);
virtual std::string getSourceName() const override;
virtual std::string getText() override;
virtual std::string getText(const misc::Interval &interval) override;
virtual std::string getText(RuleContext *ctx) override;
virtual std::string getText(Token *start, Token *stop) override;
/// Get all tokens from lexer until EOF.
virtual void fill();
protected:
/**
* The {@link TokenSource} from which tokens for this stream are fetched.
*/
TokenSource *_tokenSource;
/**
* A collection of all tokens fetched from the token source. The list is
* considered a complete view of the input once {@link #fetchedEOF} is set
* to {@code true}.
*/
std::vector<std::unique_ptr<Token>> _tokens;
/**
* The index into {@link #tokens} of the current token (next token to
* {@link #consume}). {@link #tokens}{@code [}{@link #p}{@code ]} should be
* {@link #LT LT(1)}.
*
* <p>This field is set to -1 when the stream is first constructed or when
* {@link #setTokenSource} is called, indicating that the first token has
* not yet been fetched from the token source. For additional information,
* see the documentation of {@link IntStream} for a description of
* Initializing Methods.</p>
*/
// ml: since -1 requires to make this member signed for just this single aspect we use a member _needSetup instead.
// Use bool isInitialized() to find out if this stream has started reading.
size_t _p;
/**
* Indicates whether the {@link Token#EOF} token has been fetched from
* {@link #tokenSource} and added to {@link #tokens}. This field improves
* performance for the following cases:
*
* <ul>
* <li>{@link #consume}: The lookahead check in {@link #consume} to prevent
* consuming the EOF symbol is optimized by checking the values of
* {@link #fetchedEOF} and {@link #p} instead of calling {@link #LA}.</li>
* <li>{@link #fetch}: The check to prevent adding multiple EOF symbols into
* {@link #tokens} is trivial with this field.</li>
* <ul>
*/
bool _fetchedEOF;
/// <summary>
/// Make sure index {@code i} in tokens has a token.
/// </summary>
/// <returns> {@code true} if a token is located at index {@code i}, otherwise
/// {@code false}. </returns>
/// <seealso cref= #get(int i) </seealso>
virtual bool sync(size_t i);
/// <summary>
/// Add {@code n} elements to buffer.
/// </summary>
/// <returns> The actual number of elements added to the buffer. </returns>
virtual size_t fetch(size_t n);
virtual Token* LB(size_t k);
/// Allowed derived classes to modify the behavior of operations which change
/// the current stream position by adjusting the target token index of a seek
/// operation. The default implementation simply returns {@code i}. If an
/// exception is thrown in this method, the current stream index should not be
/// changed.
/// <p/>
/// For example, <seealso cref="CommonTokenStream"/> overrides this method to ensure that
/// the seek target is always an on-channel token.
///
/// <param name="i"> The target token index. </param>
/// <returns> The adjusted target token index. </returns>
virtual ssize_t adjustSeekIndex(size_t i);
void lazyInit();
virtual void setup();
/**
* Given a starting index, return the index of the next token on channel.
* Return {@code i} if {@code tokens[i]} is on channel. Return the index of
* the EOF token if there are no tokens on channel between {@code i} and
* EOF.
*/
virtual ssize_t nextTokenOnChannel(size_t i, size_t channel);
/**
* Given a starting index, return the index of the previous token on
* channel. Return {@code i} if {@code tokens[i]} is on channel. Return -1
* if there are no tokens on channel between {@code i} and 0.
*
* <p>
* If {@code i} specifies an index at or after the EOF token, the EOF token
* index is returned. This is due to the fact that the EOF token is treated
* as though it were on every channel.</p>
*/
virtual ssize_t previousTokenOnChannel(size_t i, size_t channel);
virtual std::vector<Token *> filterForChannel(size_t from, size_t to, ssize_t channel);
bool isInitialized() const;
private:
bool _needSetup;
void InitializeInstanceFields();
};
} // namespace antlr4

@ -1,11 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "CharStream.h"
using namespace antlr4;
CharStream::~CharStream() {
}

@ -1,37 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "IntStream.h"
#include "misc/Interval.h"
namespace antlr4 {
/// A source of characters for an ANTLR lexer.
class ANTLR4CPP_PUBLIC CharStream : public IntStream {
public:
virtual ~CharStream();
/// This method returns the text for a range of characters within this input
/// stream. This method is guaranteed to not throw an exception if the
/// specified interval lies entirely within a marked range. For more
/// information about marked ranges, see IntStream::mark.
///
/// <param name="interval"> an interval within the stream </param>
/// <returns> the text of the specified interval
/// </returns>
/// <exception cref="NullPointerException"> if {@code interval} is {@code null} </exception>
/// <exception cref="IllegalArgumentException"> if {@code interval.a < 0}, or if
/// {@code interval.b < interval.a - 1}, or if {@code interval.b} lies at or
/// past the end of the stream </exception>
/// <exception cref="UnsupportedOperationException"> if the stream does not support
/// getting the text of the specified interval </exception>
virtual std::string getText(const misc::Interval &interval) = 0;
virtual std::string toString() const = 0;
};
} // namespace antlr4

@ -1,193 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "TokenSource.h"
#include "CharStream.h"
#include "Recognizer.h"
#include "Vocabulary.h"
#include "misc/Interval.h"
#include "support/CPPUtils.h"
#include "support/StringUtils.h"
#include "CommonToken.h"
using namespace antlr4;
using namespace antlr4::misc;
using namespace antlrcpp;
const std::pair<TokenSource*, CharStream*> CommonToken::EMPTY_SOURCE;
CommonToken::CommonToken(size_t type) {
InitializeInstanceFields();
_type = type;
}
CommonToken::CommonToken(std::pair<TokenSource*, CharStream*> source, size_t type, size_t channel, size_t start, size_t stop) {
InitializeInstanceFields();
_source = source;
_type = type;
_channel = channel;
_start = start;
_stop = stop;
if (_source.first != nullptr) {
_line = static_cast<int>(source.first->getLine());
_charPositionInLine = source.first->getCharPositionInLine();
}
}
CommonToken::CommonToken(size_t type, const std::string &text) {
InitializeInstanceFields();
_type = type;
_channel = DEFAULT_CHANNEL;
_text = text;
_source = EMPTY_SOURCE;
}
CommonToken::CommonToken(Token *oldToken) {
InitializeInstanceFields();
_type = oldToken->getType();
_line = oldToken->getLine();
_index = oldToken->getTokenIndex();
_charPositionInLine = oldToken->getCharPositionInLine();
_channel = oldToken->getChannel();
_start = oldToken->getStartIndex();
_stop = oldToken->getStopIndex();
if (is<CommonToken *>(oldToken)) {
_text = (static_cast<CommonToken *>(oldToken))->_text;
_source = (static_cast<CommonToken *>(oldToken))->_source;
} else {
_text = oldToken->getText();
_source = { oldToken->getTokenSource(), oldToken->getInputStream() };
}
}
size_t CommonToken::getType() const {
return _type;
}
void CommonToken::setLine(size_t line) {
_line = line;
}
std::string CommonToken::getText() const {
if (!_text.empty()) {
return _text;
}
CharStream *input = getInputStream();
if (input == nullptr) {
return "";
}
size_t n = input->size();
if (_start < n && _stop < n) {
return input->getText(misc::Interval(_start, _stop));
} else {
return "<EOF>";
}
}
void CommonToken::setText(const std::string &text) {
_text = text;
}
size_t CommonToken::getLine() const {
return _line;
}
size_t CommonToken::getCharPositionInLine() const {
return _charPositionInLine;
}
void CommonToken::setCharPositionInLine(size_t charPositionInLine) {
_charPositionInLine = charPositionInLine;
}
size_t CommonToken::getChannel() const {
return _channel;
}
void CommonToken::setChannel(size_t channel) {
_channel = channel;
}
void CommonToken::setType(size_t type) {
_type = type;
}
size_t CommonToken::getStartIndex() const {
return _start;
}
void CommonToken::setStartIndex(size_t start) {
_start = start;
}
size_t CommonToken::getStopIndex() const {
return _stop;
}
void CommonToken::setStopIndex(size_t stop) {
_stop = stop;
}
size_t CommonToken::getTokenIndex() const {
return _index;
}
void CommonToken::setTokenIndex(size_t index) {
_index = index;
}
antlr4::TokenSource *CommonToken::getTokenSource() const {
return _source.first;
}
antlr4::CharStream *CommonToken::getInputStream() const {
return _source.second;
}
std::string CommonToken::toString() const {
return toString(nullptr);
}
std::string CommonToken::toString(Recognizer *r) const {
std::stringstream ss;
std::string channelStr;
if (_channel > 0) {
channelStr = ",channel=" + std::to_string(_channel);
}
std::string txt = getText();
if (!txt.empty()) {
txt = antlrcpp::escapeWhitespace(txt);
} else {
txt = "<no text>";
}
std::string typeString = std::to_string(symbolToNumeric(_type));
if (r != nullptr)
typeString = r->getVocabulary().getDisplayName(_type);
ss << "[@" << symbolToNumeric(getTokenIndex()) << "," << symbolToNumeric(_start) << ":" << symbolToNumeric(_stop)
<< "='" << txt << "',<" << typeString << ">" << channelStr << "," << _line << ":"
<< getCharPositionInLine() << "]";
return ss.str();
}
void CommonToken::InitializeInstanceFields() {
_type = 0;
_line = 0;
_charPositionInLine = INVALID_INDEX;
_channel = DEFAULT_CHANNEL;
_index = INVALID_INDEX;
_start = 0;
_stop = 0;
_source = EMPTY_SOURCE;
}

@ -1,158 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "WritableToken.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC CommonToken : public WritableToken {
protected:
/**
* An empty {@link Pair} which is used as the default value of
* {@link #source} for tokens that do not have a source.
*/
static const std::pair<TokenSource *, CharStream *> EMPTY_SOURCE;
/**
* This is the backing field for {@link #getType} and {@link #setType}.
*/
size_t _type;
/**
* This is the backing field for {@link #getLine} and {@link #setLine}.
*/
size_t _line;
/**
* This is the backing field for {@link #getCharPositionInLine} and
* {@link #setCharPositionInLine}.
*/
size_t _charPositionInLine; // set to invalid position
/**
* This is the backing field for {@link #getChannel} and
* {@link #setChannel}.
*/
size_t _channel;
/**
* This is the backing field for {@link #getTokenSource} and
* {@link #getInputStream}.
*
* <p>
* These properties share a field to reduce the memory footprint of
* {@link CommonToken}. Tokens created by a {@link CommonTokenFactory} from
* the same source and input stream share a reference to the same
* {@link Pair} containing these values.</p>
*/
std::pair<TokenSource *, CharStream *> _source; // ml: pure references, usually from statically allocated classes.
/**
* This is the backing field for {@link #getText} when the token text is
* explicitly set in the constructor or via {@link #setText}.
*
* @see #getText()
*/
std::string _text;
/**
* This is the backing field for {@link #getTokenIndex} and
* {@link #setTokenIndex}.
*/
size_t _index;
/**
* This is the backing field for {@link #getStartIndex} and
* {@link #setStartIndex}.
*/
size_t _start;
/**
* This is the backing field for {@link #getStopIndex} and
* {@link #setStopIndex}.
*/
size_t _stop;
public:
/**
* Constructs a new {@link CommonToken} with the specified token type.
*
* @param type The token type.
*/
CommonToken(size_t type);
CommonToken(std::pair<TokenSource*, CharStream*> source, size_t type, size_t channel, size_t start, size_t stop);
/**
* Constructs a new {@link CommonToken} with the specified token type and
* text.
*
* @param type The token type.
* @param text The text of the token.
*/
CommonToken(size_t type, const std::string &text);
/**
* Constructs a new {@link CommonToken} as a copy of another {@link Token}.
*
* <p>
* If {@code oldToken} is also a {@link CommonToken} instance, the newly
* constructed token will share a reference to the {@link #text} field and
* the {@link Pair} stored in {@link #source}. Otherwise, {@link #text} will
* be assigned the result of calling {@link #getText}, and {@link #source}
* will be constructed from the result of {@link Token#getTokenSource} and
* {@link Token#getInputStream}.</p>
*
* @param oldToken The token to copy.
*/
CommonToken(Token *oldToken);
virtual size_t getType() const override;
/**
* Explicitly set the text for this token. If {code text} is not
* {@code null}, then {@link #getText} will return this value rather than
* extracting the text from the input.
*
* @param text The explicit text of the token, or {@code null} if the text
* should be obtained from the input along with the start and stop indexes
* of the token.
*/
virtual void setText(const std::string &text) override;
virtual std::string getText() const override;
virtual void setLine(size_t line) override;
virtual size_t getLine() const override;
virtual size_t getCharPositionInLine() const override;
virtual void setCharPositionInLine(size_t charPositionInLine) override;
virtual size_t getChannel() const override;
virtual void setChannel(size_t channel) override;
virtual void setType(size_t type) override;
virtual size_t getStartIndex() const override;
virtual void setStartIndex(size_t start);
virtual size_t getStopIndex() const override;
virtual void setStopIndex(size_t stop);
virtual size_t getTokenIndex() const override;
virtual void setTokenIndex(size_t index) override;
virtual TokenSource *getTokenSource() const override;
virtual CharStream *getInputStream() const override;
virtual std::string toString() const override;
virtual std::string toString(Recognizer *r) const;
private:
void InitializeInstanceFields();
};
} // namespace antlr4

@ -1,39 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "misc/Interval.h"
#include "CommonToken.h"
#include "CharStream.h"
#include "CommonTokenFactory.h"
using namespace antlr4;
const std::unique_ptr<TokenFactory<CommonToken>> CommonTokenFactory::DEFAULT(new CommonTokenFactory);
CommonTokenFactory::CommonTokenFactory(bool copyText_) : copyText(copyText_) {
}
CommonTokenFactory::CommonTokenFactory() : CommonTokenFactory(false) {
}
std::unique_ptr<CommonToken> CommonTokenFactory::create(std::pair<TokenSource*, CharStream*> source, size_t type,
const std::string &text, size_t channel, size_t start, size_t stop, size_t line, size_t charPositionInLine) {
std::unique_ptr<CommonToken> t(new CommonToken(source, type, channel, start, stop));
t->setLine(line);
t->setCharPositionInLine(charPositionInLine);
if (text != "") {
t->setText(text);
} else if (copyText && source.second != nullptr) {
t->setText(source.second->getText(misc::Interval(start, stop)));
}
return t;
}
std::unique_ptr<CommonToken> CommonTokenFactory::create(size_t type, const std::string &text) {
return std::unique_ptr<CommonToken>(new CommonToken(type, text));
}

@ -1,74 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "TokenFactory.h"
namespace antlr4 {
/**
* This default implementation of {@link TokenFactory} creates
* {@link CommonToken} objects.
*/
class ANTLR4CPP_PUBLIC CommonTokenFactory : public TokenFactory<CommonToken> {
public:
/**
* The default {@link CommonTokenFactory} instance.
*
* <p>
* This token factory does not explicitly copy token text when constructing
* tokens.</p>
*/
static const std::unique_ptr<TokenFactory<CommonToken>> DEFAULT;
protected:
/**
* Indicates whether {@link CommonToken#setText} should be called after
* constructing tokens to explicitly set the text. This is useful for cases
* where the input stream might not be able to provide arbitrary substrings
* of text from the input after the lexer creates a token (e.g. the
* implementation of {@link CharStream#getText} in
* {@link UnbufferedCharStream} throws an
* {@link UnsupportedOperationException}). Explicitly setting the token text
* allows {@link Token#getText} to be called at any time regardless of the
* input stream implementation.
*
* <p>
* The default value is {@code false} to avoid the performance and memory
* overhead of copying text for every token unless explicitly requested.</p>
*/
const bool copyText;
public:
/**
* Constructs a {@link CommonTokenFactory} with the specified value for
* {@link #copyText}.
*
* <p>
* When {@code copyText} is {@code false}, the {@link #DEFAULT} instance
* should be used instead of constructing a new instance.</p>
*
* @param copyText The value for {@link #copyText}.
*/
CommonTokenFactory(bool copyText);
/**
* Constructs a {@link CommonTokenFactory} with {@link #copyText} set to
* {@code false}.
*
* <p>
* The {@link #DEFAULT} instance should be used instead of calling this
* directly.</p>
*/
CommonTokenFactory();
virtual std::unique_ptr<CommonToken> create(std::pair<TokenSource*, CharStream*> source, size_t type,
const std::string &text, size_t channel, size_t start, size_t stop, size_t line, size_t charPositionInLine) override;
virtual std::unique_ptr<CommonToken> create(size_t type, const std::string &text) override;
};
} // namespace antlr4

@ -1,78 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "Token.h"
#include "CommonTokenStream.h"
using namespace antlr4;
CommonTokenStream::CommonTokenStream(TokenSource *tokenSource) : CommonTokenStream(tokenSource, Token::DEFAULT_CHANNEL) {
}
CommonTokenStream::CommonTokenStream(TokenSource *tokenSource, size_t channel_)
: BufferedTokenStream(tokenSource), channel(channel_) {
}
ssize_t CommonTokenStream::adjustSeekIndex(size_t i) {
return nextTokenOnChannel(i, channel);
}
Token* CommonTokenStream::LB(size_t k) {
if (k == 0 || k > _p) {
return nullptr;
}
ssize_t i = static_cast<ssize_t>(_p);
size_t n = 1;
// find k good tokens looking backwards
while (n <= k) {
// skip off-channel tokens
i = previousTokenOnChannel(i - 1, channel);
n++;
}
if (i < 0) {
return nullptr;
}
return _tokens[i].get();
}
Token* CommonTokenStream::LT(ssize_t k) {
lazyInit();
if (k == 0) {
return nullptr;
}
if (k < 0) {
return LB(static_cast<size_t>(-k));
}
size_t i = _p;
ssize_t n = 1; // we know tokens[p] is a good one
// find k good tokens
while (n < k) {
// skip off-channel tokens, but make sure to not look past EOF
if (sync(i + 1)) {
i = nextTokenOnChannel(i + 1, channel);
}
n++;
}
return _tokens[i].get();
}
int CommonTokenStream::getNumberOfOnChannelTokens() {
int n = 0;
fill();
for (size_t i = 0; i < _tokens.size(); i++) {
Token *t = _tokens[i].get();
if (t->getChannel() == channel) {
n++;
}
if (t->getType() == Token::EOF) {
break;
}
}
return n;
}

@ -1,79 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "BufferedTokenStream.h"
namespace antlr4 {
/**
* This class extends {@link BufferedTokenStream} with functionality to filter
* token streams to tokens on a particular channel (tokens where
* {@link Token#getChannel} returns a particular value).
*
* <p>
* This token stream provides access to all tokens by index or when calling
* methods like {@link #getText}. The channel filtering is only used for code
* accessing tokens via the lookahead methods {@link #LA}, {@link #LT}, and
* {@link #LB}.</p>
*
* <p>
* By default, tokens are placed on the default channel
* ({@link Token#DEFAULT_CHANNEL}), but may be reassigned by using the
* {@code ->channel(HIDDEN)} lexer command, or by using an embedded action to
* call {@link Lexer#setChannel}.
* </p>
*
* <p>
* Note: lexer rules which use the {@code ->skip} lexer command or call
* {@link Lexer#skip} do not produce tokens at all, so input text matched by
* such a rule will not be available as part of the token stream, regardless of
* channel.</p>
*/
class ANTLR4CPP_PUBLIC CommonTokenStream : public BufferedTokenStream {
public:
/**
* Constructs a new {@link CommonTokenStream} using the specified token
* source and the default token channel ({@link Token#DEFAULT_CHANNEL}).
*
* @param tokenSource The token source.
*/
CommonTokenStream(TokenSource *tokenSource);
/**
* Constructs a new {@link CommonTokenStream} using the specified token
* source and filtering tokens to the specified channel. Only tokens whose
* {@link Token#getChannel} matches {@code channel} or have the
* {@link Token#getType} equal to {@link Token#EOF} will be returned by the
* token stream lookahead methods.
*
* @param tokenSource The token source.
* @param channel The channel to use for filtering tokens.
*/
CommonTokenStream(TokenSource *tokenSource, size_t channel);
virtual Token* LT(ssize_t k) override;
/// Count EOF just once.
virtual int getNumberOfOnChannelTokens();
protected:
/**
* Specifies the channel to use for filtering tokens.
*
* <p>
* The default value is {@link Token#DEFAULT_CHANNEL}, which matches the
* default channel assigned to tokens created by the lexer.</p>
*/
size_t channel;
virtual ssize_t adjustSeekIndex(size_t i) override;
virtual Token* LB(size_t k) override;
};
} // namespace antlr4

@ -1,15 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "ConsoleErrorListener.h"
using namespace antlr4;
ConsoleErrorListener ConsoleErrorListener::INSTANCE;
void ConsoleErrorListener::syntaxError(Recognizer * /*recognizer*/, Token * /*offendingSymbol*/,
size_t line, size_t charPositionInLine, const std::string &msg, std::exception_ptr /*e*/) {
std::cerr << "line " << line << ":" << charPositionInLine << " " << msg << std::endl;
}

@ -1,35 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "BaseErrorListener.h"
namespace antlr4 {
class ANTLR4CPP_PUBLIC ConsoleErrorListener : public BaseErrorListener {
public:
/**
* Provides a default instance of {@link ConsoleErrorListener}.
*/
static ConsoleErrorListener INSTANCE;
/**
* {@inheritDoc}
*
* <p>
* This implementation prints messages to {@link System#err} containing the
* values of {@code line}, {@code charPositionInLine}, and {@code msg} using
* the following format.</p>
*
* <pre>
* line <em>line</em>:<em>charPositionInLine</em> <em>msg</em>
* </pre>
*/
virtual void syntaxError(Recognizer *recognizer, Token * offendingSymbol, size_t line, size_t charPositionInLine,
const std::string &msg, std::exception_ptr e) override;
};
} // namespace antlr4

@ -1,336 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "NoViableAltException.h"
#include "misc/IntervalSet.h"
#include "atn/ParserATNSimulator.h"
#include "InputMismatchException.h"
#include "FailedPredicateException.h"
#include "ParserRuleContext.h"
#include "atn/RuleTransition.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
#include "support/StringUtils.h"
#include "support/Casts.h"
#include "Parser.h"
#include "CommonToken.h"
#include "Vocabulary.h"
#include "DefaultErrorStrategy.h"
using namespace antlr4;
using namespace antlr4::atn;
using namespace antlrcpp;
DefaultErrorStrategy::DefaultErrorStrategy() {
InitializeInstanceFields();
}
DefaultErrorStrategy::~DefaultErrorStrategy() {
}
void DefaultErrorStrategy::reset(Parser *recognizer) {
_errorSymbols.clear();
endErrorCondition(recognizer);
}
void DefaultErrorStrategy::beginErrorCondition(Parser * /*recognizer*/) {
errorRecoveryMode = true;
}
bool DefaultErrorStrategy::inErrorRecoveryMode(Parser * /*recognizer*/) {
return errorRecoveryMode;
}
void DefaultErrorStrategy::endErrorCondition(Parser * /*recognizer*/) {
errorRecoveryMode = false;
lastErrorIndex = -1;
}
void DefaultErrorStrategy::reportMatch(Parser *recognizer) {
endErrorCondition(recognizer);
}
void DefaultErrorStrategy::reportError(Parser *recognizer, const RecognitionException &e) {
// If we've already reported an error and have not matched a token
// yet successfully, don't report any errors.
if (inErrorRecoveryMode(recognizer)) {
return; // don't report spurious errors
}
beginErrorCondition(recognizer);
if (is<const NoViableAltException *>(&e)) {
reportNoViableAlternative(recognizer, static_cast<const NoViableAltException &>(e));
} else if (is<const InputMismatchException *>(&e)) {
reportInputMismatch(recognizer, static_cast<const InputMismatchException &>(e));
} else if (is<const FailedPredicateException *>(&e)) {
reportFailedPredicate(recognizer, static_cast<const FailedPredicateException &>(e));
} else if (is<const RecognitionException *>(&e)) {
recognizer->notifyErrorListeners(e.getOffendingToken(), e.what(), std::current_exception());
}
}
void DefaultErrorStrategy::recover(Parser *recognizer, std::exception_ptr /*e*/) {
if (lastErrorIndex == static_cast<int>(recognizer->getInputStream()->index()) &&
lastErrorStates.contains(recognizer->getState())) {
// uh oh, another error at same token index and previously-visited
// state in ATN; must be a case where LT(1) is in the recovery
// token set so nothing got consumed. Consume a single token
// at least to prevent an infinite loop; this is a failsafe.
recognizer->consume();
}
lastErrorIndex = static_cast<int>(recognizer->getInputStream()->index());
lastErrorStates.add(recognizer->getState());
misc::IntervalSet followSet = getErrorRecoverySet(recognizer);
consumeUntil(recognizer, followSet);
}
void DefaultErrorStrategy::sync(Parser *recognizer) {
atn::ATNState *s = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[recognizer->getState()];
// If already recovering, don't try to sync
if (inErrorRecoveryMode(recognizer)) {
return;
}
TokenStream *tokens = recognizer->getTokenStream();
size_t la = tokens->LA(1);
// try cheaper subset first; might get lucky. seems to shave a wee bit off
auto nextTokens = recognizer->getATN().nextTokens(s);
if (nextTokens.contains(Token::EPSILON) || nextTokens.contains(la)) {
return;
}
switch (s->getStateType()) {
case atn::ATNStateType::BLOCK_START:
case atn::ATNStateType::STAR_BLOCK_START:
case atn::ATNStateType::PLUS_BLOCK_START:
case atn::ATNStateType::STAR_LOOP_ENTRY:
// report error and recover if possible
if (singleTokenDeletion(recognizer) != nullptr) {
return;
}
throw InputMismatchException(recognizer);
case atn::ATNStateType::PLUS_LOOP_BACK:
case atn::ATNStateType::STAR_LOOP_BACK: {
reportUnwantedToken(recognizer);
misc::IntervalSet expecting = recognizer->getExpectedTokens();
misc::IntervalSet whatFollowsLoopIterationOrRule = expecting.Or(getErrorRecoverySet(recognizer));
consumeUntil(recognizer, whatFollowsLoopIterationOrRule);
}
break;
default:
// do nothing if we can't identify the exact kind of ATN state
break;
}
}
void DefaultErrorStrategy::reportNoViableAlternative(Parser *recognizer, const NoViableAltException &e) {
TokenStream *tokens = recognizer->getTokenStream();
std::string input;
if (tokens != nullptr) {
if (e.getStartToken()->getType() == Token::EOF) {
input = "<EOF>";
} else {
input = tokens->getText(e.getStartToken(), e.getOffendingToken());
}
} else {
input = "<unknown input>";
}
std::string msg = "no viable alternative at input " + escapeWSAndQuote(input);
recognizer->notifyErrorListeners(e.getOffendingToken(), msg, std::make_exception_ptr(e));
}
void DefaultErrorStrategy::reportInputMismatch(Parser *recognizer, const InputMismatchException &e) {
std::string msg = "mismatched input " + getTokenErrorDisplay(e.getOffendingToken()) +
" expecting " + e.getExpectedTokens().toString(recognizer->getVocabulary());
recognizer->notifyErrorListeners(e.getOffendingToken(), msg, std::make_exception_ptr(e));
}
void DefaultErrorStrategy::reportFailedPredicate(Parser *recognizer, const FailedPredicateException &e) {
const std::string& ruleName = recognizer->getRuleNames()[recognizer->getContext()->getRuleIndex()];
std::string msg = "rule " + ruleName + " " + e.what();
recognizer->notifyErrorListeners(e.getOffendingToken(), msg, std::make_exception_ptr(e));
}
void DefaultErrorStrategy::reportUnwantedToken(Parser *recognizer) {
if (inErrorRecoveryMode(recognizer)) {
return;
}
beginErrorCondition(recognizer);
Token *t = recognizer->getCurrentToken();
std::string tokenName = getTokenErrorDisplay(t);
misc::IntervalSet expecting = getExpectedTokens(recognizer);
std::string msg = "extraneous input " + tokenName + " expecting " + expecting.toString(recognizer->getVocabulary());
recognizer->notifyErrorListeners(t, msg, nullptr);
}
void DefaultErrorStrategy::reportMissingToken(Parser *recognizer) {
if (inErrorRecoveryMode(recognizer)) {
return;
}
beginErrorCondition(recognizer);
Token *t = recognizer->getCurrentToken();
misc::IntervalSet expecting = getExpectedTokens(recognizer);
std::string expectedText = expecting.toString(recognizer->getVocabulary());
std::string msg = "missing " + expectedText + " at " + getTokenErrorDisplay(t);
recognizer->notifyErrorListeners(t, msg, nullptr);
}
Token* DefaultErrorStrategy::recoverInline(Parser *recognizer) {
// Single token deletion.
Token *matchedSymbol = singleTokenDeletion(recognizer);
if (matchedSymbol) {
// We have deleted the extra token.
// Now, move past ttype token as if all were ok.
recognizer->consume();
return matchedSymbol;
}
// Single token insertion.
if (singleTokenInsertion(recognizer)) {
return getMissingSymbol(recognizer);
}
// Even that didn't work; must throw the exception.
throw InputMismatchException(recognizer);
}
bool DefaultErrorStrategy::singleTokenInsertion(Parser *recognizer) {
ssize_t currentSymbolType = recognizer->getInputStream()->LA(1);
// if current token is consistent with what could come after current
// ATN state, then we know we're missing a token; error recovery
// is free to conjure up and insert the missing token
atn::ATNState *currentState = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[recognizer->getState()];
atn::ATNState *next = currentState->transitions[0]->target;
const atn::ATN &atn = recognizer->getInterpreter<atn::ATNSimulator>()->atn;
misc::IntervalSet expectingAtLL2 = atn.nextTokens(next, recognizer->getContext());
if (expectingAtLL2.contains(currentSymbolType)) {
reportMissingToken(recognizer);
return true;
}
return false;
}
Token* DefaultErrorStrategy::singleTokenDeletion(Parser *recognizer) {
size_t nextTokenType = recognizer->getInputStream()->LA(2);
misc::IntervalSet expecting = getExpectedTokens(recognizer);
if (expecting.contains(nextTokenType)) {
reportUnwantedToken(recognizer);
recognizer->consume(); // simply delete extra token
// we want to return the token we're actually matching
Token *matchedSymbol = recognizer->getCurrentToken();
reportMatch(recognizer); // we know current token is correct
return matchedSymbol;
}
return nullptr;
}
Token* DefaultErrorStrategy::getMissingSymbol(Parser *recognizer) {
Token *currentSymbol = recognizer->getCurrentToken();
misc::IntervalSet expecting = getExpectedTokens(recognizer);
size_t expectedTokenType = expecting.getMinElement(); // get any element
std::string tokenText;
if (expectedTokenType == Token::EOF) {
tokenText = "<missing EOF>";
} else {
tokenText = "<missing " + recognizer->getVocabulary().getDisplayName(expectedTokenType) + ">";
}
Token *current = currentSymbol;
Token *lookback = recognizer->getTokenStream()->LT(-1);
if (current->getType() == Token::EOF && lookback != nullptr) {
current = lookback;
}
_errorSymbols.push_back(recognizer->getTokenFactory()->create(
{ current->getTokenSource(), current->getTokenSource()->getInputStream() },
expectedTokenType, tokenText, Token::DEFAULT_CHANNEL, INVALID_INDEX, INVALID_INDEX,
current->getLine(), current->getCharPositionInLine()));
return _errorSymbols.back().get();
}
misc::IntervalSet DefaultErrorStrategy::getExpectedTokens(Parser *recognizer) {
return recognizer->getExpectedTokens();
}
std::string DefaultErrorStrategy::getTokenErrorDisplay(Token *t) {
if (t == nullptr) {
return "<no Token>";
}
std::string s = getSymbolText(t);
if (s == "") {
if (getSymbolType(t) == Token::EOF) {
s = "<EOF>";
} else {
s = "<" + std::to_string(getSymbolType(t)) + ">";
}
}
return escapeWSAndQuote(s);
}
std::string DefaultErrorStrategy::getSymbolText(Token *symbol) {
return symbol->getText();
}
size_t DefaultErrorStrategy::getSymbolType(Token *symbol) {
return symbol->getType();
}
std::string DefaultErrorStrategy::escapeWSAndQuote(const std::string &s) const {
std::string result;
result.reserve(s.size() + 2);
result.push_back('\'');
antlrcpp::escapeWhitespace(result, s);
result.push_back('\'');
result.shrink_to_fit();
return result;
}
misc::IntervalSet DefaultErrorStrategy::getErrorRecoverySet(Parser *recognizer) {
const atn::ATN &atn = recognizer->getInterpreter<atn::ATNSimulator>()->atn;
RuleContext *ctx = recognizer->getContext();
misc::IntervalSet recoverSet;
while (ctx->invokingState != ATNState::INVALID_STATE_NUMBER) {
// compute what follows who invoked us
atn::ATNState *invokingState = atn.states[ctx->invokingState];
const atn::RuleTransition *rt = downCast<const atn::RuleTransition*>(invokingState->transitions[0].get());
misc::IntervalSet follow = atn.nextTokens(rt->followState);
recoverSet.addAll(follow);
if (ctx->parent == nullptr)
break;
ctx = static_cast<RuleContext *>(ctx->parent);
}
recoverSet.remove(Token::EPSILON);
return recoverSet;
}
void DefaultErrorStrategy::consumeUntil(Parser *recognizer, const misc::IntervalSet &set) {
size_t ttype = recognizer->getInputStream()->LA(1);
while (ttype != Token::EOF && !set.contains(ttype)) {
recognizer->consume();
ttype = recognizer->getInputStream()->LA(1);
}
}
void DefaultErrorStrategy::InitializeInstanceFields() {
errorRecoveryMode = false;
lastErrorIndex = -1;
}

@ -1,466 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "ANTLRErrorStrategy.h"
#include "misc/IntervalSet.h"
namespace antlr4 {
/**
* This is the default implementation of {@link ANTLRErrorStrategy} used for
* error reporting and recovery in ANTLR parsers.
*/
class ANTLR4CPP_PUBLIC DefaultErrorStrategy : public ANTLRErrorStrategy {
public:
DefaultErrorStrategy();
DefaultErrorStrategy(DefaultErrorStrategy const& other) = delete;
virtual ~DefaultErrorStrategy();
DefaultErrorStrategy& operator = (DefaultErrorStrategy const& other) = delete;
protected:
/**
* Indicates whether the error strategy is currently "recovering from an
* error". This is used to suppress reporting multiple error messages while
* attempting to recover from a detected syntax error.
*
* @see #inErrorRecoveryMode
*/
bool errorRecoveryMode;
/** The index into the input stream where the last error occurred.
* This is used to prevent infinite loops where an error is found
* but no token is consumed during recovery...another error is found,
* ad nauseum. This is a failsafe mechanism to guarantee that at least
* one token/tree node is consumed for two errors.
*/
int lastErrorIndex;
misc::IntervalSet lastErrorStates;
/// <summary>
/// {@inheritDoc}
/// <p/>
/// The default implementation simply calls <seealso cref="#endErrorCondition"/> to
/// ensure that the handler is not in error recovery mode.
/// </summary>
public:
virtual void reset(Parser *recognizer) override;
/// <summary>
/// This method is called to enter error recovery mode when a recognition
/// exception is reported.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
protected:
virtual void beginErrorCondition(Parser *recognizer);
/// <summary>
/// {@inheritDoc}
/// </summary>
public:
virtual bool inErrorRecoveryMode(Parser *recognizer) override;
/// <summary>
/// This method is called to leave error recovery mode after recovering from
/// a recognition exception.
/// </summary>
/// <param name="recognizer"> </param>
protected:
virtual void endErrorCondition(Parser *recognizer);
/// <summary>
/// {@inheritDoc}
/// <p/>
/// The default implementation simply calls <seealso cref="#endErrorCondition"/>.
/// </summary>
public:
virtual void reportMatch(Parser *recognizer) override;
/// {@inheritDoc}
/// <p/>
/// The default implementation returns immediately if the handler is already
/// in error recovery mode. Otherwise, it calls <seealso cref="#beginErrorCondition"/>
/// and dispatches the reporting task based on the runtime type of {@code e}
/// according to the following table.
///
/// <ul>
/// <li><seealso cref="NoViableAltException"/>: Dispatches the call to
/// <seealso cref="#reportNoViableAlternative"/></li>
/// <li><seealso cref="InputMismatchException"/>: Dispatches the call to
/// <seealso cref="#reportInputMismatch"/></li>
/// <li><seealso cref="FailedPredicateException"/>: Dispatches the call to
/// <seealso cref="#reportFailedPredicate"/></li>
/// <li>All other types: calls <seealso cref="Parser#notifyErrorListeners"/> to report
/// the exception</li>
/// </ul>
virtual void reportError(Parser *recognizer, const RecognitionException &e) override;
/// <summary>
/// {@inheritDoc}
/// <p/>
/// The default implementation resynchronizes the parser by consuming tokens
/// until we find one in the resynchronization set--loosely the set of tokens
/// that can follow the current rule.
/// </summary>
virtual void recover(Parser *recognizer, std::exception_ptr e) override;
/**
* The default implementation of {@link ANTLRErrorStrategy#sync} makes sure
* that the current lookahead symbol is consistent with what were expecting
* at this point in the ATN. You can call this anytime but ANTLR only
* generates code to check before subrules/loops and each iteration.
*
* <p>Implements Jim Idle's magic sync mechanism in closures and optional
* subrules. E.g.,</p>
*
* <pre>
* a : sync ( stuff sync )* ;
* sync : {consume to what can follow sync} ;
* </pre>
*
* At the start of a sub rule upon error, {@link #sync} performs single
* token deletion, if possible. If it can't do that, it bails on the current
* rule and uses the default error recovery, which consumes until the
* resynchronization set of the current rule.
*
* <p>If the sub rule is optional ({@code (...)?}, {@code (...)*}, or block
* with an empty alternative), then the expected set includes what follows
* the subrule.</p>
*
* <p>During loop iteration, it consumes until it sees a token that can start a
* sub rule or what follows loop. Yes, that is pretty aggressive. We opt to
* stay in the loop as long as possible.</p>
*
* <p><strong>ORIGINS</strong></p>
*
* <p>Previous versions of ANTLR did a poor job of their recovery within loops.
* A single mismatch token or missing token would force the parser to bail
* out of the entire rules surrounding the loop. So, for rule</p>
*
* <pre>
* classDef : 'class' ID '{' member* '}'
* </pre>
*
* input with an extra token between members would force the parser to
* consume until it found the next class definition rather than the next
* member definition of the current class.
*
* <p>This functionality cost a little bit of effort because the parser has to
* compare token set at the start of the loop and at each iteration. If for
* some reason speed is suffering for you, you can turn off this
* functionality by simply overriding this method as a blank { }.</p>
*/
virtual void sync(Parser *recognizer) override;
/// <summary>
/// This is called by <seealso cref="#reportError"/> when the exception is a
/// <seealso cref="NoViableAltException"/>.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception </param>
protected:
virtual void reportNoViableAlternative(Parser *recognizer, const NoViableAltException &e);
/// <summary>
/// This is called by <seealso cref="#reportError"/> when the exception is an
/// <seealso cref="InputMismatchException"/>.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception </param>
virtual void reportInputMismatch(Parser *recognizer, const InputMismatchException &e);
/// <summary>
/// This is called by <seealso cref="#reportError"/> when the exception is a
/// <seealso cref="FailedPredicateException"/>.
/// </summary>
/// <seealso cref= #reportError
/// </seealso>
/// <param name="recognizer"> the parser instance </param>
/// <param name="e"> the recognition exception </param>
virtual void reportFailedPredicate(Parser *recognizer, const FailedPredicateException &e);
/**
* This method is called to report a syntax error which requires the removal
* of a token from the input stream. At the time this method is called, the
* erroneous symbol is current {@code LT(1)} symbol and has not yet been
* removed from the input stream. When this method returns,
* {@code recognizer} is in error recovery mode.
*
* <p>This method is called when {@link #singleTokenDeletion} identifies
* single-token deletion as a viable recovery strategy for a mismatched
* input error.</p>
*
* <p>The default implementation simply returns if the handler is already in
* error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
* enter error recovery mode, followed by calling
* {@link Parser#notifyErrorListeners}.</p>
*
* @param recognizer the parser instance
*/
virtual void reportUnwantedToken(Parser *recognizer);
/**
* This method is called to report a syntax error which requires the
* insertion of a missing token into the input stream. At the time this
* method is called, the missing token has not yet been inserted. When this
* method returns, {@code recognizer} is in error recovery mode.
*
* <p>This method is called when {@link #singleTokenInsertion} identifies
* single-token insertion as a viable recovery strategy for a mismatched
* input error.</p>
*
* <p>The default implementation simply returns if the handler is already in
* error recovery mode. Otherwise, it calls {@link #beginErrorCondition} to
* enter error recovery mode, followed by calling
* {@link Parser#notifyErrorListeners}.</p>
*
* @param recognizer the parser instance
*/
virtual void reportMissingToken(Parser *recognizer);
public:
/**
* {@inheritDoc}
*
* <p>The default implementation attempts to recover from the mismatched input
* by using single token insertion and deletion as described below. If the
* recovery attempt fails, this method throws an
* {@link InputMismatchException}.</p>
*
* <p><strong>EXTRA TOKEN</strong> (single token deletion)</p>
*
* <p>{@code LA(1)} is not what we are looking for. If {@code LA(2)} has the
* right token, however, then assume {@code LA(1)} is some extra spurious
* token and delete it. Then consume and return the next token (which was
* the {@code LA(2)} token) as the successful result of the match operation.</p>
*
* <p>This recovery strategy is implemented by {@link #singleTokenDeletion}.</p>
*
* <p><strong>MISSING TOKEN</strong> (single token insertion)</p>
*
* <p>If current token (at {@code LA(1)}) is consistent with what could come
* after the expected {@code LA(1)} token, then assume the token is missing
* and use the parser's {@link TokenFactory} to create it on the fly. The
* "insertion" is performed by returning the created token as the successful
* result of the match operation.</p>
*
* <p>This recovery strategy is implemented by {@link #singleTokenInsertion}.</p>
*
* <p><strong>EXAMPLE</strong></p>
*
* <p>For example, Input {@code i=(3;} is clearly missing the {@code ')'}. When
* the parser returns from the nested call to {@code expr}, it will have
* call chain:</p>
*
* <pre>
* stat &rarr; expr &rarr; atom
* </pre>
*
* and it will be trying to match the {@code ')'} at this point in the
* derivation:
*
* <pre>
* =&gt; ID '=' '(' INT ')' ('+' atom)* ';'
* ^
* </pre>
*
* The attempt to match {@code ')'} will fail when it sees {@code ';'} and
* call {@link #recoverInline}. To recover, it sees that {@code LA(1)==';'}
* is in the set of tokens that can follow the {@code ')'} token reference
* in rule {@code atom}. It can assume that you forgot the {@code ')'}.
*/
virtual Token* recoverInline(Parser *recognizer) override;
/// <summary>
/// This method implements the single-token insertion inline error recovery
/// strategy. It is called by <seealso cref="#recoverInline"/> if the single-token
/// deletion strategy fails to recover from the mismatched input. If this
/// method returns {@code true}, {@code recognizer} will be in error recovery
/// mode.
/// <p/>
/// This method determines whether or not single-token insertion is viable by
/// checking if the {@code LA(1)} input symbol could be successfully matched
/// if it were instead the {@code LA(2)} symbol. If this method returns
/// {@code true}, the caller is responsible for creating and inserting a
/// token with the correct type to produce this behavior.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <returns> {@code true} if single-token insertion is a viable recovery
/// strategy for the current mismatched input, otherwise {@code false} </returns>
protected:
virtual bool singleTokenInsertion(Parser *recognizer);
/// <summary>
/// This method implements the single-token deletion inline error recovery
/// strategy. It is called by <seealso cref="#recoverInline"/> to attempt to recover
/// from mismatched input. If this method returns null, the parser and error
/// handler state will not have changed. If this method returns non-null,
/// {@code recognizer} will <em>not</em> be in error recovery mode since the
/// returned token was a successful match.
/// <p/>
/// If the single-token deletion is successful, this method calls
/// <seealso cref="#reportUnwantedToken"/> to report the error, followed by
/// <seealso cref="Parser#consume"/> to actually "delete" the extraneous token. Then,
/// before returning <seealso cref="#reportMatch"/> is called to signal a successful
/// match.
/// </summary>
/// <param name="recognizer"> the parser instance </param>
/// <returns> the successfully matched <seealso cref="Token"/> instance if single-token
/// deletion successfully recovers from the mismatched input, otherwise
/// {@code null} </returns>
virtual Token* singleTokenDeletion(Parser *recognizer);
/// <summary>
/// Conjure up a missing token during error recovery.
///
/// The recognizer attempts to recover from single missing
/// symbols. But, actions might refer to that missing symbol.
/// For example, x=ID {f($x);}. The action clearly assumes
/// that there has been an identifier matched previously and that
/// $x points at that token. If that token is missing, but
/// the next token in the stream is what we want we assume that
/// this token is missing and we keep going. Because we
/// have to return some token to replace the missing token,
/// we have to conjure one up. This method gives the user control
/// over the tokens returned for missing tokens. Mostly,
/// you will want to create something special for identifier
/// tokens. For literals such as '{' and ',', the default
/// action in the parser or tree parser works. It simply creates
/// a CommonToken of the appropriate type. The text will be the token.
/// If you change what tokens must be created by the lexer,
/// override this method to create the appropriate tokens.
/// </summary>
virtual Token* getMissingSymbol(Parser *recognizer);
virtual misc::IntervalSet getExpectedTokens(Parser *recognizer);
/// <summary>
/// How should a token be displayed in an error message? The default
/// is to display just the text, but during development you might
/// want to have a lot of information spit out. Override in that case
/// to use t.toString() (which, for CommonToken, dumps everything about
/// the token). This is better than forcing you to override a method in
/// your token objects because you don't have to go modify your lexer
/// so that it creates a new class.
/// </summary>
virtual std::string getTokenErrorDisplay(Token *t);
virtual std::string getSymbolText(Token *symbol);
virtual size_t getSymbolType(Token *symbol);
virtual std::string escapeWSAndQuote(const std::string &s) const;
/* Compute the error recovery set for the current rule. During
* rule invocation, the parser pushes the set of tokens that can
* follow that rule reference on the stack; this amounts to
* computing FIRST of what follows the rule reference in the
* enclosing rule. See LinearApproximator.FIRST().
* This local follow set only includes tokens
* from within the rule; i.e., the FIRST computation done by
* ANTLR stops at the end of a rule.
*
* EXAMPLE
*
* When you find a "no viable alt exception", the input is not
* consistent with any of the alternatives for rule r. The best
* thing to do is to consume tokens until you see something that
* can legally follow a call to r *or* any rule that called r.
* You don't want the exact set of viable next tokens because the
* input might just be missing a token--you might consume the
* rest of the input looking for one of the missing tokens.
*
* Consider grammar:
*
* a : '[' b ']'
* | '(' b ')'
* ;
* b : c '^' INT ;
* c : ID
* | INT
* ;
*
* At each rule invocation, the set of tokens that could follow
* that rule is pushed on a stack. Here are the various
* context-sensitive follow sets:
*
* FOLLOW(b1_in_a) = FIRST(']') = ']'
* FOLLOW(b2_in_a) = FIRST(')') = ')'
* FOLLOW(c_in_b) = FIRST('^') = '^'
*
* Upon erroneous input "[]", the call chain is
*
* a -> b -> c
*
* and, hence, the follow context stack is:
*
* depth follow set start of rule execution
* 0 <EOF> a (from main())
* 1 ']' b
* 2 '^' c
*
* Notice that ')' is not included, because b would have to have
* been called from a different context in rule a for ')' to be
* included.
*
* For error recovery, we cannot consider FOLLOW(c)
* (context-sensitive or otherwise). We need the combined set of
* all context-sensitive FOLLOW sets--the set of all tokens that
* could follow any reference in the call chain. We need to
* resync to one of those tokens. Note that FOLLOW(c)='^' and if
* we resync'd to that token, we'd consume until EOF. We need to
* sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}.
* In this case, for input "[]", LA(1) is ']' and in the set, so we would
* not consume anything. After printing an error, rule c would
* return normally. Rule b would not find the required '^' though.
* At this point, it gets a mismatched token error and throws an
* exception (since LA(1) is not in the viable following token
* set). The rule exception handler tries to recover, but finds
* the same recovery set and doesn't consume anything. Rule b
* exits normally returning to rule a. Now it finds the ']' (and
* with the successful match exits errorRecovery mode).
*
* So, you can see that the parser walks up the call chain looking
* for the token that was a member of the recovery set.
*
* Errors are not generated in errorRecovery mode.
*
* ANTLR's error recovery mechanism is based upon original ideas:
*
* "Algorithms + Data Structures = Programs" by Niklaus Wirth
*
* and
*
* "A note on error recovery in recursive descent parsers":
* http://portal.acm.org/citation.cfm?id=947902.947905
*
* Later, Josef Grosch had some good ideas:
*
* "Efficient and Comfortable Error Recovery in Recursive Descent
* Parsers":
* ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip
*
* Like Grosch I implement context-sensitive FOLLOW sets that are combined
* at run-time upon error to avoid overhead during parsing.
*/
virtual misc::IntervalSet getErrorRecoverySet(Parser *recognizer);
/// <summary>
/// Consume tokens until one matches the given token set. </summary>
virtual void consumeUntil(Parser *recognizer, const misc::IntervalSet &set);
private:
std::vector<std::unique_ptr<Token>> _errorSymbols; // Temporarily created token.
void InitializeInstanceFields();
};
} // namespace antlr4

@ -1,84 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "atn/PredictionContext.h"
#include "atn/ATNConfig.h"
#include "atn/ATNConfigSet.h"
#include "Parser.h"
#include "misc/Interval.h"
#include "dfa/DFA.h"
#include "DiagnosticErrorListener.h"
using namespace antlr4;
DiagnosticErrorListener::DiagnosticErrorListener() : DiagnosticErrorListener(true) {
}
DiagnosticErrorListener::DiagnosticErrorListener(bool exactOnly_) : exactOnly(exactOnly_) {
}
void DiagnosticErrorListener::reportAmbiguity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
bool exact, const antlrcpp::BitSet &ambigAlts, atn::ATNConfigSet *configs) {
if (exactOnly && !exact) {
return;
}
std::string decision = getDecisionDescription(recognizer, dfa);
antlrcpp::BitSet conflictingAlts = getConflictingAlts(ambigAlts, configs);
std::string text = recognizer->getTokenStream()->getText(misc::Interval(startIndex, stopIndex));
std::string message = "reportAmbiguity d=" + decision + ": ambigAlts=" + conflictingAlts.toString() +
", input='" + text + "'";
recognizer->notifyErrorListeners(message);
}
void DiagnosticErrorListener::reportAttemptingFullContext(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex,
size_t stopIndex, const antlrcpp::BitSet &/*conflictingAlts*/, atn::ATNConfigSet * /*configs*/) {
std::string decision = getDecisionDescription(recognizer, dfa);
std::string text = recognizer->getTokenStream()->getText(misc::Interval(startIndex, stopIndex));
std::string message = "reportAttemptingFullContext d=" + decision + ", input='" + text + "'";
recognizer->notifyErrorListeners(message);
}
void DiagnosticErrorListener::reportContextSensitivity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex,
size_t stopIndex, size_t /*prediction*/, atn::ATNConfigSet * /*configs*/) {
std::string decision = getDecisionDescription(recognizer, dfa);
std::string text = recognizer->getTokenStream()->getText(misc::Interval(startIndex, stopIndex));
std::string message = "reportContextSensitivity d=" + decision + ", input='" + text + "'";
recognizer->notifyErrorListeners(message);
}
std::string DiagnosticErrorListener::getDecisionDescription(Parser *recognizer, const dfa::DFA &dfa) {
size_t decision = dfa.decision;
size_t ruleIndex = (reinterpret_cast<atn::ATNState*>(dfa.atnStartState))->ruleIndex;
const std::vector<std::string>& ruleNames = recognizer->getRuleNames();
if (ruleIndex == INVALID_INDEX || ruleIndex >= ruleNames.size()) {
return std::to_string(decision);
}
std::string ruleName = ruleNames[ruleIndex];
if (ruleName == "" || ruleName.empty()) {
return std::to_string(decision);
}
return std::to_string(decision) + " (" + ruleName + ")";
}
antlrcpp::BitSet DiagnosticErrorListener::getConflictingAlts(const antlrcpp::BitSet &reportedAlts,
atn::ATNConfigSet *configs) {
if (reportedAlts.count() > 0) { // Not exactly like the original Java code, but this listener is only used
// in the TestRig (where it never provides a good alt set), so it's probably ok so.
return reportedAlts;
}
antlrcpp::BitSet result;
for (auto &config : configs->configs) {
result.set(config->alt);
}
return result;
}

@ -1,80 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "BaseErrorListener.h"
namespace antlr4 {
/// <summary>
/// This implementation of <seealso cref="ANTLRErrorListener"/> can be used to identify
/// certain potential correctness and performance problems in grammars. "Reports"
/// are made by calling <seealso cref="Parser#notifyErrorListeners"/> with the appropriate
/// message.
///
/// <ul>
/// <li><b>Ambiguities</b>: These are cases where more than one path through the
/// grammar can match the input.</li>
/// <li><b>Weak context sensitivity</b>: These are cases where full-context
/// prediction resolved an SLL conflict to a unique alternative which equaled the
/// minimum alternative of the SLL conflict.</li>
/// <li><b>Strong (forced) context sensitivity</b>: These are cases where the
/// full-context prediction resolved an SLL conflict to a unique alternative,
/// <em>and</em> the minimum alternative of the SLL conflict was found to not be
/// a truly viable alternative. Two-stage parsing cannot be used for inputs where
/// this situation occurs.</li>
/// </ul>
///
/// @author Sam Harwell
/// </summary>
class ANTLR4CPP_PUBLIC DiagnosticErrorListener : public BaseErrorListener {
/// <summary>
/// When {@code true}, only exactly known ambiguities are reported.
/// </summary>
protected:
const bool exactOnly;
/// <summary>
/// Initializes a new instance of <seealso cref="DiagnosticErrorListener"/> which only
/// reports exact ambiguities.
/// </summary>
public:
DiagnosticErrorListener();
/// <summary>
/// Initializes a new instance of <seealso cref="DiagnosticErrorListener"/>, specifying
/// whether all ambiguities or only exact ambiguities are reported.
/// </summary>
/// <param name="exactOnly"> {@code true} to report only exact ambiguities, otherwise
/// {@code false} to report all ambiguities. </param>
DiagnosticErrorListener(bool exactOnly);
virtual void reportAmbiguity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex, bool exact,
const antlrcpp::BitSet &ambigAlts, atn::ATNConfigSet *configs) override;
virtual void reportAttemptingFullContext(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
const antlrcpp::BitSet &conflictingAlts, atn::ATNConfigSet *configs) override;
virtual void reportContextSensitivity(Parser *recognizer, const dfa::DFA &dfa, size_t startIndex, size_t stopIndex,
size_t prediction, atn::ATNConfigSet *configs) override;
protected:
virtual std::string getDecisionDescription(Parser *recognizer, const dfa::DFA &dfa);
/// <summary>
/// Computes the set of conflicting or ambiguous alternatives from a
/// configuration set, if that information was not already provided by the
/// parser.
/// </summary>
/// <param name="reportedAlts"> The set of conflicting or ambiguous alternatives, as
/// reported by the parser. </param>
/// <param name="configs"> The conflicting or ambiguous configuration set. </param>
/// <returns> Returns {@code reportedAlts} if it is not {@code null}, otherwise
/// returns the set of alternatives represented in {@code configs}. </returns>
virtual antlrcpp::BitSet getConflictingAlts(const antlrcpp::BitSet &reportedAlts, atn::ATNConfigSet *configs);
};
} // namespace antlr4

@ -1,64 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "Exceptions.h"
using namespace antlr4;
RuntimeException::RuntimeException(const std::string &msg) : std::exception(), _message(msg) {
}
const char* RuntimeException::what() const noexcept {
return _message.c_str();
}
//------------------ IOException ---------------------------------------------------------------------------------------
IOException::IOException(const std::string &msg) : std::exception(), _message(msg) {
}
const char* IOException::what() const noexcept {
return _message.c_str();
}
//------------------ IllegalStateException -----------------------------------------------------------------------------
IllegalStateException::~IllegalStateException() {
}
//------------------ IllegalArgumentException --------------------------------------------------------------------------
IllegalArgumentException::~IllegalArgumentException() {
}
//------------------ NullPointerException ------------------------------------------------------------------------------
NullPointerException::~NullPointerException() {
}
//------------------ IndexOutOfBoundsException -------------------------------------------------------------------------
IndexOutOfBoundsException::~IndexOutOfBoundsException() {
}
//------------------ UnsupportedOperationException ---------------------------------------------------------------------
UnsupportedOperationException::~UnsupportedOperationException() {
}
//------------------ EmptyStackException -------------------------------------------------------------------------------
EmptyStackException::~EmptyStackException() {
}
//------------------ CancellationException -----------------------------------------------------------------------------
CancellationException::~CancellationException() {
}
//------------------ ParseCancellationException ------------------------------------------------------------------------
ParseCancellationException::~ParseCancellationException() {
}

@ -1,99 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
// An exception hierarchy modelled loosely after java.lang.* exceptions.
class ANTLR4CPP_PUBLIC RuntimeException : public std::exception {
private:
std::string _message;
public:
RuntimeException(const std::string &msg = "");
virtual const char* what() const noexcept override;
};
class ANTLR4CPP_PUBLIC IllegalStateException : public RuntimeException {
public:
IllegalStateException(const std::string &msg = "") : RuntimeException(msg) {}
IllegalStateException(IllegalStateException const&) = default;
~IllegalStateException();
IllegalStateException& operator=(IllegalStateException const&) = default;
};
class ANTLR4CPP_PUBLIC IllegalArgumentException : public RuntimeException {
public:
IllegalArgumentException(IllegalArgumentException const&) = default;
IllegalArgumentException(const std::string &msg = "") : RuntimeException(msg) {}
~IllegalArgumentException();
IllegalArgumentException& operator=(IllegalArgumentException const&) = default;
};
class ANTLR4CPP_PUBLIC NullPointerException : public RuntimeException {
public:
NullPointerException(const std::string &msg = "") : RuntimeException(msg) {}
NullPointerException(NullPointerException const&) = default;
~NullPointerException();
NullPointerException& operator=(NullPointerException const&) = default;
};
class ANTLR4CPP_PUBLIC IndexOutOfBoundsException : public RuntimeException {
public:
IndexOutOfBoundsException(const std::string &msg = "") : RuntimeException(msg) {}
IndexOutOfBoundsException(IndexOutOfBoundsException const&) = default;
~IndexOutOfBoundsException();
IndexOutOfBoundsException& operator=(IndexOutOfBoundsException const&) = default;
};
class ANTLR4CPP_PUBLIC UnsupportedOperationException : public RuntimeException {
public:
UnsupportedOperationException(const std::string &msg = "") : RuntimeException(msg) {}
UnsupportedOperationException(UnsupportedOperationException const&) = default;
~UnsupportedOperationException();
UnsupportedOperationException& operator=(UnsupportedOperationException const&) = default;
};
class ANTLR4CPP_PUBLIC EmptyStackException : public RuntimeException {
public:
EmptyStackException(const std::string &msg = "") : RuntimeException(msg) {}
EmptyStackException(EmptyStackException const&) = default;
~EmptyStackException();
EmptyStackException& operator=(EmptyStackException const&) = default;
};
// IOException is not a runtime exception (in the java hierarchy).
// Hence we have to duplicate the RuntimeException implementation.
class ANTLR4CPP_PUBLIC IOException : public std::exception {
private:
std::string _message;
public:
IOException(const std::string &msg = "");
virtual const char* what() const noexcept override;
};
class ANTLR4CPP_PUBLIC CancellationException : public IllegalStateException {
public:
CancellationException(const std::string &msg = "") : IllegalStateException(msg) {}
CancellationException(CancellationException const&) = default;
~CancellationException();
CancellationException& operator=(CancellationException const&) = default;
};
class ANTLR4CPP_PUBLIC ParseCancellationException : public CancellationException {
public:
ParseCancellationException(const std::string &msg = "") : CancellationException(msg) {}
ParseCancellationException(ParseCancellationException const&) = default;
~ParseCancellationException();
ParseCancellationException& operator=(ParseCancellationException const&) = default;
};
} // namespace antlr4

@ -1,52 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "atn/ParserATNSimulator.h"
#include "Parser.h"
#include "atn/PredicateTransition.h"
#include "atn/ATN.h"
#include "atn/ATNState.h"
#include "support/Casts.h"
#include "support/CPPUtils.h"
#include "FailedPredicateException.h"
using namespace antlr4;
using namespace antlrcpp;
FailedPredicateException::FailedPredicateException(Parser *recognizer) : FailedPredicateException(recognizer, "", "") {
}
FailedPredicateException::FailedPredicateException(Parser *recognizer, const std::string &predicate): FailedPredicateException(recognizer, predicate, "") {
}
FailedPredicateException::FailedPredicateException(Parser *recognizer, const std::string &predicate, const std::string &message)
: RecognitionException(!message.empty() ? message : "failed predicate: " + predicate + "?", recognizer,
recognizer->getInputStream(), recognizer->getContext(), recognizer->getCurrentToken()) {
atn::ATNState *s = recognizer->getInterpreter<atn::ATNSimulator>()->atn.states[recognizer->getState()];
const atn::Transition *transition = s->transitions[0].get();
if (transition->getTransitionType() == atn::TransitionType::PREDICATE) {
_ruleIndex = downCast<const atn::PredicateTransition&>(*transition).getRuleIndex();
_predicateIndex = downCast<const atn::PredicateTransition&>(*transition).getPredIndex();
} else {
_ruleIndex = 0;
_predicateIndex = 0;
}
_predicate = predicate;
}
size_t FailedPredicateException::getRuleIndex() {
return _ruleIndex;
}
size_t FailedPredicateException::getPredIndex() {
return _predicateIndex;
}
std::string FailedPredicateException::getPredicate() {
return _predicate;
}

@ -1,32 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "RecognitionException.h"
namespace antlr4 {
/// A semantic predicate failed during validation. Validation of predicates
/// occurs when normally parsing the alternative just like matching a token.
/// Disambiguating predicate evaluation occurs when we test a predicate during
/// prediction.
class ANTLR4CPP_PUBLIC FailedPredicateException : public RecognitionException {
public:
explicit FailedPredicateException(Parser *recognizer);
FailedPredicateException(Parser *recognizer, const std::string &predicate);
FailedPredicateException(Parser *recognizer, const std::string &predicate, const std::string &message);
virtual size_t getRuleIndex();
virtual size_t getPredIndex();
virtual std::string getPredicate();
private:
size_t _ruleIndex;
size_t _predicateIndex;
std::string _predicate;
};
} // namespace antlr4

@ -1,57 +0,0 @@
// Copyright 2012-2022 The ANTLR Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions
// and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
// WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include "antlr4-common.h"
#if ANTLR4CPP_USING_ABSEIL
#include "absl/container/flat_hash_map.h"
#else
#include <unordered_map>
#endif
// By default ANTLRv4 uses containers provided by the C++ standard library. In most deployments this
// is fine, however in some using custom containers may be preferred. This header allows that by
// optionally supporting some alternative implementations and allowing for more easier patching of
// other alternatives.
namespace antlr4 {
#if ANTLR4CPP_USING_ABSEIL
template <typename Key, typename Value,
typename Hash = typename absl::flat_hash_map<Key, Value>::hasher,
typename Equal = typename absl::flat_hash_map<Key, Value>::key_equal,
typename Allocator = typename absl::flat_hash_map<Key, Value>::allocator_type>
using FlatHashMap = absl::flat_hash_map<Key, Value, Hash, Equal, Allocator>;
#else
template <typename Key, typename Value,
typename Hash = std::hash<Key>,
typename Equal = std::equal_to<Key>,
typename Allocator = std::allocator<std::pair<const Key, Value>>>
using FlatHashMap = std::unordered_map<Key, Value, Hash, Equal, Allocator>;
#endif
} // namespace antlr4

@ -1,57 +0,0 @@
// Copyright 2012-2022 The ANTLR Project
//
// Redistribution and use in source and binary forms, with or without modification, are permitted
// provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions
// and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of
// conditions and the following disclaimer in the documentation and/or other materials provided
// with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to
// endorse or promote products derived from this software without specific prior written
// permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
// WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include "antlr4-common.h"
#if ANTLR4CPP_USING_ABSEIL
#include "absl/container/flat_hash_set.h"
#else
#include <unordered_set>
#endif
// By default ANTLRv4 uses containers provided by the C++ standard library. In most deployments this
// is fine, however in some using custom containers may be preferred. This header allows that by
// optionally supporting some alternative implementations and allowing for more easier patching of
// other alternatives.
namespace antlr4 {
#if ANTLR4CPP_USING_ABSEIL
template <typename Key,
typename Hash = typename absl::flat_hash_set<Key>::hasher,
typename Equal = typename absl::flat_hash_set<Key>::key_equal,
typename Allocator = typename absl::flat_hash_set<Key>::allocator_type>
using FlatHashSet = absl::flat_hash_set<Key, Hash, Equal, Allocator>;
#else
template <typename Key,
typename Hash = std::hash<Key>,
typename Equal = std::equal_to<Key>,
typename Allocator = std::allocator<Key>>
using FlatHashSet = std::unordered_set<Key, Hash, Equal, Allocator>;
#endif
} // namespace antlr4

@ -1,18 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "Parser.h"
#include "InputMismatchException.h"
using namespace antlr4;
InputMismatchException::InputMismatchException(Parser *recognizer)
: RecognitionException(recognizer, recognizer->getInputStream(), recognizer->getContext(),
recognizer->getCurrentToken()) {
}
InputMismatchException::~InputMismatchException() {
}

@ -1,24 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "RecognitionException.h"
namespace antlr4 {
/// <summary>
/// This signifies any kind of mismatched input exceptions such as
/// when the current input does not match the expected token.
/// </summary>
class ANTLR4CPP_PUBLIC InputMismatchException : public RecognitionException {
public:
InputMismatchException(Parser *recognizer);
InputMismatchException(InputMismatchException const&) = default;
~InputMismatchException();
InputMismatchException& operator=(InputMismatchException const&) = default;
};
} // namespace antlr4

@ -1,12 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#include "IntStream.h"
using namespace antlr4;
const std::string IntStream::UNKNOWN_SOURCE_NAME = "<unknown>";
IntStream::~IntStream() = default;

@ -1,218 +0,0 @@
/* Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
* Use of this file is governed by the BSD 3-clause license that
* can be found in the LICENSE.txt file in the project root.
*/
#pragma once
#include "antlr4-common.h"
namespace antlr4 {
/// <summary>
/// A simple stream of symbols whose values are represented as integers. This
/// interface provides <em>marked ranges</em> with support for a minimum level
/// of buffering necessary to implement arbitrary lookahead during prediction.
/// For more information on marked ranges, see <seealso cref="#mark"/>.
/// <p/>
/// <strong>Initializing Methods:</strong> Some methods in this interface have
/// unspecified behavior if no call to an initializing method has occurred after
/// the stream was constructed. The following is a list of initializing methods:
///
/// <ul>
/// <li><seealso cref="#LA"/></li>
/// <li><seealso cref="#consume"/></li>
/// <li><seealso cref="#size"/></li>
/// </ul>
/// </summary>
class ANTLR4CPP_PUBLIC IntStream {
public:
static constexpr size_t EOF = std::numeric_limits<size_t>::max();
/// The value returned by <seealso cref="#LA LA()"/> when the end of the stream is
/// reached.
/// No explicit EOF definition. We got EOF on all platforms.
//static const size_t _EOF = std::ios::eofbit;
/// <summary>
/// The value returned by <seealso cref="#getSourceName"/> when the actual name of the
/// underlying source is not known.
/// </summary>
static const std::string UNKNOWN_SOURCE_NAME;
virtual ~IntStream();
/// <summary>
/// Consumes the current symbol in the stream. This method has the following
/// effects:
///
/// <ul>
/// <li><strong>Forward movement:</strong> The value of <seealso cref="#index index()"/>
/// before calling this method is less than the value of {@code index()}
/// after calling this method.</li>
/// <li><strong>Ordered lookahead:</strong> The value of {@code LA(1)} before
/// calling this method becomes the value of {@code LA(-1)} after calling
/// this method.</li>
/// </ul>
///
/// Note that calling this method does not guarantee that {@code index()} is
/// incremented by exactly 1, as that would preclude the ability to implement
/// filtering streams (e.g. <seealso cref="CommonTokenStream"/> which distinguishes
/// between "on-channel" and "off-channel" tokens).
/// </summary>
/// <exception cref="IllegalStateException"> if an attempt is made to consume the the
/// end of the stream (i.e. if {@code LA(1)==}<seealso cref="#EOF EOF"/> before calling
/// {@code consume}). </exception>
virtual void consume() = 0;
/// <summary>
/// Gets the value of the symbol at offset {@code i} from the current
/// position. When {@code i==1}, this method returns the value of the current
/// symbol in the stream (which is the next symbol to be consumed). When
/// {@code i==-1}, this method returns the value of the previously read
/// symbol in the stream. It is not valid to call this method with
/// {@code i==0}, but the specific behavior is unspecified because this
/// method is frequently called from performance-critical code.
/// <p/>
/// This method is guaranteed to succeed if any of the following are true:
///
/// <ul>
/// <li>{@code i>0}</li>
/// <li>{@code i==-1} and <seealso cref="#index index()"/> returns a value greater
/// than the value of {@code index()} after the stream was constructed
/// and {@code LA(1)} was called in that order. Specifying the current
/// {@code index()} relative to the index after the stream was created
/// allows for filtering implementations that do not return every symbol
/// from the underlying source. Specifying the call to {@code LA(1)}
/// allows for lazily initialized streams.</li>
/// <li>{@code LA(i)} refers to a symbol consumed within a marked region
/// that has not yet been released.</li>
/// </ul>
///
/// If {@code i} represents a position at or beyond the end of the stream,
/// this method returns <seealso cref="#EOF"/>.
/// <p/>
/// The return value is unspecified if {@code i<0} and fewer than {@code -i}
/// calls to <seealso cref="#consume consume()"/> have occurred from the beginning of
/// the stream before calling this method.
/// </summary>
/// <exception cref="UnsupportedOperationException"> if the stream does not support
/// retrieving the value of the specified symbol </exception>
virtual size_t LA(ssize_t i) = 0;
/// <summary>
/// A mark provides a guarantee that <seealso cref="#seek seek()"/> operations will be
/// valid over a "marked range" extending from the index where {@code mark()}
/// was called to the current <seealso cref="#index index()"/>. This allows the use of
/// streaming input sources by specifying the minimum buffering requirements
/// to support arbitrary lookahead during prediction.
/// <p/>
/// The returned mark is an opaque handle (type {@code int}) which is passed
/// to <seealso cref="#release release()"/> when the guarantees provided by the marked
/// range are no longer necessary. When calls to
/// {@code mark()}/{@code release()} are nested, the marks must be released
/// in reverse order of which they were obtained. Since marked regions are
/// used during performance-critical sections of prediction, the specific
/// behavior of invalid usage is unspecified (i.e. a mark is not released, or
/// a mark is released twice, or marks are not released in reverse order from
/// which they were created).
/// <p/>
/// The behavior of this method is unspecified if no call to an
/// <seealso cref="IntStream initializing method"/> has occurred after this stream was
/// constructed.
/// <p/>
/// This method does not change the current position in the input stream.
/// <p/>
/// The following example shows the use of <seealso cref="#mark mark()"/>,
/// <seealso cref="#release release(mark)"/>, <seealso cref="#index index()"/>, and
/// <seealso cref="#seek seek(index)"/> as part of an operation to safely work within a
/// marked region, then restore the stream position to its original value and
/// release the mark.
/// <pre>
/// IntStream stream = ...;
/// int index = -1;
/// int mark = stream.mark();
/// try {
/// index = stream.index();
/// // perform work here...
/// } finally {
/// if (index != -1) {
/// stream.seek(index);
/// }
/// stream.release(mark);
/// }
/// </pre>
/// </summary>
/// <returns> An opaque marker which should be passed to
/// <seealso cref="#release release()"/> when the marked range is no longer required. </returns>
virtual ssize_t mark() = 0;
/// <summary>
/// This method releases a marked range created by a call to
/// <seealso cref="#mark mark()"/>. Calls to {@code release()} must appear in the
/// reverse order of the corresponding calls to {@code mark()}. If a mark is
/// released twice, or if marks are not released in reverse order of the
/// corresponding calls to {@code mark()}, the behavior is unspecified.
/// <p/>
/// For more information and an example, see <seealso cref="#mark"/>.
/// </summary>
/// <param name="marker"> A marker returned by a call to {@code mark()}. </param>
/// <seealso cref= #mark </seealso>
virtual void release(ssize_t marker) = 0;
/// <summary>
/// Return the index into the stream of the input symbol referred to by
/// {@code LA(1)}.
/// <p/>
/// The behavior of this method is unspecified if no call to an
/// <seealso cref="IntStream initializing method"/> has occurred after this stream was
/// constructed.
/// </summary>
virtual size_t index() = 0;
/// <summary>
/// Set the input cursor to the position indicated by {@code index}. If the
/// specified index lies past the end of the stream, the operation behaves as
/// though {@code index} was the index of the EOF symbol. After this method
/// returns without throwing an exception, the at least one of the following
/// will be true.
///
/// <ul>
/// <li><seealso cref="#index index()"/> will return the index of the first symbol
/// appearing at or after the specified {@code index}. Specifically,
/// implementations which filter their sources should automatically
/// adjust {@code index} forward the minimum amount required for the
/// operation to target a non-ignored symbol.</li>
/// <li>{@code LA(1)} returns <seealso cref="#EOF"/></li>
/// </ul>
///
/// This operation is guaranteed to not throw an exception if {@code index}
/// lies within a marked region. For more information on marked regions, see
/// <seealso cref="#mark"/>. The behavior of this method is unspecified if no call to
/// an <seealso cref="IntStream initializing method"/> has occurred after this stream
/// was constructed.
/// </summary>
/// <param name="index"> The absolute index to seek to.
/// </param>
/// <exception cref="IllegalArgumentException"> if {@code index} is less than 0 </exception>
/// <exception cref="UnsupportedOperationException"> if the stream does not support
/// seeking to the specified index </exception>
virtual void seek(size_t index) = 0;
/// <summary>
/// Returns the total number of symbols in the stream, including a single EOF
/// symbol.
/// </summary>
/// <exception cref="UnsupportedOperationException"> if the size of the stream is
/// unknown. </exception>
virtual size_t size() = 0;
/// <summary>
/// Gets the name of the underlying symbol source. This method returns a
/// non-null, non-empty string. If such a name is not known, this method
/// returns <seealso cref="#UNKNOWN_SOURCE_NAME"/>.
/// </summary>
virtual std::string getSourceName() const = 0;
};
} // namespace antlr4

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save