提示词:
对标 LinuxCNC,分阶段完善 Web 版数控系统仿真的 WASM 程序,继续补齐 G 代码语法并严格测试。 总结: - 对齐 LinuxCNC 对同一行重复非 G/M 字的拒绝行为,覆盖 G1 X1 X2 等重复轴字错误。 - 将 smoke parser 字母字归一为大写,补充 lowercase 普通字和命名 O-word 回归覆盖。 - 已通过 ./test-native.sh 和 ./test-linuxcnc-source-link.sh。
This commit is contained in:
@@ -354,13 +354,14 @@ bool looks_like_real_start(char ch) {
|
|||||||
|
|
||||||
bool parse_word_list_impl(const std::string &line, std::vector<Word> *words, std::string *error, bool strict) {
|
bool parse_word_list_impl(const std::string &line, std::vector<Word> *words, std::string *error, bool strict) {
|
||||||
words->clear();
|
words->clear();
|
||||||
|
std::array<bool, 26> seen_letters{};
|
||||||
const char *text = line.c_str();
|
const char *text = line.c_str();
|
||||||
for (size_t i = 0; text[i] != '\0';) {
|
for (size_t i = 0; text[i] != '\0';) {
|
||||||
if (std::isspace(static_cast<unsigned char>(text[i]))) {
|
if (std::isspace(static_cast<unsigned char>(text[i]))) {
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
char letter = text[i];
|
char letter = static_cast<char>(std::toupper(static_cast<unsigned char>(text[i])));
|
||||||
if (!std::isalpha(static_cast<unsigned char>(letter))) {
|
if (!std::isalpha(static_cast<unsigned char>(letter))) {
|
||||||
++i;
|
++i;
|
||||||
continue;
|
continue;
|
||||||
@@ -391,6 +392,16 @@ bool parse_word_list_impl(const std::string &line, std::vector<Word> *words, std
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (letter != 'G' && letter != 'M') {
|
||||||
|
const size_t letter_index = static_cast<size_t>(letter - 'A');
|
||||||
|
if (strict && seen_letters[letter_index]) {
|
||||||
|
if (error) {
|
||||||
|
*error = "multiple " + std::string(1, letter) + " words on one line";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
seen_letters[letter_index] = true;
|
||||||
|
}
|
||||||
words->push_back({letter, value});
|
words->push_back({letter, value});
|
||||||
i = next;
|
i = next;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -242,6 +242,8 @@ int main() {
|
|||||||
bool saw_global_low_parameter_after_oword = false;
|
bool saw_global_low_parameter_after_oword = false;
|
||||||
bool saw_named_oword_call = false;
|
bool saw_named_oword_call = false;
|
||||||
bool saw_named_oword_return = false;
|
bool saw_named_oword_return = false;
|
||||||
|
bool saw_lowercase_named_oword_call = false;
|
||||||
|
bool saw_lowercase_named_oword_return = false;
|
||||||
bool saw_named_parameter_reference = false;
|
bool saw_named_parameter_reference = false;
|
||||||
bool saw_named_parameter_call_arg = false;
|
bool saw_named_parameter_call_arg = false;
|
||||||
bool saw_named_parameter_local = false;
|
bool saw_named_parameter_local = false;
|
||||||
@@ -274,6 +276,7 @@ int main() {
|
|||||||
bool saw_word_unary_function_motion = false;
|
bool saw_word_unary_function_motion = false;
|
||||||
bool saw_word_atan_function_motion = false;
|
bool saw_word_atan_function_motion = false;
|
||||||
bool saw_signed_word_unary_function_motion = false;
|
bool saw_signed_word_unary_function_motion = false;
|
||||||
|
bool saw_lowercase_motion = false;
|
||||||
bool saw_trig_function_motion = false;
|
bool saw_trig_function_motion = false;
|
||||||
bool saw_inverse_trig_function_motion = false;
|
bool saw_inverse_trig_function_motion = false;
|
||||||
bool saw_atan_function_motion = false;
|
bool saw_atan_function_motion = false;
|
||||||
@@ -3030,6 +3033,41 @@ int main() {
|
|||||||
ok &= expect(saw_named_oword_call, "expected named O-word subprogram call");
|
ok &= expect(saw_named_oword_call, "expected named O-word subprogram call");
|
||||||
ok &= expect(saw_named_oword_return, "expected named O-word return to caller");
|
ok &= expect(saw_named_oword_return, "expected named O-word return to caller");
|
||||||
|
|
||||||
|
const char lowercase_named_oword_subprogram[] =
|
||||||
|
"g21 g90\n"
|
||||||
|
"g0 x0 y0 z0\n"
|
||||||
|
"f100\n"
|
||||||
|
"o<lower_named> call [5]\n"
|
||||||
|
"g1 y3\n"
|
||||||
|
"m30\n"
|
||||||
|
"o<lower_named> sub\n"
|
||||||
|
"g1 x#1\n"
|
||||||
|
"o<lower_named> return\n"
|
||||||
|
"g1 x99\n"
|
||||||
|
"o<lower_named> endsub\n";
|
||||||
|
events.clear();
|
||||||
|
ok &= expect(cnc_sim_parse_program(sim,
|
||||||
|
lowercase_named_oword_subprogram,
|
||||||
|
sizeof(lowercase_named_oword_subprogram) - 1) == 0,
|
||||||
|
cnc_sim_last_error(sim));
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_lowercase_named_oword_call = saw_lowercase_named_oword_call ||
|
||||||
|
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||||
|
event.line == 8 &&
|
||||||
|
event.end.x == 5.0);
|
||||||
|
saw_lowercase_named_oword_return = saw_lowercase_named_oword_return ||
|
||||||
|
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||||
|
event.line == 5 &&
|
||||||
|
event.start.x == 5.0 &&
|
||||||
|
event.end.y == 3.0);
|
||||||
|
ok &= expect(!(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||||
|
event.line == 10 &&
|
||||||
|
event.end.x == 99.0),
|
||||||
|
"expected lowercase named O-word return to skip remaining subprogram body");
|
||||||
|
}
|
||||||
|
ok &= expect(saw_lowercase_named_oword_call, "expected lowercase named O-word subprogram call");
|
||||||
|
ok &= expect(saw_lowercase_named_oword_return, "expected lowercase named O-word return to caller");
|
||||||
|
|
||||||
const char named_parameter_program[] =
|
const char named_parameter_program[] =
|
||||||
"#<target> = 5\n"
|
"#<target> = 5\n"
|
||||||
"#<step> = [#<target> + 2]\n"
|
"#<step> = [#<target> + 2]\n"
|
||||||
@@ -3524,6 +3562,16 @@ int main() {
|
|||||||
sizeof(g1_without_feed_program) - 1) != 0,
|
sizeof(g1_without_feed_program) - 1) != 0,
|
||||||
"expected LinuxCNC to reject G1 with zero feed rate");
|
"expected LinuxCNC to reject G1 with zero feed rate");
|
||||||
|
|
||||||
|
const char duplicate_axis_word_program[] =
|
||||||
|
"G21 G90\n"
|
||||||
|
"F100\n"
|
||||||
|
"G1 X1 X2\n";
|
||||||
|
events.clear();
|
||||||
|
ok &= expect(cnc_sim_parse_program(sim,
|
||||||
|
duplicate_axis_word_program,
|
||||||
|
sizeof(duplicate_axis_word_program) - 1) != 0,
|
||||||
|
"expected LinuxCNC to reject multiple X words on one line");
|
||||||
|
|
||||||
const char scientific_notation_word_program[] =
|
const char scientific_notation_word_program[] =
|
||||||
"G21 G90\n"
|
"G21 G90\n"
|
||||||
"F100\n"
|
"F100\n"
|
||||||
@@ -3597,6 +3645,23 @@ int main() {
|
|||||||
ok &= expect(saw_word_atan_function_motion, "expected LinuxCNC ATAN function as a word value");
|
ok &= expect(saw_word_atan_function_motion, "expected LinuxCNC ATAN function as a word value");
|
||||||
ok &= expect(saw_signed_word_unary_function_motion, "expected signed LinuxCNC unary function as a word value");
|
ok &= expect(saw_signed_word_unary_function_motion, "expected signed LinuxCNC unary function as a word value");
|
||||||
|
|
||||||
|
const char lowercase_word_program[] =
|
||||||
|
"g21 g90\n"
|
||||||
|
"f100\n"
|
||||||
|
"g1 x3\n";
|
||||||
|
events.clear();
|
||||||
|
ok &= expect(cnc_sim_parse_program(sim,
|
||||||
|
lowercase_word_program,
|
||||||
|
sizeof(lowercase_word_program) - 1) == 0,
|
||||||
|
cnc_sim_last_error(sim));
|
||||||
|
for (const auto &event : events) {
|
||||||
|
saw_lowercase_motion = saw_lowercase_motion ||
|
||||||
|
(event.type == CNC_SIM_EVENT_LINEAR_FEED &&
|
||||||
|
event.line == 3 &&
|
||||||
|
event.end.x == 3.0);
|
||||||
|
}
|
||||||
|
ok &= expect(saw_lowercase_motion, "expected LinuxCNC lowercase word parsing");
|
||||||
|
|
||||||
const char additional_math_function_program[] =
|
const char additional_math_function_program[] =
|
||||||
"#1 = [ASIN[0.5] + ACOS[0.5]]\n"
|
"#1 = [ASIN[0.5] + ACOS[0.5]]\n"
|
||||||
"#2 = [FIX[1.9] + FUP[1.1] + ROUND[-1.5]]\n"
|
"#2 = [FIX[1.9] + FUP[1.1] + ROUND[-1.5]]\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user