Compare commits
7 Commits
master
...
zwz-compil
| Author | SHA1 | Date |
|---|---|---|
|
|
12c217e5f9 | 6 days ago |
|
|
b1c34228b1 | 1 week ago |
|
|
29d1315410 | 2 weeks ago |
|
|
e4fed12b92 | 2 weeks ago |
|
|
472f059af7 | 2 weeks ago |
|
|
96dda8642a | 2 weeks ago |
|
|
f83b83c664 | 2 weeks ago |
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
|
||||
namespace ir {
|
||||
|
||||
template <typename IterT> struct range {
|
||||
using iterator = IterT;
|
||||
using value_type = typename std::iterator_traits<iterator>::value_type;
|
||||
using reference = typename std::iterator_traits<iterator>::reference;
|
||||
|
||||
private:
|
||||
iterator b;
|
||||
iterator e;
|
||||
|
||||
public:
|
||||
explicit range(iterator b, iterator e) : b(b), e(e) {}
|
||||
iterator begin() { return b; }
|
||||
iterator end() { return e; }
|
||||
iterator begin() const { return b; }
|
||||
iterator end() const { return e; }
|
||||
auto size() const { return std::distance(b, e); }
|
||||
auto empty() const { return b == e; }
|
||||
};
|
||||
|
||||
//! create `range` object from iterator pair [begin, end)
|
||||
template <typename IterT> range<IterT> make_range(IterT b, IterT e) {
|
||||
return range<IterT>(b, e);
|
||||
}
|
||||
//! create `range` object from a container who has `begin()` and `end()` methods
|
||||
template <typename ContainerT>
|
||||
range<typename ContainerT::iterator> make_range(ContainerT &c) {
|
||||
return make_range(c.begin(), c.end());
|
||||
}
|
||||
//! create `range` object from a container who has `begin()` and `end()` methods
|
||||
template <typename ContainerT>
|
||||
range<typename ContainerT::const_iterator> make_range(const ContainerT &c) {
|
||||
return make_range(c.begin(), c.end());
|
||||
}
|
||||
|
||||
} // namespace ir
|
||||
@ -0,0 +1,80 @@
|
||||
// 编译期常量求值与常量初始化展开。
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "SysYParser.h"
|
||||
#include "sem/SymbolTable.h"
|
||||
|
||||
struct ConstValue {
|
||||
SymbolDataType type = SymbolDataType::Unknown;
|
||||
int64_t int_value = 0;
|
||||
double float_value = 0.0;
|
||||
bool bool_value = false;
|
||||
|
||||
static ConstValue FromInt(int64_t value);
|
||||
static ConstValue FromFloat(double value);
|
||||
static ConstValue FromBool(bool value);
|
||||
|
||||
bool IsScalar() const;
|
||||
bool IsNumeric() const;
|
||||
int64_t AsInt() const;
|
||||
double AsFloat() const;
|
||||
bool AsBool() const;
|
||||
};
|
||||
|
||||
struct ConstArrayValue {
|
||||
SymbolDataType elem_type = SymbolDataType::Unknown;
|
||||
std::vector<int64_t> dims;
|
||||
std::vector<ConstValue> elements;
|
||||
};
|
||||
|
||||
class ConstEvalContext {
|
||||
public:
|
||||
ConstEvalContext();
|
||||
|
||||
void EnterScope();
|
||||
void ExitScope();
|
||||
|
||||
bool DefineScalar(const std::string& name, ConstValue value);
|
||||
bool DefineArray(const std::string& name, ConstArrayValue value);
|
||||
|
||||
const ConstValue* LookupScalar(const std::string& name) const;
|
||||
const ConstArrayValue* LookupArray(const std::string& name) const;
|
||||
|
||||
private:
|
||||
struct Binding {
|
||||
bool is_array = false;
|
||||
ConstValue scalar;
|
||||
ConstArrayValue array;
|
||||
};
|
||||
|
||||
using Scope = std::unordered_map<std::string, Binding>;
|
||||
|
||||
const Binding* LookupBinding(const std::string& name) const;
|
||||
|
||||
std::vector<Scope> scopes_;
|
||||
};
|
||||
|
||||
class ConstEvaluator {
|
||||
public:
|
||||
ConstEvaluator(const SymbolTable& table, const ConstEvalContext& ctx);
|
||||
|
||||
ConstValue EvaluateConstExp(SysYParser::ConstExpContext& ctx) const;
|
||||
ConstValue EvaluateExp(SysYParser::ExpContext& ctx) const;
|
||||
|
||||
// 数组维度必须是正整数。
|
||||
int64_t EvaluateArrayDim(SysYParser::ConstExpContext& ctx) const;
|
||||
|
||||
// 展平 const 初始化列表,结果按行优先顺序存放。
|
||||
std::vector<ConstValue> EvaluateConstInitList(
|
||||
SysYParser::ConstInitValContext& init, SymbolDataType elem_type,
|
||||
const std::vector<int64_t>& dims) const;
|
||||
|
||||
private:
|
||||
const SymbolTable& table_;
|
||||
const ConstEvalContext& ctx_;
|
||||
};
|
||||
@ -1,30 +1,48 @@
|
||||
// 基于语法树的语义检查与名称绑定。
|
||||
#pragma once
|
||||
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "SysYParser.h"
|
||||
#include "sem/SymbolTable.h"
|
||||
|
||||
class SemanticContext {
|
||||
public:
|
||||
void BindVarUse(SysYParser::VarContext* use,
|
||||
SysYParser::VarDefContext* decl) {
|
||||
var_uses_[use] = decl;
|
||||
SymbolEntry* RegisterSymbol(SymbolEntry symbol) {
|
||||
symbols_.push_back(std::move(symbol));
|
||||
return &symbols_.back();
|
||||
}
|
||||
|
||||
SysYParser::VarDefContext* ResolveVarUse(
|
||||
const SysYParser::VarContext* use) const {
|
||||
auto it = var_uses_.find(use);
|
||||
return it == var_uses_.end() ? nullptr : it->second;
|
||||
void BindLValUse(SysYParser::LValContext* use, const SymbolEntry* symbol) {
|
||||
lval_uses_[use] = symbol;
|
||||
}
|
||||
|
||||
const SymbolEntry* ResolveLValUse(const SysYParser::LValContext* use) const {
|
||||
auto it = lval_uses_.find(use);
|
||||
return it == lval_uses_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
void BindCallUse(SysYParser::UnaryExpContext* call,
|
||||
const SymbolEntry* symbol) {
|
||||
call_uses_[call] = symbol;
|
||||
}
|
||||
|
||||
const SymbolEntry* ResolveCallUse(
|
||||
const SysYParser::UnaryExpContext* call) const {
|
||||
auto it = call_uses_.find(call);
|
||||
return it == call_uses_.end() ? nullptr : it->second;
|
||||
}
|
||||
|
||||
const std::list<SymbolEntry>& GetSymbols() const { return symbols_; }
|
||||
|
||||
private:
|
||||
std::unordered_map<const SysYParser::VarContext*,
|
||||
SysYParser::VarDefContext*>
|
||||
var_uses_;
|
||||
std::list<SymbolEntry> symbols_;
|
||||
std::unordered_map<const SysYParser::LValContext*, const SymbolEntry*>
|
||||
lval_uses_;
|
||||
std::unordered_map<const SysYParser::UnaryExpContext*, const SymbolEntry*>
|
||||
call_uses_;
|
||||
};
|
||||
|
||||
// 目前仅检查:
|
||||
// - 变量先声明后使用
|
||||
// - 局部变量不允许重复定义
|
||||
// 基于 SysY.g4 规则进行语义分析,构建 IR 导向的符号绑定结果。
|
||||
SemanticContext RunSema(SysYParser::CompUnitContext& comp_unit);
|
||||
|
||||
@ -1,17 +1,76 @@
|
||||
// 极简符号表:记录局部变量定义点。
|
||||
// IR 导向符号表:符号条目可直接挂接 IR 实体。
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "SysYParser.h"
|
||||
namespace antlr4 {
|
||||
class ParserRuleContext;
|
||||
} // namespace antlr4
|
||||
|
||||
namespace ir {
|
||||
class Type;
|
||||
class Value;
|
||||
class Function;
|
||||
} // namespace ir
|
||||
|
||||
enum class SymbolKind {
|
||||
Variable,
|
||||
Constant,
|
||||
Function,
|
||||
Parameter,
|
||||
};
|
||||
|
||||
enum class SymbolDataType {
|
||||
Unknown,
|
||||
Void,
|
||||
Int,
|
||||
Float,
|
||||
Bool,
|
||||
};
|
||||
|
||||
struct SymbolEntry {
|
||||
std::string name;
|
||||
SymbolKind kind = SymbolKind::Variable;
|
||||
SymbolDataType data_type = SymbolDataType::Unknown;
|
||||
std::shared_ptr<ir::Type> type;
|
||||
ir::Value* ir_value = nullptr;
|
||||
ir::Function* ir_function = nullptr;
|
||||
bool is_const = false;
|
||||
bool is_global = false;
|
||||
bool has_initializer = false;
|
||||
bool is_array = false;
|
||||
std::vector<int64_t> array_dims;
|
||||
bool has_constexpr_value = false;
|
||||
int64_t const_int_value = 0;
|
||||
double const_float_value = 0.0;
|
||||
std::vector<int64_t> const_int_init;
|
||||
std::vector<double> const_float_init;
|
||||
std::vector<SymbolDataType> param_types;
|
||||
std::vector<bool> param_is_array;
|
||||
const antlr4::ParserRuleContext* decl_ctx = nullptr;
|
||||
};
|
||||
|
||||
class SymbolTable {
|
||||
public:
|
||||
void Add(const std::string& name, SysYParser::VarDefContext* decl);
|
||||
SymbolTable();
|
||||
|
||||
void EnterScope();
|
||||
void ExitScope();
|
||||
|
||||
bool Insert(const SymbolEntry* symbol);
|
||||
|
||||
bool Contains(const std::string& name) const;
|
||||
SysYParser::VarDefContext* Lookup(const std::string& name) const;
|
||||
bool ContainsCurrentScope(const std::string& name) const;
|
||||
|
||||
const SymbolEntry* Lookup(const std::string& name) const;
|
||||
const SymbolEntry* LookupCurrentScope(const std::string& name) const;
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, SysYParser::VarDefContext*> table_;
|
||||
using Scope = std::unordered_map<std::string, const SymbolEntry*>;
|
||||
|
||||
std::vector<Scope> scopes_;
|
||||
};
|
||||
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1 @@
|
||||
./scripts/lab1_build_test.sh: line 111: /home/zhangwanzheng/nudt-compiler-cpp/build/bin/compiler: No such file or directory
|
||||
@ -0,0 +1,591 @@
|
||||
// Generated from /root/sysy2026/nudt-compiler-cpp/src/antlr4/SysY.g4 by ANTLR 4.13.1
|
||||
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.tree.ErrorNode;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/**
|
||||
* This class provides an empty implementation of {@link SysYListener},
|
||||
* which can be extended to create a listener which only needs to handle a subset
|
||||
* of the available methods.
|
||||
*/
|
||||
@SuppressWarnings("CheckReturnValue")
|
||||
public class SysYBaseListener implements SysYListener {
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterCompUnit(SysYParser.CompUnitContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitCompUnit(SysYParser.CompUnitContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterDecl(SysYParser.DeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitDecl(SysYParser.DeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterConstDecl(SysYParser.ConstDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitConstDecl(SysYParser.ConstDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBType(SysYParser.BTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBType(SysYParser.BTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterConstDef(SysYParser.ConstDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitConstDef(SysYParser.ConstDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterConstInitVal(SysYParser.ConstInitValContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitConstInitVal(SysYParser.ConstInitValContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterVarDecl(SysYParser.VarDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitVarDecl(SysYParser.VarDeclContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterVarDef(SysYParser.VarDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitVarDef(SysYParser.VarDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterInitVal(SysYParser.InitValContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitInitVal(SysYParser.InitValContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterFuncDef(SysYParser.FuncDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitFuncDef(SysYParser.FuncDefContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterFuncType(SysYParser.FuncTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitFuncType(SysYParser.FuncTypeContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterFuncFParams(SysYParser.FuncFParamsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitFuncFParams(SysYParser.FuncFParamsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterFuncFParam(SysYParser.FuncFParamContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitFuncFParam(SysYParser.FuncFParamContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBlock(SysYParser.BlockContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBlock(SysYParser.BlockContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBlockItem(SysYParser.BlockItemContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBlockItem(SysYParser.BlockItemContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAssignStmt(SysYParser.AssignStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAssignStmt(SysYParser.AssignStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExpStmt(SysYParser.ExpStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExpStmt(SysYParser.ExpStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBlockStmt(SysYParser.BlockStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBlockStmt(SysYParser.BlockStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterIfStmt(SysYParser.IfStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitIfStmt(SysYParser.IfStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterWhileStmt(SysYParser.WhileStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitWhileStmt(SysYParser.WhileStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBreakStmt(SysYParser.BreakStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBreakStmt(SysYParser.BreakStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterContinueStmt(SysYParser.ContinueStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitContinueStmt(SysYParser.ContinueStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterReturnStmt(SysYParser.ReturnStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitReturnStmt(SysYParser.ReturnStmtContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterExp(SysYParser.ExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitExp(SysYParser.ExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterCond(SysYParser.CondContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitCond(SysYParser.CondContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterLVal(SysYParser.LValContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitLVal(SysYParser.LValContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterPrimaryExp(SysYParser.PrimaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitPrimaryExp(SysYParser.PrimaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterNumber(SysYParser.NumberContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitNumber(SysYParser.NumberContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterPrimaryUnaryExp(SysYParser.PrimaryUnaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitPrimaryUnaryExp(SysYParser.PrimaryUnaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterCallUnaryExp(SysYParser.CallUnaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitCallUnaryExp(SysYParser.CallUnaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterOpUnaryExp(SysYParser.OpUnaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitOpUnaryExp(SysYParser.OpUnaryExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterUnaryOp(SysYParser.UnaryOpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitUnaryOp(SysYParser.UnaryOpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterFuncRParams(SysYParser.FuncRParamsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitFuncRParams(SysYParser.FuncRParamsContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBinaryMulExp(SysYParser.BinaryMulExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBinaryMulExp(SysYParser.BinaryMulExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterUnaryMulExp(SysYParser.UnaryMulExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitUnaryMulExp(SysYParser.UnaryMulExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBinaryAddExp(SysYParser.BinaryAddExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBinaryAddExp(SysYParser.BinaryAddExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterMulAddExp(SysYParser.MulAddExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitMulAddExp(SysYParser.MulAddExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAddRelExp(SysYParser.AddRelExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAddRelExp(SysYParser.AddRelExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBinaryRelExp(SysYParser.BinaryRelExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBinaryRelExp(SysYParser.BinaryRelExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBinaryEqExp(SysYParser.BinaryEqExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBinaryEqExp(SysYParser.BinaryEqExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterRelEqExp(SysYParser.RelEqExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitRelEqExp(SysYParser.RelEqExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterEqLAndExp(SysYParser.EqLAndExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitEqLAndExp(SysYParser.EqLAndExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBinaryLAndExp(SysYParser.BinaryLAndExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBinaryLAndExp(SysYParser.BinaryLAndExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterAndLOrExp(SysYParser.AndLOrExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitAndLOrExp(SysYParser.AndLOrExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterBinaryLOrExp(SysYParser.BinaryLOrExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitBinaryLOrExp(SysYParser.BinaryLOrExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterConstExp(SysYParser.ConstExpContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitConstExp(SysYParser.ConstExpContext ctx) { }
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void enterEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void exitEveryRule(ParserRuleContext ctx) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitTerminal(TerminalNode node) { }
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <p>The default implementation does nothing.</p>
|
||||
*/
|
||||
@Override public void visitErrorNode(ErrorNode node) { }
|
||||
}
|
||||
@ -0,0 +1,358 @@
|
||||
// Generated from /root/sysy2026/nudt-compiler-cpp/src/antlr4/SysY.g4 by ANTLR 4.13.1
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
import org.antlr.v4.runtime.TokenStream;
|
||||
import org.antlr.v4.runtime.*;
|
||||
import org.antlr.v4.runtime.atn.*;
|
||||
import org.antlr.v4.runtime.dfa.DFA;
|
||||
import org.antlr.v4.runtime.misc.*;
|
||||
|
||||
@SuppressWarnings({"all", "warnings", "unchecked", "unused", "cast", "CheckReturnValue", "this-escape"})
|
||||
public class SysYLexer extends Lexer {
|
||||
static { RuntimeMetaData.checkVersion("4.13.1", RuntimeMetaData.VERSION); }
|
||||
|
||||
protected static final DFA[] _decisionToDFA;
|
||||
protected static final PredictionContextCache _sharedContextCache =
|
||||
new PredictionContextCache();
|
||||
public static final int
|
||||
CONST=1, INT=2, FLOAT=3, VOID=4, IF=5, ELSE=6, WHILE=7, BREAK=8, CONTINUE=9,
|
||||
RETURN=10, ADD=11, SUB=12, MUL=13, DIV=14, MOD=15, ASSIGN=16, EQ=17, NE=18,
|
||||
LT=19, LE=20, GT=21, GE=22, NOT=23, AND=24, OR=25, LPAREN=26, RPAREN=27,
|
||||
LBRACK=28, RBRACK=29, LBRACE=30, RBRACE=31, COMMA=32, SEMI=33, Ident=34,
|
||||
IntConst=35, FloatConst=36, WS=37, LINE_COMMENT=38, BLOCK_COMMENT=39;
|
||||
public static String[] channelNames = {
|
||||
"DEFAULT_TOKEN_CHANNEL", "HIDDEN"
|
||||
};
|
||||
|
||||
public static String[] modeNames = {
|
||||
"DEFAULT_MODE"
|
||||
};
|
||||
|
||||
private static String[] makeRuleNames() {
|
||||
return new String[] {
|
||||
"CONST", "INT", "FLOAT", "VOID", "IF", "ELSE", "WHILE", "BREAK", "CONTINUE",
|
||||
"RETURN", "ADD", "SUB", "MUL", "DIV", "MOD", "ASSIGN", "EQ", "NE", "LT",
|
||||
"LE", "GT", "GE", "NOT", "AND", "OR", "LPAREN", "RPAREN", "LBRACK", "RBRACK",
|
||||
"LBRACE", "RBRACE", "COMMA", "SEMI", "Ident", "Digit", "NonzeroDigit",
|
||||
"OctDigit", "HexDigit", "DecInteger", "OctInteger", "HexInteger", "DecFraction",
|
||||
"DecExponent", "DecFloat", "HexFraction", "BinExponent", "HexFloat",
|
||||
"IntConst", "FloatConst", "WS", "LINE_COMMENT", "BLOCK_COMMENT"
|
||||
};
|
||||
}
|
||||
public static final String[] ruleNames = makeRuleNames();
|
||||
|
||||
private static String[] makeLiteralNames() {
|
||||
return new String[] {
|
||||
null, "'const'", "'int'", "'float'", "'void'", "'if'", "'else'", "'while'",
|
||||
"'break'", "'continue'", "'return'", "'+'", "'-'", "'*'", "'/'", "'%'",
|
||||
"'='", "'=='", "'!='", "'<'", "'<='", "'>'", "'>='", "'!'", "'&&'", "'||'",
|
||||
"'('", "')'", "'['", "']'", "'{'", "'}'", "','", "';'"
|
||||
};
|
||||
}
|
||||
private static final String[] _LITERAL_NAMES = makeLiteralNames();
|
||||
private static String[] makeSymbolicNames() {
|
||||
return new String[] {
|
||||
null, "CONST", "INT", "FLOAT", "VOID", "IF", "ELSE", "WHILE", "BREAK",
|
||||
"CONTINUE", "RETURN", "ADD", "SUB", "MUL", "DIV", "MOD", "ASSIGN", "EQ",
|
||||
"NE", "LT", "LE", "GT", "GE", "NOT", "AND", "OR", "LPAREN", "RPAREN",
|
||||
"LBRACK", "RBRACK", "LBRACE", "RBRACE", "COMMA", "SEMI", "Ident", "IntConst",
|
||||
"FloatConst", "WS", "LINE_COMMENT", "BLOCK_COMMENT"
|
||||
};
|
||||
}
|
||||
private static final String[] _SYMBOLIC_NAMES = makeSymbolicNames();
|
||||
public static final Vocabulary VOCABULARY = new VocabularyImpl(_LITERAL_NAMES, _SYMBOLIC_NAMES);
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #VOCABULARY} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String[] tokenNames;
|
||||
static {
|
||||
tokenNames = new String[_SYMBOLIC_NAMES.length];
|
||||
for (int i = 0; i < tokenNames.length; i++) {
|
||||
tokenNames[i] = VOCABULARY.getLiteralName(i);
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = VOCABULARY.getSymbolicName(i);
|
||||
}
|
||||
|
||||
if (tokenNames[i] == null) {
|
||||
tokenNames[i] = "<INVALID>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Deprecated
|
||||
public String[] getTokenNames() {
|
||||
return tokenNames;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
public Vocabulary getVocabulary() {
|
||||
return VOCABULARY;
|
||||
}
|
||||
|
||||
|
||||
public SysYLexer(CharStream input) {
|
||||
super(input);
|
||||
_interp = new LexerATNSimulator(this,_ATN,_decisionToDFA,_sharedContextCache);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getGrammarFileName() { return "SysY.g4"; }
|
||||
|
||||
@Override
|
||||
public String[] getRuleNames() { return ruleNames; }
|
||||
|
||||
@Override
|
||||
public String getSerializedATN() { return _serializedATN; }
|
||||
|
||||
@Override
|
||||
public String[] getChannelNames() { return channelNames; }
|
||||
|
||||
@Override
|
||||
public String[] getModeNames() { return modeNames; }
|
||||
|
||||
@Override
|
||||
public ATN getATN() { return _ATN; }
|
||||
|
||||
public static final String _serializedATN =
|
||||
"\u0004\u0000\'\u0171\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001"+
|
||||
"\u0007\u0001\u0002\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004"+
|
||||
"\u0007\u0004\u0002\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007"+
|
||||
"\u0007\u0007\u0002\b\u0007\b\u0002\t\u0007\t\u0002\n\u0007\n\u0002\u000b"+
|
||||
"\u0007\u000b\u0002\f\u0007\f\u0002\r\u0007\r\u0002\u000e\u0007\u000e\u0002"+
|
||||
"\u000f\u0007\u000f\u0002\u0010\u0007\u0010\u0002\u0011\u0007\u0011\u0002"+
|
||||
"\u0012\u0007\u0012\u0002\u0013\u0007\u0013\u0002\u0014\u0007\u0014\u0002"+
|
||||
"\u0015\u0007\u0015\u0002\u0016\u0007\u0016\u0002\u0017\u0007\u0017\u0002"+
|
||||
"\u0018\u0007\u0018\u0002\u0019\u0007\u0019\u0002\u001a\u0007\u001a\u0002"+
|
||||
"\u001b\u0007\u001b\u0002\u001c\u0007\u001c\u0002\u001d\u0007\u001d\u0002"+
|
||||
"\u001e\u0007\u001e\u0002\u001f\u0007\u001f\u0002 \u0007 \u0002!\u0007"+
|
||||
"!\u0002\"\u0007\"\u0002#\u0007#\u0002$\u0007$\u0002%\u0007%\u0002&\u0007"+
|
||||
"&\u0002\'\u0007\'\u0002(\u0007(\u0002)\u0007)\u0002*\u0007*\u0002+\u0007"+
|
||||
"+\u0002,\u0007,\u0002-\u0007-\u0002.\u0007.\u0002/\u0007/\u00020\u0007"+
|
||||
"0\u00021\u00071\u00022\u00072\u00023\u00073\u0001\u0000\u0001\u0000\u0001"+
|
||||
"\u0000\u0001\u0000\u0001\u0000\u0001\u0000\u0001\u0001\u0001\u0001\u0001"+
|
||||
"\u0001\u0001\u0001\u0001\u0002\u0001\u0002\u0001\u0002\u0001\u0002\u0001"+
|
||||
"\u0002\u0001\u0002\u0001\u0003\u0001\u0003\u0001\u0003\u0001\u0003\u0001"+
|
||||
"\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001"+
|
||||
"\u0005\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006\u0001\u0006\u0001"+
|
||||
"\u0006\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001"+
|
||||
"\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0001\b\u0001\b"+
|
||||
"\u0001\b\u0001\b\u0001\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001"+
|
||||
"\t\u0001\t\u0001\t\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\f\u0001"+
|
||||
"\f\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001"+
|
||||
"\u0010\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0001"+
|
||||
"\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001"+
|
||||
"\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0001"+
|
||||
"\u0017\u0001\u0017\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+
|
||||
"\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0001"+
|
||||
"\u001c\u0001\u001c\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001"+
|
||||
"\u001f\u0001\u001f\u0001 \u0001 \u0001!\u0001!\u0005!\u00d9\b!\n!\f!\u00dc"+
|
||||
"\t!\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0001$\u0001%\u0001%\u0001&\u0001"+
|
||||
"&\u0005&\u00e8\b&\n&\f&\u00eb\t&\u0001\'\u0001\'\u0005\'\u00ef\b\'\n\'"+
|
||||
"\f\'\u00f2\t\'\u0001(\u0001(\u0001(\u0004(\u00f7\b(\u000b(\f(\u00f8\u0001"+
|
||||
")\u0004)\u00fc\b)\u000b)\f)\u00fd\u0001)\u0001)\u0005)\u0102\b)\n)\f)"+
|
||||
"\u0105\t)\u0001)\u0001)\u0004)\u0109\b)\u000b)\f)\u010a\u0003)\u010d\b"+
|
||||
")\u0001*\u0001*\u0003*\u0111\b*\u0001*\u0004*\u0114\b*\u000b*\f*\u0115"+
|
||||
"\u0001+\u0001+\u0003+\u011a\b+\u0001+\u0001+\u0001+\u0003+\u011f\b+\u0001"+
|
||||
",\u0005,\u0122\b,\n,\f,\u0125\t,\u0001,\u0001,\u0004,\u0129\b,\u000b,"+
|
||||
"\f,\u012a\u0001,\u0004,\u012e\b,\u000b,\f,\u012f\u0001,\u0001,\u0003,"+
|
||||
"\u0134\b,\u0001-\u0001-\u0003-\u0138\b-\u0001-\u0004-\u013b\b-\u000b-"+
|
||||
"\f-\u013c\u0001.\u0001.\u0001.\u0001.\u0001.\u0001.\u0001.\u0001.\u0003"+
|
||||
".\u0147\b.\u0001/\u0001/\u0001/\u0003/\u014c\b/\u00010\u00010\u00030\u0150"+
|
||||
"\b0\u00011\u00041\u0153\b1\u000b1\f1\u0154\u00011\u00011\u00012\u0001"+
|
||||
"2\u00012\u00012\u00052\u015d\b2\n2\f2\u0160\t2\u00012\u00012\u00013\u0001"+
|
||||
"3\u00013\u00013\u00053\u0168\b3\n3\f3\u016b\t3\u00013\u00013\u00013\u0001"+
|
||||
"3\u00013\u0001\u0169\u00004\u0001\u0001\u0003\u0002\u0005\u0003\u0007"+
|
||||
"\u0004\t\u0005\u000b\u0006\r\u0007\u000f\b\u0011\t\u0013\n\u0015\u000b"+
|
||||
"\u0017\f\u0019\r\u001b\u000e\u001d\u000f\u001f\u0010!\u0011#\u0012%\u0013"+
|
||||
"\'\u0014)\u0015+\u0016-\u0017/\u00181\u00193\u001a5\u001b7\u001c9\u001d"+
|
||||
";\u001e=\u001f? A!C\"E\u0000G\u0000I\u0000K\u0000M\u0000O\u0000Q\u0000"+
|
||||
"S\u0000U\u0000W\u0000Y\u0000[\u0000]\u0000_#a$c%e&g\'\u0001\u0000\f\u0003"+
|
||||
"\u0000AZ__az\u0004\u000009AZ__az\u0001\u000009\u0001\u000019\u0001\u0000"+
|
||||
"07\u0003\u000009AFaf\u0002\u0000XXxx\u0002\u0000EEee\u0002\u0000++--\u0002"+
|
||||
"\u0000PPpp\u0003\u0000\t\n\r\r \u0002\u0000\n\n\r\r\u017c\u0000\u0001"+
|
||||
"\u0001\u0000\u0000\u0000\u0000\u0003\u0001\u0000\u0000\u0000\u0000\u0005"+
|
||||
"\u0001\u0000\u0000\u0000\u0000\u0007\u0001\u0000\u0000\u0000\u0000\t\u0001"+
|
||||
"\u0000\u0000\u0000\u0000\u000b\u0001\u0000\u0000\u0000\u0000\r\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u000f\u0001\u0000\u0000\u0000\u0000\u0011\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u0013\u0001\u0000\u0000\u0000\u0000\u0015\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u0017\u0001\u0000\u0000\u0000\u0000\u0019\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u001b\u0001\u0000\u0000\u0000\u0000\u001d\u0001\u0000"+
|
||||
"\u0000\u0000\u0000\u001f\u0001\u0000\u0000\u0000\u0000!\u0001\u0000\u0000"+
|
||||
"\u0000\u0000#\u0001\u0000\u0000\u0000\u0000%\u0001\u0000\u0000\u0000\u0000"+
|
||||
"\'\u0001\u0000\u0000\u0000\u0000)\u0001\u0000\u0000\u0000\u0000+\u0001"+
|
||||
"\u0000\u0000\u0000\u0000-\u0001\u0000\u0000\u0000\u0000/\u0001\u0000\u0000"+
|
||||
"\u0000\u00001\u0001\u0000\u0000\u0000\u00003\u0001\u0000\u0000\u0000\u0000"+
|
||||
"5\u0001\u0000\u0000\u0000\u00007\u0001\u0000\u0000\u0000\u00009\u0001"+
|
||||
"\u0000\u0000\u0000\u0000;\u0001\u0000\u0000\u0000\u0000=\u0001\u0000\u0000"+
|
||||
"\u0000\u0000?\u0001\u0000\u0000\u0000\u0000A\u0001\u0000\u0000\u0000\u0000"+
|
||||
"C\u0001\u0000\u0000\u0000\u0000_\u0001\u0000\u0000\u0000\u0000a\u0001"+
|
||||
"\u0000\u0000\u0000\u0000c\u0001\u0000\u0000\u0000\u0000e\u0001\u0000\u0000"+
|
||||
"\u0000\u0000g\u0001\u0000\u0000\u0000\u0001i\u0001\u0000\u0000\u0000\u0003"+
|
||||
"o\u0001\u0000\u0000\u0000\u0005s\u0001\u0000\u0000\u0000\u0007y\u0001"+
|
||||
"\u0000\u0000\u0000\t~\u0001\u0000\u0000\u0000\u000b\u0081\u0001\u0000"+
|
||||
"\u0000\u0000\r\u0086\u0001\u0000\u0000\u0000\u000f\u008c\u0001\u0000\u0000"+
|
||||
"\u0000\u0011\u0092\u0001\u0000\u0000\u0000\u0013\u009b\u0001\u0000\u0000"+
|
||||
"\u0000\u0015\u00a2\u0001\u0000\u0000\u0000\u0017\u00a4\u0001\u0000\u0000"+
|
||||
"\u0000\u0019\u00a6\u0001\u0000\u0000\u0000\u001b\u00a8\u0001\u0000\u0000"+
|
||||
"\u0000\u001d\u00aa\u0001\u0000\u0000\u0000\u001f\u00ac\u0001\u0000\u0000"+
|
||||
"\u0000!\u00ae\u0001\u0000\u0000\u0000#\u00b1\u0001\u0000\u0000\u0000%"+
|
||||
"\u00b4\u0001\u0000\u0000\u0000\'\u00b6\u0001\u0000\u0000\u0000)\u00b9"+
|
||||
"\u0001\u0000\u0000\u0000+\u00bb\u0001\u0000\u0000\u0000-\u00be\u0001\u0000"+
|
||||
"\u0000\u0000/\u00c0\u0001\u0000\u0000\u00001\u00c3\u0001\u0000\u0000\u0000"+
|
||||
"3\u00c6\u0001\u0000\u0000\u00005\u00c8\u0001\u0000\u0000\u00007\u00ca"+
|
||||
"\u0001\u0000\u0000\u00009\u00cc\u0001\u0000\u0000\u0000;\u00ce\u0001\u0000"+
|
||||
"\u0000\u0000=\u00d0\u0001\u0000\u0000\u0000?\u00d2\u0001\u0000\u0000\u0000"+
|
||||
"A\u00d4\u0001\u0000\u0000\u0000C\u00d6\u0001\u0000\u0000\u0000E\u00dd"+
|
||||
"\u0001\u0000\u0000\u0000G\u00df\u0001\u0000\u0000\u0000I\u00e1\u0001\u0000"+
|
||||
"\u0000\u0000K\u00e3\u0001\u0000\u0000\u0000M\u00e5\u0001\u0000\u0000\u0000"+
|
||||
"O\u00ec\u0001\u0000\u0000\u0000Q\u00f3\u0001\u0000\u0000\u0000S\u010c"+
|
||||
"\u0001\u0000\u0000\u0000U\u010e\u0001\u0000\u0000\u0000W\u011e\u0001\u0000"+
|
||||
"\u0000\u0000Y\u0133\u0001\u0000\u0000\u0000[\u0135\u0001\u0000\u0000\u0000"+
|
||||
"]\u0146\u0001\u0000\u0000\u0000_\u014b\u0001\u0000\u0000\u0000a\u014f"+
|
||||
"\u0001\u0000\u0000\u0000c\u0152\u0001\u0000\u0000\u0000e\u0158\u0001\u0000"+
|
||||
"\u0000\u0000g\u0163\u0001\u0000\u0000\u0000ij\u0005c\u0000\u0000jk\u0005"+
|
||||
"o\u0000\u0000kl\u0005n\u0000\u0000lm\u0005s\u0000\u0000mn\u0005t\u0000"+
|
||||
"\u0000n\u0002\u0001\u0000\u0000\u0000op\u0005i\u0000\u0000pq\u0005n\u0000"+
|
||||
"\u0000qr\u0005t\u0000\u0000r\u0004\u0001\u0000\u0000\u0000st\u0005f\u0000"+
|
||||
"\u0000tu\u0005l\u0000\u0000uv\u0005o\u0000\u0000vw\u0005a\u0000\u0000"+
|
||||
"wx\u0005t\u0000\u0000x\u0006\u0001\u0000\u0000\u0000yz\u0005v\u0000\u0000"+
|
||||
"z{\u0005o\u0000\u0000{|\u0005i\u0000\u0000|}\u0005d\u0000\u0000}\b\u0001"+
|
||||
"\u0000\u0000\u0000~\u007f\u0005i\u0000\u0000\u007f\u0080\u0005f\u0000"+
|
||||
"\u0000\u0080\n\u0001\u0000\u0000\u0000\u0081\u0082\u0005e\u0000\u0000"+
|
||||
"\u0082\u0083\u0005l\u0000\u0000\u0083\u0084\u0005s\u0000\u0000\u0084\u0085"+
|
||||
"\u0005e\u0000\u0000\u0085\f\u0001\u0000\u0000\u0000\u0086\u0087\u0005"+
|
||||
"w\u0000\u0000\u0087\u0088\u0005h\u0000\u0000\u0088\u0089\u0005i\u0000"+
|
||||
"\u0000\u0089\u008a\u0005l\u0000\u0000\u008a\u008b\u0005e\u0000\u0000\u008b"+
|
||||
"\u000e\u0001\u0000\u0000\u0000\u008c\u008d\u0005b\u0000\u0000\u008d\u008e"+
|
||||
"\u0005r\u0000\u0000\u008e\u008f\u0005e\u0000\u0000\u008f\u0090\u0005a"+
|
||||
"\u0000\u0000\u0090\u0091\u0005k\u0000\u0000\u0091\u0010\u0001\u0000\u0000"+
|
||||
"\u0000\u0092\u0093\u0005c\u0000\u0000\u0093\u0094\u0005o\u0000\u0000\u0094"+
|
||||
"\u0095\u0005n\u0000\u0000\u0095\u0096\u0005t\u0000\u0000\u0096\u0097\u0005"+
|
||||
"i\u0000\u0000\u0097\u0098\u0005n\u0000\u0000\u0098\u0099\u0005u\u0000"+
|
||||
"\u0000\u0099\u009a\u0005e\u0000\u0000\u009a\u0012\u0001\u0000\u0000\u0000"+
|
||||
"\u009b\u009c\u0005r\u0000\u0000\u009c\u009d\u0005e\u0000\u0000\u009d\u009e"+
|
||||
"\u0005t\u0000\u0000\u009e\u009f\u0005u\u0000\u0000\u009f\u00a0\u0005r"+
|
||||
"\u0000\u0000\u00a0\u00a1\u0005n\u0000\u0000\u00a1\u0014\u0001\u0000\u0000"+
|
||||
"\u0000\u00a2\u00a3\u0005+\u0000\u0000\u00a3\u0016\u0001\u0000\u0000\u0000"+
|
||||
"\u00a4\u00a5\u0005-\u0000\u0000\u00a5\u0018\u0001\u0000\u0000\u0000\u00a6"+
|
||||
"\u00a7\u0005*\u0000\u0000\u00a7\u001a\u0001\u0000\u0000\u0000\u00a8\u00a9"+
|
||||
"\u0005/\u0000\u0000\u00a9\u001c\u0001\u0000\u0000\u0000\u00aa\u00ab\u0005"+
|
||||
"%\u0000\u0000\u00ab\u001e\u0001\u0000\u0000\u0000\u00ac\u00ad\u0005=\u0000"+
|
||||
"\u0000\u00ad \u0001\u0000\u0000\u0000\u00ae\u00af\u0005=\u0000\u0000\u00af"+
|
||||
"\u00b0\u0005=\u0000\u0000\u00b0\"\u0001\u0000\u0000\u0000\u00b1\u00b2"+
|
||||
"\u0005!\u0000\u0000\u00b2\u00b3\u0005=\u0000\u0000\u00b3$\u0001\u0000"+
|
||||
"\u0000\u0000\u00b4\u00b5\u0005<\u0000\u0000\u00b5&\u0001\u0000\u0000\u0000"+
|
||||
"\u00b6\u00b7\u0005<\u0000\u0000\u00b7\u00b8\u0005=\u0000\u0000\u00b8("+
|
||||
"\u0001\u0000\u0000\u0000\u00b9\u00ba\u0005>\u0000\u0000\u00ba*\u0001\u0000"+
|
||||
"\u0000\u0000\u00bb\u00bc\u0005>\u0000\u0000\u00bc\u00bd\u0005=\u0000\u0000"+
|
||||
"\u00bd,\u0001\u0000\u0000\u0000\u00be\u00bf\u0005!\u0000\u0000\u00bf."+
|
||||
"\u0001\u0000\u0000\u0000\u00c0\u00c1\u0005&\u0000\u0000\u00c1\u00c2\u0005"+
|
||||
"&\u0000\u0000\u00c20\u0001\u0000\u0000\u0000\u00c3\u00c4\u0005|\u0000"+
|
||||
"\u0000\u00c4\u00c5\u0005|\u0000\u0000\u00c52\u0001\u0000\u0000\u0000\u00c6"+
|
||||
"\u00c7\u0005(\u0000\u0000\u00c74\u0001\u0000\u0000\u0000\u00c8\u00c9\u0005"+
|
||||
")\u0000\u0000\u00c96\u0001\u0000\u0000\u0000\u00ca\u00cb\u0005[\u0000"+
|
||||
"\u0000\u00cb8\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005]\u0000\u0000\u00cd"+
|
||||
":\u0001\u0000\u0000\u0000\u00ce\u00cf\u0005{\u0000\u0000\u00cf<\u0001"+
|
||||
"\u0000\u0000\u0000\u00d0\u00d1\u0005}\u0000\u0000\u00d1>\u0001\u0000\u0000"+
|
||||
"\u0000\u00d2\u00d3\u0005,\u0000\u0000\u00d3@\u0001\u0000\u0000\u0000\u00d4"+
|
||||
"\u00d5\u0005;\u0000\u0000\u00d5B\u0001\u0000\u0000\u0000\u00d6\u00da\u0007"+
|
||||
"\u0000\u0000\u0000\u00d7\u00d9\u0007\u0001\u0000\u0000\u00d8\u00d7\u0001"+
|
||||
"\u0000\u0000\u0000\u00d9\u00dc\u0001\u0000\u0000\u0000\u00da\u00d8\u0001"+
|
||||
"\u0000\u0000\u0000\u00da\u00db\u0001\u0000\u0000\u0000\u00dbD\u0001\u0000"+
|
||||
"\u0000\u0000\u00dc\u00da\u0001\u0000\u0000\u0000\u00dd\u00de\u0007\u0002"+
|
||||
"\u0000\u0000\u00deF\u0001\u0000\u0000\u0000\u00df\u00e0\u0007\u0003\u0000"+
|
||||
"\u0000\u00e0H\u0001\u0000\u0000\u0000\u00e1\u00e2\u0007\u0004\u0000\u0000"+
|
||||
"\u00e2J\u0001\u0000\u0000\u0000\u00e3\u00e4\u0007\u0005\u0000\u0000\u00e4"+
|
||||
"L\u0001\u0000\u0000\u0000\u00e5\u00e9\u0003G#\u0000\u00e6\u00e8\u0003"+
|
||||
"E\"\u0000\u00e7\u00e6\u0001\u0000\u0000\u0000\u00e8\u00eb\u0001\u0000"+
|
||||
"\u0000\u0000\u00e9\u00e7\u0001\u0000\u0000\u0000\u00e9\u00ea\u0001\u0000"+
|
||||
"\u0000\u0000\u00eaN\u0001\u0000\u0000\u0000\u00eb\u00e9\u0001\u0000\u0000"+
|
||||
"\u0000\u00ec\u00f0\u00050\u0000\u0000\u00ed\u00ef\u0003I$\u0000\u00ee"+
|
||||
"\u00ed\u0001\u0000\u0000\u0000\u00ef\u00f2\u0001\u0000\u0000\u0000\u00f0"+
|
||||
"\u00ee\u0001\u0000\u0000\u0000\u00f0\u00f1\u0001\u0000\u0000\u0000\u00f1"+
|
||||
"P\u0001\u0000\u0000\u0000\u00f2\u00f0\u0001\u0000\u0000\u0000\u00f3\u00f4"+
|
||||
"\u00050\u0000\u0000\u00f4\u00f6\u0007\u0006\u0000\u0000\u00f5\u00f7\u0003"+
|
||||
"K%\u0000\u00f6\u00f5\u0001\u0000\u0000\u0000\u00f7\u00f8\u0001\u0000\u0000"+
|
||||
"\u0000\u00f8\u00f6\u0001\u0000\u0000\u0000\u00f8\u00f9\u0001\u0000\u0000"+
|
||||
"\u0000\u00f9R\u0001\u0000\u0000\u0000\u00fa\u00fc\u0003E\"\u0000\u00fb"+
|
||||
"\u00fa\u0001\u0000\u0000\u0000\u00fc\u00fd\u0001\u0000\u0000\u0000\u00fd"+
|
||||
"\u00fb\u0001\u0000\u0000\u0000\u00fd\u00fe\u0001\u0000\u0000\u0000\u00fe"+
|
||||
"\u00ff\u0001\u0000\u0000\u0000\u00ff\u0103\u0005.\u0000\u0000\u0100\u0102"+
|
||||
"\u0003E\"\u0000\u0101\u0100\u0001\u0000\u0000\u0000\u0102\u0105\u0001"+
|
||||
"\u0000\u0000\u0000\u0103\u0101\u0001\u0000\u0000\u0000\u0103\u0104\u0001"+
|
||||
"\u0000\u0000\u0000\u0104\u010d\u0001\u0000\u0000\u0000\u0105\u0103\u0001"+
|
||||
"\u0000\u0000\u0000\u0106\u0108\u0005.\u0000\u0000\u0107\u0109\u0003E\""+
|
||||
"\u0000\u0108\u0107\u0001\u0000\u0000\u0000\u0109\u010a\u0001\u0000\u0000"+
|
||||
"\u0000\u010a\u0108\u0001\u0000\u0000\u0000\u010a\u010b\u0001\u0000\u0000"+
|
||||
"\u0000\u010b\u010d\u0001\u0000\u0000\u0000\u010c\u00fb\u0001\u0000\u0000"+
|
||||
"\u0000\u010c\u0106\u0001\u0000\u0000\u0000\u010dT\u0001\u0000\u0000\u0000"+
|
||||
"\u010e\u0110\u0007\u0007\u0000\u0000\u010f\u0111\u0007\b\u0000\u0000\u0110"+
|
||||
"\u010f\u0001\u0000\u0000\u0000\u0110\u0111\u0001\u0000\u0000\u0000\u0111"+
|
||||
"\u0113\u0001\u0000\u0000\u0000\u0112\u0114\u0003E\"\u0000\u0113\u0112"+
|
||||
"\u0001\u0000\u0000\u0000\u0114\u0115\u0001\u0000\u0000\u0000\u0115\u0113"+
|
||||
"\u0001\u0000\u0000\u0000\u0115\u0116\u0001\u0000\u0000\u0000\u0116V\u0001"+
|
||||
"\u0000\u0000\u0000\u0117\u0119\u0003S)\u0000\u0118\u011a\u0003U*\u0000"+
|
||||
"\u0119\u0118\u0001\u0000\u0000\u0000\u0119\u011a\u0001\u0000\u0000\u0000"+
|
||||
"\u011a\u011f\u0001\u0000\u0000\u0000\u011b\u011c\u0003M&\u0000\u011c\u011d"+
|
||||
"\u0003U*\u0000\u011d\u011f\u0001\u0000\u0000\u0000\u011e\u0117\u0001\u0000"+
|
||||
"\u0000\u0000\u011e\u011b\u0001\u0000\u0000\u0000\u011fX\u0001\u0000\u0000"+
|
||||
"\u0000\u0120\u0122\u0003K%\u0000\u0121\u0120\u0001\u0000\u0000\u0000\u0122"+
|
||||
"\u0125\u0001\u0000\u0000\u0000\u0123\u0121\u0001\u0000\u0000\u0000\u0123"+
|
||||
"\u0124\u0001\u0000\u0000\u0000\u0124\u0126\u0001\u0000\u0000\u0000\u0125"+
|
||||
"\u0123\u0001\u0000\u0000\u0000\u0126\u0128\u0005.\u0000\u0000\u0127\u0129"+
|
||||
"\u0003K%\u0000\u0128\u0127\u0001\u0000\u0000\u0000\u0129\u012a\u0001\u0000"+
|
||||
"\u0000\u0000\u012a\u0128\u0001\u0000\u0000\u0000\u012a\u012b\u0001\u0000"+
|
||||
"\u0000\u0000\u012b\u0134\u0001\u0000\u0000\u0000\u012c\u012e\u0003K%\u0000"+
|
||||
"\u012d\u012c\u0001\u0000\u0000\u0000\u012e\u012f\u0001\u0000\u0000\u0000"+
|
||||
"\u012f\u012d\u0001\u0000\u0000\u0000\u012f\u0130\u0001\u0000\u0000\u0000"+
|
||||
"\u0130\u0131\u0001\u0000\u0000\u0000\u0131\u0132\u0005.\u0000\u0000\u0132"+
|
||||
"\u0134\u0001\u0000\u0000\u0000\u0133\u0123\u0001\u0000\u0000\u0000\u0133"+
|
||||
"\u012d\u0001\u0000\u0000\u0000\u0134Z\u0001\u0000\u0000\u0000\u0135\u0137"+
|
||||
"\u0007\t\u0000\u0000\u0136\u0138\u0007\b\u0000\u0000\u0137\u0136\u0001"+
|
||||
"\u0000\u0000\u0000\u0137\u0138\u0001\u0000\u0000\u0000\u0138\u013a\u0001"+
|
||||
"\u0000\u0000\u0000\u0139\u013b\u0003E\"\u0000\u013a\u0139\u0001\u0000"+
|
||||
"\u0000\u0000\u013b\u013c\u0001\u0000\u0000\u0000\u013c\u013a\u0001\u0000"+
|
||||
"\u0000\u0000\u013c\u013d\u0001\u0000\u0000\u0000\u013d\\\u0001\u0000\u0000"+
|
||||
"\u0000\u013e\u013f\u00050\u0000\u0000\u013f\u0140\u0007\u0006\u0000\u0000"+
|
||||
"\u0140\u0141\u0003Y,\u0000\u0141\u0142\u0003[-\u0000\u0142\u0147\u0001"+
|
||||
"\u0000\u0000\u0000\u0143\u0144\u0003Q(\u0000\u0144\u0145\u0003[-\u0000"+
|
||||
"\u0145\u0147\u0001\u0000\u0000\u0000\u0146\u013e\u0001\u0000\u0000\u0000"+
|
||||
"\u0146\u0143\u0001\u0000\u0000\u0000\u0147^\u0001\u0000\u0000\u0000\u0148"+
|
||||
"\u014c\u0003M&\u0000\u0149\u014c\u0003O\'\u0000\u014a\u014c\u0003Q(\u0000"+
|
||||
"\u014b\u0148\u0001\u0000\u0000\u0000\u014b\u0149\u0001\u0000\u0000\u0000"+
|
||||
"\u014b\u014a\u0001\u0000\u0000\u0000\u014c`\u0001\u0000\u0000\u0000\u014d"+
|
||||
"\u0150\u0003W+\u0000\u014e\u0150\u0003].\u0000\u014f\u014d\u0001\u0000"+
|
||||
"\u0000\u0000\u014f\u014e\u0001\u0000\u0000\u0000\u0150b\u0001\u0000\u0000"+
|
||||
"\u0000\u0151\u0153\u0007\n\u0000\u0000\u0152\u0151\u0001\u0000\u0000\u0000"+
|
||||
"\u0153\u0154\u0001\u0000\u0000\u0000\u0154\u0152\u0001\u0000\u0000\u0000"+
|
||||
"\u0154\u0155\u0001\u0000\u0000\u0000\u0155\u0156\u0001\u0000\u0000\u0000"+
|
||||
"\u0156\u0157\u00061\u0000\u0000\u0157d\u0001\u0000\u0000\u0000\u0158\u0159"+
|
||||
"\u0005/\u0000\u0000\u0159\u015a\u0005/\u0000\u0000\u015a\u015e\u0001\u0000"+
|
||||
"\u0000\u0000\u015b\u015d\b\u000b\u0000\u0000\u015c\u015b\u0001\u0000\u0000"+
|
||||
"\u0000\u015d\u0160\u0001\u0000\u0000\u0000\u015e\u015c\u0001\u0000\u0000"+
|
||||
"\u0000\u015e\u015f\u0001\u0000\u0000\u0000\u015f\u0161\u0001\u0000\u0000"+
|
||||
"\u0000\u0160\u015e\u0001\u0000\u0000\u0000\u0161\u0162\u00062\u0000\u0000"+
|
||||
"\u0162f\u0001\u0000\u0000\u0000\u0163\u0164\u0005/\u0000\u0000\u0164\u0165"+
|
||||
"\u0005*\u0000\u0000\u0165\u0169\u0001\u0000\u0000\u0000\u0166\u0168\t"+
|
||||
"\u0000\u0000\u0000\u0167\u0166\u0001\u0000\u0000\u0000\u0168\u016b\u0001"+
|
||||
"\u0000\u0000\u0000\u0169\u016a\u0001\u0000\u0000\u0000\u0169\u0167\u0001"+
|
||||
"\u0000\u0000\u0000\u016a\u016c\u0001\u0000\u0000\u0000\u016b\u0169\u0001"+
|
||||
"\u0000\u0000\u0000\u016c\u016d\u0005*\u0000\u0000\u016d\u016e\u0005/\u0000"+
|
||||
"\u0000\u016e\u016f\u0001\u0000\u0000\u0000\u016f\u0170\u00063\u0000\u0000"+
|
||||
"\u0170h\u0001\u0000\u0000\u0000\u0019\u0000\u00da\u00e9\u00f0\u00f8\u00fd"+
|
||||
"\u0103\u010a\u010c\u0110\u0115\u0119\u011e\u0123\u012a\u012f\u0133\u0137"+
|
||||
"\u013c\u0146\u014b\u014f\u0154\u015e\u0169\u0001\u0006\u0000\u0000";
|
||||
public static final ATN _ATN =
|
||||
new ATNDeserializer().deserialize(_serializedATN.toCharArray());
|
||||
static {
|
||||
_decisionToDFA = new DFA[_ATN.getNumberOfDecisions()];
|
||||
for (int i = 0; i < _ATN.getNumberOfDecisions(); i++) {
|
||||
_decisionToDFA[i] = new DFA(_ATN.getDecisionState(i), i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,515 @@
|
||||
// Generated from /root/sysy2026/nudt-compiler-cpp/src/antlr4/SysY.g4 by ANTLR 4.13.1
|
||||
import org.antlr.v4.runtime.tree.ParseTreeListener;
|
||||
|
||||
/**
|
||||
* This interface defines a complete listener for a parse tree produced by
|
||||
* {@link SysYParser}.
|
||||
*/
|
||||
public interface SysYListener extends ParseTreeListener {
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#compUnit}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterCompUnit(SysYParser.CompUnitContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#compUnit}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitCompUnit(SysYParser.CompUnitContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#decl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterDecl(SysYParser.DeclContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#decl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitDecl(SysYParser.DeclContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#constDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterConstDecl(SysYParser.ConstDeclContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#constDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitConstDecl(SysYParser.ConstDeclContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#bType}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBType(SysYParser.BTypeContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#bType}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBType(SysYParser.BTypeContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#constDef}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterConstDef(SysYParser.ConstDefContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#constDef}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitConstDef(SysYParser.ConstDefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#constInitVal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterConstInitVal(SysYParser.ConstInitValContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#constInitVal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitConstInitVal(SysYParser.ConstInitValContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#varDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterVarDecl(SysYParser.VarDeclContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#varDecl}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitVarDecl(SysYParser.VarDeclContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#varDef}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterVarDef(SysYParser.VarDefContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#varDef}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitVarDef(SysYParser.VarDefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#initVal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterInitVal(SysYParser.InitValContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#initVal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitInitVal(SysYParser.InitValContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#funcDef}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterFuncDef(SysYParser.FuncDefContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#funcDef}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitFuncDef(SysYParser.FuncDefContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#funcType}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterFuncType(SysYParser.FuncTypeContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#funcType}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitFuncType(SysYParser.FuncTypeContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#funcFParams}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterFuncFParams(SysYParser.FuncFParamsContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#funcFParams}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitFuncFParams(SysYParser.FuncFParamsContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#funcFParam}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterFuncFParam(SysYParser.FuncFParamContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#funcFParam}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitFuncFParam(SysYParser.FuncFParamContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#block}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBlock(SysYParser.BlockContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#block}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBlock(SysYParser.BlockContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#blockItem}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBlockItem(SysYParser.BlockItemContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#blockItem}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBlockItem(SysYParser.BlockItemContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code assignStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterAssignStmt(SysYParser.AssignStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code assignStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAssignStmt(SysYParser.AssignStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code expStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExpStmt(SysYParser.ExpStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code expStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExpStmt(SysYParser.ExpStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code blockStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBlockStmt(SysYParser.BlockStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code blockStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBlockStmt(SysYParser.BlockStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code ifStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterIfStmt(SysYParser.IfStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code ifStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitIfStmt(SysYParser.IfStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code whileStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterWhileStmt(SysYParser.WhileStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code whileStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitWhileStmt(SysYParser.WhileStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code breakStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBreakStmt(SysYParser.BreakStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code breakStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBreakStmt(SysYParser.BreakStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code continueStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterContinueStmt(SysYParser.ContinueStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code continueStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitContinueStmt(SysYParser.ContinueStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code returnStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterReturnStmt(SysYParser.ReturnStmtContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code returnStmt}
|
||||
* labeled alternative in {@link SysYParser#stmt}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitReturnStmt(SysYParser.ReturnStmtContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#exp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterExp(SysYParser.ExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#exp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitExp(SysYParser.ExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#cond}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterCond(SysYParser.CondContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#cond}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitCond(SysYParser.CondContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#lVal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterLVal(SysYParser.LValContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#lVal}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitLVal(SysYParser.LValContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#primaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterPrimaryExp(SysYParser.PrimaryExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#primaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitPrimaryExp(SysYParser.PrimaryExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#number}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterNumber(SysYParser.NumberContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#number}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitNumber(SysYParser.NumberContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code primaryUnaryExp}
|
||||
* labeled alternative in {@link SysYParser#unaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterPrimaryUnaryExp(SysYParser.PrimaryUnaryExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code primaryUnaryExp}
|
||||
* labeled alternative in {@link SysYParser#unaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitPrimaryUnaryExp(SysYParser.PrimaryUnaryExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code callUnaryExp}
|
||||
* labeled alternative in {@link SysYParser#unaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterCallUnaryExp(SysYParser.CallUnaryExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code callUnaryExp}
|
||||
* labeled alternative in {@link SysYParser#unaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitCallUnaryExp(SysYParser.CallUnaryExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code opUnaryExp}
|
||||
* labeled alternative in {@link SysYParser#unaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterOpUnaryExp(SysYParser.OpUnaryExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code opUnaryExp}
|
||||
* labeled alternative in {@link SysYParser#unaryExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitOpUnaryExp(SysYParser.OpUnaryExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#unaryOp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterUnaryOp(SysYParser.UnaryOpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#unaryOp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitUnaryOp(SysYParser.UnaryOpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#funcRParams}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterFuncRParams(SysYParser.FuncRParamsContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#funcRParams}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitFuncRParams(SysYParser.FuncRParamsContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code binaryMulExp}
|
||||
* labeled alternative in {@link SysYParser#mulExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBinaryMulExp(SysYParser.BinaryMulExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code binaryMulExp}
|
||||
* labeled alternative in {@link SysYParser#mulExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBinaryMulExp(SysYParser.BinaryMulExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code unaryMulExp}
|
||||
* labeled alternative in {@link SysYParser#mulExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterUnaryMulExp(SysYParser.UnaryMulExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code unaryMulExp}
|
||||
* labeled alternative in {@link SysYParser#mulExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitUnaryMulExp(SysYParser.UnaryMulExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code binaryAddExp}
|
||||
* labeled alternative in {@link SysYParser#addExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBinaryAddExp(SysYParser.BinaryAddExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code binaryAddExp}
|
||||
* labeled alternative in {@link SysYParser#addExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBinaryAddExp(SysYParser.BinaryAddExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code mulAddExp}
|
||||
* labeled alternative in {@link SysYParser#addExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterMulAddExp(SysYParser.MulAddExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code mulAddExp}
|
||||
* labeled alternative in {@link SysYParser#addExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitMulAddExp(SysYParser.MulAddExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code addRelExp}
|
||||
* labeled alternative in {@link SysYParser#relExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterAddRelExp(SysYParser.AddRelExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code addRelExp}
|
||||
* labeled alternative in {@link SysYParser#relExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAddRelExp(SysYParser.AddRelExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code binaryRelExp}
|
||||
* labeled alternative in {@link SysYParser#relExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBinaryRelExp(SysYParser.BinaryRelExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code binaryRelExp}
|
||||
* labeled alternative in {@link SysYParser#relExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBinaryRelExp(SysYParser.BinaryRelExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code binaryEqExp}
|
||||
* labeled alternative in {@link SysYParser#eqExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBinaryEqExp(SysYParser.BinaryEqExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code binaryEqExp}
|
||||
* labeled alternative in {@link SysYParser#eqExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBinaryEqExp(SysYParser.BinaryEqExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code relEqExp}
|
||||
* labeled alternative in {@link SysYParser#eqExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterRelEqExp(SysYParser.RelEqExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code relEqExp}
|
||||
* labeled alternative in {@link SysYParser#eqExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitRelEqExp(SysYParser.RelEqExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code eqLAndExp}
|
||||
* labeled alternative in {@link SysYParser#lAndExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterEqLAndExp(SysYParser.EqLAndExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code eqLAndExp}
|
||||
* labeled alternative in {@link SysYParser#lAndExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitEqLAndExp(SysYParser.EqLAndExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code binaryLAndExp}
|
||||
* labeled alternative in {@link SysYParser#lAndExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBinaryLAndExp(SysYParser.BinaryLAndExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code binaryLAndExp}
|
||||
* labeled alternative in {@link SysYParser#lAndExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBinaryLAndExp(SysYParser.BinaryLAndExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code andLOrExp}
|
||||
* labeled alternative in {@link SysYParser#lOrExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterAndLOrExp(SysYParser.AndLOrExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code andLOrExp}
|
||||
* labeled alternative in {@link SysYParser#lOrExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitAndLOrExp(SysYParser.AndLOrExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by the {@code binaryLOrExp}
|
||||
* labeled alternative in {@link SysYParser#lOrExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterBinaryLOrExp(SysYParser.BinaryLOrExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by the {@code binaryLOrExp}
|
||||
* labeled alternative in {@link SysYParser#lOrExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitBinaryLOrExp(SysYParser.BinaryLOrExpContext ctx);
|
||||
/**
|
||||
* Enter a parse tree produced by {@link SysYParser#constExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void enterConstExp(SysYParser.ConstExpContext ctx);
|
||||
/**
|
||||
* Exit a parse tree produced by {@link SysYParser#constExp}.
|
||||
* @param ctx the parse tree
|
||||
*/
|
||||
void exitConstExp(SysYParser.ConstExpContext ctx);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@ -1,98 +1,178 @@
|
||||
// SysY 子集语法:支持形如
|
||||
// int main() { int a = 1; int b = 2; return a + b; }
|
||||
// 的最小返回表达式编译。
|
||||
grammar SysY;
|
||||
|
||||
// 后续需要自行添加
|
||||
////Grammer
|
||||
|
||||
grammar SysY;
|
||||
module: compUnit EOF;
|
||||
|
||||
compUnit: (decl | funcDef)+;
|
||||
|
||||
decl: constDecl | varDecl;
|
||||
|
||||
constDecl: CONST bType constDef (COMMA constDef)* SEMI;
|
||||
|
||||
bType: INT | FLOAT;
|
||||
|
||||
constDef: Ident (LBRACK constExp RBRACK)* ASSIGN constInitVal;
|
||||
|
||||
constInitVal:
|
||||
constExp
|
||||
| LBRACE (constInitVal (COMMA constInitVal)*)? RBRACE;
|
||||
|
||||
varDecl: bType varDef (COMMA varDef)* SEMI;
|
||||
|
||||
varDef:
|
||||
Ident (LBRACK constExp RBRACK)*
|
||||
| Ident (LBRACK constExp RBRACK)* ASSIGN initVal;
|
||||
|
||||
initVal: exp | LBRACE (initVal (COMMA initVal)*)? RBRACE;
|
||||
|
||||
funcDef: funcType Ident LPAREN funcFParams? RPAREN block;
|
||||
|
||||
funcType: VOID | INT | FLOAT;
|
||||
|
||||
funcFParams: funcFParam (COMMA funcFParam)*;
|
||||
|
||||
funcFParam:
|
||||
bType Ident
|
||||
| bType Ident LBRACK RBRACK (LBRACK exp RBRACK)*;
|
||||
|
||||
block: LBRACE blockItem* RBRACE;
|
||||
|
||||
blockItem: decl | stmt;
|
||||
|
||||
stmt:
|
||||
lVal ASSIGN exp SEMI
|
||||
| exp? SEMI
|
||||
| block
|
||||
| IF LPAREN cond RPAREN stmt (ELSE stmt)?
|
||||
| WHILE LPAREN cond RPAREN stmt
|
||||
| BREAK SEMI
|
||||
| CONTINUE SEMI
|
||||
| RETURN exp? SEMI;
|
||||
|
||||
/*===-------------------------------------------===*/
|
||||
/* Lexer rules */
|
||||
/*===-------------------------------------------===*/
|
||||
exp: addExp;
|
||||
|
||||
cond: lOrExp;
|
||||
|
||||
lVal: Ident (LBRACK exp RBRACK)*;
|
||||
|
||||
primaryExp: LPAREN exp RPAREN | lVal | number;
|
||||
|
||||
number: IntConst | FloatConst;
|
||||
|
||||
unaryExp:
|
||||
primaryExp
|
||||
| Ident LPAREN funcRParams? RPAREN
|
||||
| unaryOp unaryExp;
|
||||
|
||||
unaryOp: ADD | SUB | NOT;
|
||||
|
||||
funcRParams: exp (COMMA exp)*;
|
||||
|
||||
mulExp:
|
||||
unaryExp
|
||||
| mulExp op = (MUL | DIV | MOD) unaryExp;
|
||||
|
||||
addExp:
|
||||
mulExp
|
||||
| addExp op = (ADD | SUB) mulExp;
|
||||
|
||||
relExp:
|
||||
addExp
|
||||
| relExp op = (LT | GT | LE | GE) addExp;
|
||||
|
||||
eqExp:
|
||||
relExp
|
||||
| eqExp op = (EQ | NE) relExp;
|
||||
|
||||
lAndExp: eqExp | lAndExp AND eqExp ;
|
||||
|
||||
lOrExp: lAndExp | lOrExp OR lAndExp ;
|
||||
|
||||
constExp: addExp;
|
||||
|
||||
////Lexer
|
||||
//keywords
|
||||
CONST: 'const';
|
||||
INT: 'int';
|
||||
FLOAT: 'float';
|
||||
VOID: 'void';
|
||||
IF: 'if';
|
||||
ELSE: 'else';
|
||||
WHILE: 'while';
|
||||
BREAK: 'break';
|
||||
CONTINUE: 'continue';
|
||||
RETURN: 'return';
|
||||
|
||||
ASSIGN: '=';
|
||||
//operators
|
||||
ADD: '+';
|
||||
|
||||
SUB: '-';
|
||||
MUL: '*';
|
||||
DIV: '/';
|
||||
MOD: '%';
|
||||
ASSIGN: '=';
|
||||
EQ: '==';
|
||||
NE: '!=';
|
||||
LT: '<';
|
||||
LE: '<=';
|
||||
GT: '>';
|
||||
GE: '>=';
|
||||
NOT: '!';
|
||||
AND: '&&';
|
||||
OR: '||';
|
||||
|
||||
//括号
|
||||
LPAREN: '(';
|
||||
RPAREN: ')';
|
||||
LBRACK: '[';
|
||||
RBRACK: ']';
|
||||
LBRACE: '{';
|
||||
RBRACE: '}';
|
||||
SEMICOLON: ';';
|
||||
|
||||
ID: [a-zA-Z_][a-zA-Z_0-9]*;
|
||||
ILITERAL: [0-9]+;
|
||||
|
||||
WS: [ \t\r\n] -> skip;
|
||||
LINECOMMENT: '//' ~[\r\n]* -> skip;
|
||||
BLOCKCOMMENT: '/*' .*? '*/' -> skip;
|
||||
|
||||
/*===-------------------------------------------===*/
|
||||
/* Syntax rules */
|
||||
/*===-------------------------------------------===*/
|
||||
|
||||
compUnit
|
||||
: funcDef EOF
|
||||
;
|
||||
|
||||
decl
|
||||
: btype varDef SEMICOLON
|
||||
;
|
||||
|
||||
btype
|
||||
: INT
|
||||
;
|
||||
|
||||
varDef
|
||||
: lValue (ASSIGN initValue)?
|
||||
;
|
||||
|
||||
initValue
|
||||
: exp
|
||||
;
|
||||
|
||||
funcDef
|
||||
: funcType ID LPAREN RPAREN blockStmt
|
||||
;
|
||||
|
||||
funcType
|
||||
: INT
|
||||
;
|
||||
|
||||
blockStmt
|
||||
: LBRACE blockItem* RBRACE
|
||||
;
|
||||
|
||||
blockItem
|
||||
: decl
|
||||
| stmt
|
||||
;
|
||||
|
||||
stmt
|
||||
: returnStmt
|
||||
;
|
||||
|
||||
returnStmt
|
||||
: RETURN exp SEMICOLON
|
||||
;
|
||||
|
||||
exp
|
||||
: LPAREN exp RPAREN # parenExp
|
||||
| var # varExp
|
||||
| number # numberExp
|
||||
| exp ADD exp # additiveExp
|
||||
;
|
||||
|
||||
var
|
||||
: ID
|
||||
;
|
||||
|
||||
lValue
|
||||
: ID
|
||||
;
|
||||
|
||||
number
|
||||
: ILITERAL
|
||||
;
|
||||
COMMA: ',';
|
||||
SEMI: ';';
|
||||
|
||||
//标识符
|
||||
Ident: [a-zA-Z_] [a-zA-Z_0-9]*;
|
||||
|
||||
//数字常量片段
|
||||
// 十进制数字
|
||||
fragment Digit: [0-9];
|
||||
// 非零十进制数字
|
||||
fragment NonzeroDigit: [1-9];
|
||||
// 八进制数字
|
||||
fragment OctDigit: [0-7];
|
||||
// 十六进制数字
|
||||
fragment HexDigit: [0-9a-fA-F];
|
||||
// 十进制整数:非零开头,后接若干十进制数字
|
||||
fragment DecInteger: NonzeroDigit Digit*;
|
||||
// 八进制整数:以 0 开头
|
||||
fragment OctInteger: '0' OctDigit*;
|
||||
// 十六进制整数:以 0x 或 0X 开头
|
||||
fragment HexInteger: '0' [xX] HexDigit+;
|
||||
// 十进制小数部分
|
||||
fragment DecFraction: Digit+ '.' Digit* | '.' Digit+;
|
||||
// 十进制指数部分
|
||||
fragment DecExponent: [eE] [+\-]? Digit+;
|
||||
// 十进制浮点数
|
||||
fragment DecFloat:
|
||||
DecFraction DecExponent?
|
||||
| DecInteger DecExponent;
|
||||
// 十六进制小数部分
|
||||
fragment HexFraction: HexDigit* '.' HexDigit+ | HexDigit+ '.';
|
||||
// 十六进制浮点数的二进制指数部分
|
||||
fragment BinExponent: [pP] [+\-]? Digit+;
|
||||
// 十六进制浮点数
|
||||
fragment HexFloat:
|
||||
'0' [xX] HexFraction BinExponent
|
||||
| HexInteger BinExponent;
|
||||
//整型常量
|
||||
IntConst: DecInteger | OctInteger | HexInteger;
|
||||
//浮点常量
|
||||
FloatConst: DecFloat | HexFloat;
|
||||
|
||||
//空白符规则
|
||||
WS: [ \t\r\n]+ -> skip;
|
||||
// 单行注释
|
||||
LINE_COMMENT: '//' ~[\r\n]* -> skip;
|
||||
// 跨行注释
|
||||
BLOCK_COMMENT: '/*' .*? '*/' -> skip;
|
||||
@ -1,4 +1,752 @@
|
||||
// 常量求值:
|
||||
// - 处理数组维度、全局初始化、const 表达式等编译期可计算场景
|
||||
// - 为语义分析与 IR 生成提供常量折叠/常量值信息
|
||||
#include "sem/ConstEval.h"
|
||||
|
||||
#include <any>
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <limits>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "SysYBaseVisitor.h"
|
||||
#include "utils/Log.h"
|
||||
|
||||
namespace {
|
||||
|
||||
using DataType = SymbolDataType;
|
||||
|
||||
bool IsNumericType(DataType type) {
|
||||
return type == DataType::Int || type == DataType::Float ||
|
||||
type == DataType::Bool;
|
||||
}
|
||||
|
||||
ConstValue MakeZeroValue(DataType type) {
|
||||
switch (type) {
|
||||
case DataType::Float:
|
||||
return ConstValue::FromFloat(0.0);
|
||||
case DataType::Int:
|
||||
return ConstValue::FromInt(0);
|
||||
case DataType::Bool:
|
||||
return ConstValue::FromBool(false);
|
||||
default:
|
||||
return ConstValue{};
|
||||
}
|
||||
}
|
||||
|
||||
ConstValue CastToType(ConstValue value, DataType target_type) {
|
||||
switch (target_type) {
|
||||
case DataType::Int:
|
||||
return ConstValue::FromInt(value.AsInt());
|
||||
case DataType::Float:
|
||||
return ConstValue::FromFloat(value.AsFloat());
|
||||
case DataType::Bool:
|
||||
return ConstValue::FromBool(value.AsBool());
|
||||
default:
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "不支持的常量目标类型转换"));
|
||||
}
|
||||
}
|
||||
|
||||
int64_t ParseIntLiteral(const std::string& text) {
|
||||
char* end = nullptr;
|
||||
const long long value = std::strtoll(text.c_str(), &end, 0);
|
||||
if (end == text.c_str() || *end != '\0') {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "整数字面量解析失败: " + text));
|
||||
}
|
||||
return static_cast<int64_t>(value);
|
||||
}
|
||||
|
||||
double ParseFloatLiteral(const std::string& text) {
|
||||
char* end = nullptr;
|
||||
const double value = std::strtod(text.c_str(), &end);
|
||||
if (end == text.c_str() || *end != '\0') {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "浮点数字面量解析失败: " + text));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
size_t Product(const std::vector<int64_t>& dims, size_t begin) {
|
||||
size_t result = 1;
|
||||
for (size_t i = begin; i < dims.size(); ++i) {
|
||||
if (dims[i] <= 0) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组维度必须为正整数"));
|
||||
}
|
||||
const size_t dim = static_cast<size_t>(dims[i]);
|
||||
if (result > std::numeric_limits<size_t>::max() / dim) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组维度乘积溢出"));
|
||||
}
|
||||
result *= dim;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class ConstEvalVisitor final : public SysYBaseVisitor {
|
||||
public:
|
||||
ConstEvalVisitor(const SymbolTable& table, const ConstEvalContext& values)
|
||||
: table_(table), values_(values) {}
|
||||
|
||||
ConstValue EvaluateConstExp(SysYParser::ConstExpContext& ctx) {
|
||||
return Evaluate(ctx.addExp());
|
||||
}
|
||||
|
||||
ConstValue EvaluateExp(SysYParser::ExpContext& ctx) {
|
||||
return Evaluate(ctx.addExp());
|
||||
}
|
||||
|
||||
std::any visitExp(SysYParser::ExpContext* ctx) override {
|
||||
if (!ctx || !ctx->addExp()) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法表达式"));
|
||||
}
|
||||
return Evaluate(ctx->addExp());
|
||||
}
|
||||
|
||||
std::any visitConstExp(SysYParser::ConstExpContext* ctx) override {
|
||||
if (!ctx || !ctx->addExp()) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 constExp"));
|
||||
}
|
||||
return Evaluate(ctx->addExp());
|
||||
}
|
||||
|
||||
std::any visitCond(SysYParser::CondContext* ctx) override {
|
||||
if (!ctx || !ctx->lOrExp()) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法条件表达式"));
|
||||
}
|
||||
return Evaluate(ctx->lOrExp());
|
||||
}
|
||||
|
||||
std::any visitLVal(SysYParser::LValContext* ctx) override {
|
||||
if (!ctx || !ctx->Ident()) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法左值"));
|
||||
}
|
||||
const std::string name = ctx->Ident()->getText();
|
||||
const SymbolEntry* symbol = table_.Lookup(name);
|
||||
if (!symbol) {
|
||||
throw std::runtime_error(FormatError("consteval", "未定义符号: " + name));
|
||||
}
|
||||
if (!symbol->is_const && symbol->kind != SymbolKind::Constant) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "常量表达式中使用了非常量符号: " + name));
|
||||
}
|
||||
|
||||
const size_t index_count = ctx->exp().size();
|
||||
if (index_count == 0) {
|
||||
if (const ConstValue* scalar = values_.LookupScalar(name)) {
|
||||
return *scalar;
|
||||
}
|
||||
if (values_.LookupArray(name)) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组名不能作为标量常量参与求值: " + name));
|
||||
}
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "常量符号缺少编译期值: " + name));
|
||||
}
|
||||
|
||||
const ConstArrayValue* array = values_.LookupArray(name);
|
||||
if (!array) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "下标访问目标不是常量数组: " + name));
|
||||
}
|
||||
if (index_count != array->dims.size()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "常量数组索引维度不匹配: " + name));
|
||||
}
|
||||
|
||||
size_t linear_index = 0;
|
||||
for (size_t i = 0; i < index_count; ++i) {
|
||||
const ConstValue index_value = Evaluate(ctx->exp(i));
|
||||
const int64_t index = index_value.AsInt();
|
||||
const int64_t dim = array->dims[i];
|
||||
if (index < 0 || index >= dim) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "常量数组访问越界: " + name));
|
||||
}
|
||||
linear_index = linear_index * static_cast<size_t>(dim) +
|
||||
static_cast<size_t>(index);
|
||||
}
|
||||
|
||||
if (linear_index >= array->elements.size()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "常量数组线性索引越界: " + name));
|
||||
}
|
||||
return array->elements[linear_index];
|
||||
}
|
||||
|
||||
std::any visitPrimaryExp(SysYParser::PrimaryExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 primaryExp"));
|
||||
}
|
||||
if (ctx->exp()) {
|
||||
return Evaluate(ctx->exp());
|
||||
}
|
||||
if (ctx->lVal()) {
|
||||
return Evaluate(ctx->lVal());
|
||||
}
|
||||
if (ctx->number()) {
|
||||
return Evaluate(ctx->number());
|
||||
}
|
||||
throw std::runtime_error(FormatError("consteval", "无法识别的 primaryExp"));
|
||||
}
|
||||
|
||||
std::any visitNumber(SysYParser::NumberContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法数字节点"));
|
||||
}
|
||||
if (ctx->IntConst()) {
|
||||
return ConstValue::FromInt(ParseIntLiteral(ctx->IntConst()->getText()));
|
||||
}
|
||||
if (ctx->FloatConst()) {
|
||||
return ConstValue::FromFloat(
|
||||
ParseFloatLiteral(ctx->FloatConst()->getText()));
|
||||
}
|
||||
throw std::runtime_error(FormatError("consteval", "未知数字字面量类型"));
|
||||
}
|
||||
|
||||
std::any visitUnaryExp(SysYParser::UnaryExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 unaryExp"));
|
||||
}
|
||||
if (ctx->primaryExp()) {
|
||||
return Evaluate(ctx->primaryExp());
|
||||
}
|
||||
if (ctx->Ident()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "常量表达式中不允许函数调用: " +
|
||||
ctx->Ident()->getText()));
|
||||
}
|
||||
|
||||
if (!ctx->unaryOp() || !ctx->unaryExp()) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法一元表达式结构"));
|
||||
}
|
||||
const ConstValue operand = Evaluate(ctx->unaryExp());
|
||||
|
||||
if (ctx->unaryOp()->ADD()) {
|
||||
if (!operand.IsNumeric()) {
|
||||
throw std::runtime_error(FormatError("consteval", "一元加仅支持数值类型"));
|
||||
}
|
||||
if (operand.type == DataType::Float) {
|
||||
return ConstValue::FromFloat(+operand.AsFloat());
|
||||
}
|
||||
return ConstValue::FromInt(+operand.AsInt());
|
||||
}
|
||||
if (ctx->unaryOp()->SUB()) {
|
||||
if (!operand.IsNumeric()) {
|
||||
throw std::runtime_error(FormatError("consteval", "一元减仅支持数值类型"));
|
||||
}
|
||||
if (operand.type == DataType::Float) {
|
||||
return ConstValue::FromFloat(-operand.AsFloat());
|
||||
}
|
||||
return ConstValue::FromInt(-operand.AsInt());
|
||||
}
|
||||
if (ctx->unaryOp()->NOT()) {
|
||||
return ConstValue::FromBool(!operand.AsBool());
|
||||
}
|
||||
|
||||
throw std::runtime_error(FormatError("consteval", "未知一元运算符"));
|
||||
}
|
||||
|
||||
std::any visitMulExp(SysYParser::MulExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 mulExp"));
|
||||
}
|
||||
if (!ctx->mulExp()) {
|
||||
return Evaluate(ctx->unaryExp());
|
||||
}
|
||||
|
||||
const ConstValue lhs = Evaluate(ctx->mulExp());
|
||||
const ConstValue rhs = Evaluate(ctx->unaryExp());
|
||||
if (!lhs.IsNumeric() || !rhs.IsNumeric()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "乘除模运算只支持数值类型"));
|
||||
}
|
||||
|
||||
const int op = ctx->op ? ctx->op->getType() : 0;
|
||||
if (op == SysYParser::MUL) {
|
||||
if (lhs.type == DataType::Float || rhs.type == DataType::Float) {
|
||||
return ConstValue::FromFloat(lhs.AsFloat() * rhs.AsFloat());
|
||||
}
|
||||
return ConstValue::FromInt(lhs.AsInt() * rhs.AsInt());
|
||||
}
|
||||
if (op == SysYParser::DIV) {
|
||||
if (lhs.type == DataType::Float || rhs.type == DataType::Float) {
|
||||
const double divisor = rhs.AsFloat();
|
||||
if (divisor == 0.0) {
|
||||
throw std::runtime_error(FormatError("consteval", "浮点除零"));
|
||||
}
|
||||
return ConstValue::FromFloat(lhs.AsFloat() / divisor);
|
||||
}
|
||||
const int64_t divisor = rhs.AsInt();
|
||||
if (divisor == 0) {
|
||||
throw std::runtime_error(FormatError("consteval", "整数除零"));
|
||||
}
|
||||
return ConstValue::FromInt(lhs.AsInt() / divisor);
|
||||
}
|
||||
if (op == SysYParser::MOD) {
|
||||
if (lhs.type == DataType::Float || rhs.type == DataType::Float) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "取模运算不支持浮点类型"));
|
||||
}
|
||||
const int64_t divisor = rhs.AsInt();
|
||||
if (divisor == 0) {
|
||||
throw std::runtime_error(FormatError("consteval", "整数取模除零"));
|
||||
}
|
||||
return ConstValue::FromInt(lhs.AsInt() % divisor);
|
||||
}
|
||||
|
||||
throw std::runtime_error(FormatError("consteval", "未知乘法类运算符"));
|
||||
}
|
||||
|
||||
std::any visitAddExp(SysYParser::AddExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 addExp"));
|
||||
}
|
||||
if (!ctx->addExp()) {
|
||||
return Evaluate(ctx->mulExp());
|
||||
}
|
||||
|
||||
const ConstValue lhs = Evaluate(ctx->addExp());
|
||||
const ConstValue rhs = Evaluate(ctx->mulExp());
|
||||
if (!lhs.IsNumeric() || !rhs.IsNumeric()) {
|
||||
throw std::runtime_error(FormatError("consteval", "加减运算只支持数值类型"));
|
||||
}
|
||||
|
||||
const int op = ctx->op ? ctx->op->getType() : 0;
|
||||
if (op == SysYParser::ADD) {
|
||||
if (lhs.type == DataType::Float || rhs.type == DataType::Float) {
|
||||
return ConstValue::FromFloat(lhs.AsFloat() + rhs.AsFloat());
|
||||
}
|
||||
return ConstValue::FromInt(lhs.AsInt() + rhs.AsInt());
|
||||
}
|
||||
if (op == SysYParser::SUB) {
|
||||
if (lhs.type == DataType::Float || rhs.type == DataType::Float) {
|
||||
return ConstValue::FromFloat(lhs.AsFloat() - rhs.AsFloat());
|
||||
}
|
||||
return ConstValue::FromInt(lhs.AsInt() - rhs.AsInt());
|
||||
}
|
||||
|
||||
throw std::runtime_error(FormatError("consteval", "未知加法类运算符"));
|
||||
}
|
||||
|
||||
std::any visitRelExp(SysYParser::RelExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 relExp"));
|
||||
}
|
||||
if (!ctx->relExp()) {
|
||||
return Evaluate(ctx->addExp());
|
||||
}
|
||||
|
||||
const ConstValue lhs = Evaluate(ctx->relExp());
|
||||
const ConstValue rhs = Evaluate(ctx->addExp());
|
||||
if (!lhs.IsNumeric() || !rhs.IsNumeric()) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "关系比较仅支持数值类型"));
|
||||
}
|
||||
|
||||
const int op = ctx->op ? ctx->op->getType() : 0;
|
||||
if (lhs.type == DataType::Float || rhs.type == DataType::Float) {
|
||||
const double left = lhs.AsFloat();
|
||||
const double right = rhs.AsFloat();
|
||||
if (op == SysYParser::LT) {
|
||||
return ConstValue::FromBool(left < right);
|
||||
}
|
||||
if (op == SysYParser::GT) {
|
||||
return ConstValue::FromBool(left > right);
|
||||
}
|
||||
if (op == SysYParser::LE) {
|
||||
return ConstValue::FromBool(left <= right);
|
||||
}
|
||||
if (op == SysYParser::GE) {
|
||||
return ConstValue::FromBool(left >= right);
|
||||
}
|
||||
} else {
|
||||
const int64_t left = lhs.AsInt();
|
||||
const int64_t right = rhs.AsInt();
|
||||
if (op == SysYParser::LT) {
|
||||
return ConstValue::FromBool(left < right);
|
||||
}
|
||||
if (op == SysYParser::GT) {
|
||||
return ConstValue::FromBool(left > right);
|
||||
}
|
||||
if (op == SysYParser::LE) {
|
||||
return ConstValue::FromBool(left <= right);
|
||||
}
|
||||
if (op == SysYParser::GE) {
|
||||
return ConstValue::FromBool(left >= right);
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error(FormatError("consteval", "未知关系比较运算符"));
|
||||
}
|
||||
|
||||
std::any visitEqExp(SysYParser::EqExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 eqExp"));
|
||||
}
|
||||
if (!ctx->eqExp()) {
|
||||
return Evaluate(ctx->relExp());
|
||||
}
|
||||
|
||||
const ConstValue lhs = Evaluate(ctx->eqExp());
|
||||
const ConstValue rhs = Evaluate(ctx->relExp());
|
||||
|
||||
const int op = ctx->op ? ctx->op->getType() : 0;
|
||||
bool result = false;
|
||||
if (lhs.type == DataType::Float || rhs.type == DataType::Float) {
|
||||
const double left = lhs.AsFloat();
|
||||
const double right = rhs.AsFloat();
|
||||
if (op == SysYParser::EQ) {
|
||||
result = (left == right);
|
||||
} else if (op == SysYParser::NE) {
|
||||
result = (left != right);
|
||||
} else {
|
||||
throw std::runtime_error(FormatError("consteval", "未知相等比较运算符"));
|
||||
}
|
||||
} else {
|
||||
const int64_t left = lhs.AsInt();
|
||||
const int64_t right = rhs.AsInt();
|
||||
if (op == SysYParser::EQ) {
|
||||
result = (left == right);
|
||||
} else if (op == SysYParser::NE) {
|
||||
result = (left != right);
|
||||
} else {
|
||||
throw std::runtime_error(FormatError("consteval", "未知相等比较运算符"));
|
||||
}
|
||||
}
|
||||
return ConstValue::FromBool(result);
|
||||
}
|
||||
|
||||
std::any visitLAndExp(SysYParser::LAndExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 lAndExp"));
|
||||
}
|
||||
if (!ctx->lAndExp()) {
|
||||
return ConstValue::FromBool(Evaluate(ctx->eqExp()).AsBool());
|
||||
}
|
||||
|
||||
const ConstValue lhs = Evaluate(ctx->lAndExp());
|
||||
if (!lhs.AsBool()) {
|
||||
return ConstValue::FromBool(false);
|
||||
}
|
||||
const ConstValue rhs = Evaluate(ctx->eqExp());
|
||||
return ConstValue::FromBool(rhs.AsBool());
|
||||
}
|
||||
|
||||
std::any visitLOrExp(SysYParser::LOrExpContext* ctx) override {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "非法 lOrExp"));
|
||||
}
|
||||
if (!ctx->lOrExp()) {
|
||||
return ConstValue::FromBool(Evaluate(ctx->lAndExp()).AsBool());
|
||||
}
|
||||
|
||||
const ConstValue lhs = Evaluate(ctx->lOrExp());
|
||||
if (lhs.AsBool()) {
|
||||
return ConstValue::FromBool(true);
|
||||
}
|
||||
const ConstValue rhs = Evaluate(ctx->lAndExp());
|
||||
return ConstValue::FromBool(rhs.AsBool());
|
||||
}
|
||||
|
||||
private:
|
||||
ConstValue Evaluate(antlr4::ParserRuleContext* ctx) {
|
||||
if (!ctx) {
|
||||
throw std::runtime_error(FormatError("consteval", "空表达式节点"));
|
||||
}
|
||||
std::any result = ctx->accept(this);
|
||||
try {
|
||||
return std::any_cast<ConstValue>(result);
|
||||
} catch (const std::bad_any_cast&) {
|
||||
throw std::runtime_error(FormatError("consteval", "常量求值类型转换失败"));
|
||||
}
|
||||
}
|
||||
|
||||
const SymbolTable& table_;
|
||||
const ConstEvalContext& values_;
|
||||
};
|
||||
|
||||
ConstValue EvaluateScalarInit(SysYParser::ConstInitValContext& init,
|
||||
DataType elem_type,
|
||||
ConstEvalVisitor& evaluator) {
|
||||
if (init.constExp()) {
|
||||
return CastToType(evaluator.EvaluateConstExp(*init.constExp()), elem_type);
|
||||
}
|
||||
if (init.constInitVal().empty()) {
|
||||
return MakeZeroValue(elem_type);
|
||||
}
|
||||
if (init.constInitVal().size() == 1) {
|
||||
return EvaluateScalarInit(*init.constInitVal().front(), elem_type,
|
||||
evaluator);
|
||||
}
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "标量初始化含有过多元素"));
|
||||
}
|
||||
|
||||
void FillConstArrayObject(SysYParser::ConstInitValContext& init,
|
||||
size_t depth, size_t base, size_t span,
|
||||
const std::vector<int64_t>& dims, DataType elem_type,
|
||||
std::vector<ConstValue>& out,
|
||||
ConstEvalVisitor& evaluator) {
|
||||
if (depth >= dims.size()) {
|
||||
out[base] = EvaluateScalarInit(init, elem_type, evaluator);
|
||||
return;
|
||||
}
|
||||
|
||||
if (init.constExp()) {
|
||||
out[base] = CastToType(evaluator.EvaluateConstExp(*init.constExp()),
|
||||
elem_type);
|
||||
return;
|
||||
}
|
||||
|
||||
if (init.constInitVal().empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t end = base + span;
|
||||
size_t cursor = base;
|
||||
const size_t subspan = (depth + 1 < dims.size()) ? Product(dims, depth + 1)
|
||||
: static_cast<size_t>(1);
|
||||
|
||||
for (auto* child : init.constInitVal()) {
|
||||
if (!child) {
|
||||
continue;
|
||||
}
|
||||
if (cursor >= end) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组初始化元素过多"));
|
||||
}
|
||||
|
||||
if (depth + 1 >= dims.size()) {
|
||||
out[cursor] = EvaluateScalarInit(*child, elem_type, evaluator);
|
||||
++cursor;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (child->constExp()) {
|
||||
out[cursor] = CastToType(evaluator.EvaluateConstExp(*child->constExp()),
|
||||
elem_type);
|
||||
++cursor;
|
||||
continue;
|
||||
}
|
||||
|
||||
const size_t rel = cursor - base;
|
||||
if (subspan > 1 && rel % subspan != 0) {
|
||||
cursor += (subspan - (rel % subspan));
|
||||
}
|
||||
if (cursor >= end) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组初始化嵌套层级与维度不匹配"));
|
||||
}
|
||||
|
||||
FillConstArrayObject(*child, depth + 1, cursor, subspan, dims, elem_type,
|
||||
out, evaluator);
|
||||
cursor += subspan;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
ConstValue ConstValue::FromInt(int64_t value) {
|
||||
ConstValue result;
|
||||
result.type = SymbolDataType::Int;
|
||||
result.int_value = value;
|
||||
result.float_value = static_cast<double>(value);
|
||||
result.bool_value = (value != 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
ConstValue ConstValue::FromFloat(double value) {
|
||||
ConstValue result;
|
||||
result.type = SymbolDataType::Float;
|
||||
result.int_value = static_cast<int64_t>(value);
|
||||
result.float_value = value;
|
||||
result.bool_value = (value != 0.0);
|
||||
return result;
|
||||
}
|
||||
|
||||
ConstValue ConstValue::FromBool(bool value) {
|
||||
ConstValue result;
|
||||
result.type = SymbolDataType::Bool;
|
||||
result.int_value = value ? 1 : 0;
|
||||
result.float_value = value ? 1.0 : 0.0;
|
||||
result.bool_value = value;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ConstValue::IsScalar() const { return type != SymbolDataType::Unknown; }
|
||||
|
||||
bool ConstValue::IsNumeric() const {
|
||||
return type == SymbolDataType::Int || type == SymbolDataType::Float ||
|
||||
type == SymbolDataType::Bool;
|
||||
}
|
||||
|
||||
int64_t ConstValue::AsInt() const {
|
||||
if (type == SymbolDataType::Int) {
|
||||
return int_value;
|
||||
}
|
||||
if (type == SymbolDataType::Float) {
|
||||
return static_cast<int64_t>(float_value);
|
||||
}
|
||||
if (type == SymbolDataType::Bool) {
|
||||
return bool_value ? 1 : 0;
|
||||
}
|
||||
throw std::runtime_error(FormatError("consteval", "当前值不能转为整数"));
|
||||
}
|
||||
|
||||
double ConstValue::AsFloat() const {
|
||||
if (type == SymbolDataType::Float) {
|
||||
return float_value;
|
||||
}
|
||||
if (type == SymbolDataType::Int) {
|
||||
return static_cast<double>(int_value);
|
||||
}
|
||||
if (type == SymbolDataType::Bool) {
|
||||
return bool_value ? 1.0 : 0.0;
|
||||
}
|
||||
throw std::runtime_error(FormatError("consteval", "当前值不能转为浮点数"));
|
||||
}
|
||||
|
||||
bool ConstValue::AsBool() const {
|
||||
if (type == SymbolDataType::Bool) {
|
||||
return bool_value;
|
||||
}
|
||||
if (type == SymbolDataType::Int) {
|
||||
return int_value != 0;
|
||||
}
|
||||
if (type == SymbolDataType::Float) {
|
||||
return float_value != 0.0;
|
||||
}
|
||||
throw std::runtime_error(FormatError("consteval", "当前值不能转为布尔值"));
|
||||
}
|
||||
|
||||
ConstEvalContext::ConstEvalContext() { EnterScope(); }
|
||||
|
||||
void ConstEvalContext::EnterScope() { scopes_.emplace_back(); }
|
||||
|
||||
void ConstEvalContext::ExitScope() {
|
||||
if (scopes_.size() <= 1) {
|
||||
throw std::runtime_error("const eval scope underflow");
|
||||
}
|
||||
scopes_.pop_back();
|
||||
}
|
||||
|
||||
bool ConstEvalContext::DefineScalar(const std::string& name, ConstValue value) {
|
||||
if (scopes_.empty()) {
|
||||
EnterScope();
|
||||
}
|
||||
auto& current = scopes_.back();
|
||||
if (current.find(name) != current.end()) {
|
||||
return false;
|
||||
}
|
||||
Binding binding;
|
||||
binding.is_array = false;
|
||||
binding.scalar = std::move(value);
|
||||
current.emplace(name, std::move(binding));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ConstEvalContext::DefineArray(const std::string& name,
|
||||
ConstArrayValue value) {
|
||||
if (scopes_.empty()) {
|
||||
EnterScope();
|
||||
}
|
||||
auto& current = scopes_.back();
|
||||
if (current.find(name) != current.end()) {
|
||||
return false;
|
||||
}
|
||||
Binding binding;
|
||||
binding.is_array = true;
|
||||
binding.array = std::move(value);
|
||||
current.emplace(name, std::move(binding));
|
||||
return true;
|
||||
}
|
||||
|
||||
const ConstValue* ConstEvalContext::LookupScalar(const std::string& name) const {
|
||||
const Binding* binding = LookupBinding(name);
|
||||
if (!binding || binding->is_array) {
|
||||
return nullptr;
|
||||
}
|
||||
return &binding->scalar;
|
||||
}
|
||||
|
||||
const ConstArrayValue* ConstEvalContext::LookupArray(
|
||||
const std::string& name) const {
|
||||
const Binding* binding = LookupBinding(name);
|
||||
if (!binding || !binding->is_array) {
|
||||
return nullptr;
|
||||
}
|
||||
return &binding->array;
|
||||
}
|
||||
|
||||
const ConstEvalContext::Binding* ConstEvalContext::LookupBinding(
|
||||
const std::string& name) const {
|
||||
for (auto it = scopes_.rbegin(); it != scopes_.rend(); ++it) {
|
||||
auto found = it->find(name);
|
||||
if (found != it->end()) {
|
||||
return &found->second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ConstEvaluator::ConstEvaluator(const SymbolTable& table,
|
||||
const ConstEvalContext& ctx)
|
||||
: table_(table), ctx_(ctx) {}
|
||||
|
||||
ConstValue ConstEvaluator::EvaluateConstExp(
|
||||
SysYParser::ConstExpContext& ctx) const {
|
||||
ConstEvalVisitor visitor(table_, ctx_);
|
||||
return visitor.EvaluateConstExp(ctx);
|
||||
}
|
||||
|
||||
ConstValue ConstEvaluator::EvaluateExp(SysYParser::ExpContext& ctx) const {
|
||||
ConstEvalVisitor visitor(table_, ctx_);
|
||||
return visitor.EvaluateExp(ctx);
|
||||
}
|
||||
|
||||
int64_t ConstEvaluator::EvaluateArrayDim(
|
||||
SysYParser::ConstExpContext& ctx) const {
|
||||
const ConstValue value = EvaluateConstExp(ctx);
|
||||
if (!IsNumericType(value.type)) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组维度必须是数值类型"));
|
||||
}
|
||||
|
||||
if (value.type == DataType::Float) {
|
||||
const double as_float = value.AsFloat();
|
||||
if (std::trunc(as_float) != as_float) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组维度必须是整数"));
|
||||
}
|
||||
}
|
||||
|
||||
const int64_t dim = value.AsInt();
|
||||
if (dim <= 0) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "数组维度必须是正整数"));
|
||||
}
|
||||
return dim;
|
||||
}
|
||||
|
||||
std::vector<ConstValue> ConstEvaluator::EvaluateConstInitList(
|
||||
SysYParser::ConstInitValContext& init, SymbolDataType elem_type,
|
||||
const std::vector<int64_t>& dims) const {
|
||||
if (elem_type != DataType::Int && elem_type != DataType::Float &&
|
||||
elem_type != DataType::Bool) {
|
||||
throw std::runtime_error(
|
||||
FormatError("consteval", "仅支持标量类型的常量初始化"));
|
||||
}
|
||||
|
||||
ConstEvalVisitor visitor(table_, ctx_);
|
||||
if (dims.empty()) {
|
||||
return {EvaluateScalarInit(init, elem_type, visitor)};
|
||||
}
|
||||
|
||||
const size_t total = Product(dims, 0);
|
||||
std::vector<ConstValue> flattened(total, MakeZeroValue(elem_type));
|
||||
FillConstArrayObject(init, 0, 0, total, dims, elem_type, flattened, visitor);
|
||||
return flattened;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue