步骤1:VAR_TEMP 词法+语法支持(token/关键字/VarSection::Temp/保留字放行)+ 测试
This commit is contained in:
@@ -35,6 +35,7 @@ namespace compiler {
|
|||||||
VAR_OUTPUT, ///< 输出变量段起始
|
VAR_OUTPUT, ///< 输出变量段起始
|
||||||
VAR_GLOBAL, ///< 全局变量段起始
|
VAR_GLOBAL, ///< 全局变量段起始
|
||||||
VAR_EXTERNAL, ///< 外部变量段起始
|
VAR_EXTERNAL, ///< 外部变量段起始
|
||||||
|
VAR_TEMP, ///< 临时变量段起始(VAR_TEMP)
|
||||||
END_VAR, ///< 变量段结束
|
END_VAR, ///< 变量段结束
|
||||||
BOOL, ///< 布尔类型
|
BOOL, ///< 布尔类型
|
||||||
BYTE, ///< 位串类型(8 位)
|
BYTE, ///< 位串类型(8 位)
|
||||||
|
|||||||
@@ -53,9 +53,9 @@ namespace compiler {
|
|||||||
/**
|
/**
|
||||||
* @brief 变量段种类。
|
* @brief 变量段种类。
|
||||||
* @details 枚举值:Local=VAR、Input=VAR_INPUT、Output=VAR_OUTPUT、
|
* @details 枚举值:Local=VAR、Input=VAR_INPUT、Output=VAR_OUTPUT、
|
||||||
* Global=VAR_GLOBAL、External=VAR_EXTERNAL。
|
* Global=VAR_GLOBAL、External=VAR_EXTERNAL、Temp=VAR_TEMP。
|
||||||
*/
|
*/
|
||||||
enum class VarSection { Local, Input, Output, Global, External };
|
enum class VarSection { Local, Input, Output, Global, External, Temp };
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 一段 VAR_* … END_VAR:段种类 + 声明列表。
|
* @brief 一段 VAR_* … END_VAR:段种类 + 声明列表。
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ namespace {
|
|||||||
{"var_output", Tok::VAR_OUTPUT},
|
{"var_output", Tok::VAR_OUTPUT},
|
||||||
{"var_global", Tok::VAR_GLOBAL},
|
{"var_global", Tok::VAR_GLOBAL},
|
||||||
{"var_external", Tok::VAR_EXTERNAL},
|
{"var_external", Tok::VAR_EXTERNAL},
|
||||||
|
{"var_temp", Tok::VAR_TEMP},
|
||||||
{"end_var", Tok::END_VAR},
|
{"end_var", Tok::END_VAR},
|
||||||
// 类型(V2:19 种 IEC 类型)
|
// 类型(V2:19 种 IEC 类型)
|
||||||
{"bool", Tok::BOOL},
|
{"bool", Tok::BOOL},
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace {
|
|||||||
* 用户标识符(详见 Doc/compiler/语法.md)。
|
* 用户标识符(详见 Doc/compiler/语法.md)。
|
||||||
*/
|
*/
|
||||||
const char* const kForbidden[] = {
|
const char* const kForbidden[] = {
|
||||||
"var_in_out", "var_temp", "ref", "class", "any",
|
"var_in_out", "ref", "class", "any",
|
||||||
"pointer", "interface", "method",
|
"pointer", "interface", "method",
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -306,8 +306,8 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief 当前 token 是否为五种变量段关键字之一
|
* @brief 当前 token 是否为六种变量段关键字之一
|
||||||
* @return true 为 VAR / VAR_INPUT / VAR_OUTPUT / VAR_GLOBAL / VAR_EXTERNAL
|
* @return true 为 VAR / VAR_INPUT / VAR_OUTPUT / VAR_GLOBAL / VAR_EXTERNAL / VAR_TEMP
|
||||||
*/
|
*/
|
||||||
bool is_var_section() const {
|
bool is_var_section() const {
|
||||||
switch (type()) {
|
switch (type()) {
|
||||||
@@ -316,6 +316,7 @@ namespace {
|
|||||||
case Tok::VAR_OUTPUT:
|
case Tok::VAR_OUTPUT:
|
||||||
case Tok::VAR_GLOBAL:
|
case Tok::VAR_GLOBAL:
|
||||||
case Tok::VAR_EXTERNAL:
|
case Tok::VAR_EXTERNAL:
|
||||||
|
case Tok::VAR_TEMP:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
@@ -358,6 +359,7 @@ namespace {
|
|||||||
case Tok::VAR_OUTPUT: b->section = VarSection::Output; break;
|
case Tok::VAR_OUTPUT: b->section = VarSection::Output; break;
|
||||||
case Tok::VAR_GLOBAL: b->section = VarSection::Global; break;
|
case Tok::VAR_GLOBAL: b->section = VarSection::Global; break;
|
||||||
case Tok::VAR_EXTERNAL: b->section = VarSection::External; break;
|
case Tok::VAR_EXTERNAL: b->section = VarSection::External; break;
|
||||||
|
case Tok::VAR_TEMP: b->section = VarSection::Temp; break;
|
||||||
default:
|
default:
|
||||||
return fail("expected variable section");
|
return fail("expected variable section");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -197,7 +197,18 @@ static bool test_line1() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool test_var_temp_kw() {
|
||||||
|
using namespace compiler;
|
||||||
|
std::vector<Token> ts;
|
||||||
|
std::string err;
|
||||||
|
CHECK(lex("t.st", "VAR_TEMP", &ts, &err));
|
||||||
|
CHECK(!ts.empty());
|
||||||
|
CHECK(ts[0].type == Tok::VAR_TEMP);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
if (!test_var_temp_kw()) return 1;
|
||||||
if (!test_basic()) return 1;
|
if (!test_basic()) return 1;
|
||||||
if (!test_case()) return 1;
|
if (!test_case()) return 1;
|
||||||
if (!test_symbols()) return 1;
|
if (!test_symbols()) return 1;
|
||||||
|
|||||||
@@ -289,7 +289,38 @@ static bool test_negative() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- VAR_TEMP 段:解析为 VarSection::Temp ----
|
||||||
|
|
||||||
|
static bool test_var_temp() {
|
||||||
|
using namespace compiler;
|
||||||
|
Unit u;
|
||||||
|
std::string err;
|
||||||
|
CHECK(parse_pous("t.st",
|
||||||
|
"FUNCTION_BLOCK Foo\n"
|
||||||
|
"VAR_INPUT\n in : BOOL;\nEND_VAR\n"
|
||||||
|
"VAR_OUTPUT\n out : BOOL;\nEND_VAR\n"
|
||||||
|
"VAR\n state : BOOL;\nEND_VAR\n"
|
||||||
|
"VAR_TEMP\n tmp : INT;\nEND_VAR\n"
|
||||||
|
" out := tmp > 0;\n"
|
||||||
|
"END_FUNCTION_BLOCK",
|
||||||
|
&u, &err));
|
||||||
|
CHECK(u.pous.size() == 1);
|
||||||
|
const POU& p = u.pous[0];
|
||||||
|
CHECK(p.kind == PouKind::FunctionBlock);
|
||||||
|
CHECK(p.blocks.size() == 4);
|
||||||
|
CHECK(p.blocks[0].section == VarSection::Input);
|
||||||
|
CHECK(p.blocks[1].section == VarSection::Output);
|
||||||
|
CHECK(p.blocks[2].section == VarSection::Local);
|
||||||
|
CHECK(p.blocks[3].section == VarSection::Temp);
|
||||||
|
CHECK(p.blocks[3].vars.size() == 1);
|
||||||
|
CHECK(p.blocks[3].vars[0].name == "tmp");
|
||||||
|
CHECK(p.blocks[3].vars[0].type.kind == TypeKind::Scalar);
|
||||||
|
CHECK(p.blocks[3].vars[0].type.name == "int");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
if (!test_var_temp()) return 1;
|
||||||
if (!test_gvl_file()) return 1;
|
if (!test_gvl_file()) return 1;
|
||||||
if (!test_fb()) return 1;
|
if (!test_fb()) return 1;
|
||||||
if (!test_program()) return 1;
|
if (!test_program()) return 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user