提示词:
对标 LinuxCNC,分阶段完善 Web 版数控系统仿真的 WASM 程序,继续补齐 G/M 代码语法并严格测试。 总结: 按 LinuxCNC read_g/read_m 的模态组规则,补充同一行同模态组 G/M 码冲突检查;新增 G0 G1 与 M3 M4 拒绝用例。已通过 ./test-native.sh 和 ./test-linuxcnc-source-link.sh。
This commit is contained in:
@@ -495,6 +495,187 @@ bool has_m_code(const std::vector<Word> &word_list, int code) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int linuxcnc_g_code_number(double value) {
|
||||||
|
const double scaled = value * 10.0;
|
||||||
|
int code = static_cast<int>(std::floor(scaled));
|
||||||
|
const double fraction = scaled - static_cast<double>(code);
|
||||||
|
if (fraction > 0.999) {
|
||||||
|
code = static_cast<int>(std::ceil(scaled));
|
||||||
|
}
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
int supported_linuxcnc_g_modal_group(double value) {
|
||||||
|
const int code = linuxcnc_g_code_number(value);
|
||||||
|
switch (code) {
|
||||||
|
case 0:
|
||||||
|
case 10:
|
||||||
|
case 20:
|
||||||
|
case 30:
|
||||||
|
case 300:
|
||||||
|
case 500:
|
||||||
|
case 510:
|
||||||
|
case 520:
|
||||||
|
case 610:
|
||||||
|
case 620:
|
||||||
|
case 700:
|
||||||
|
case 710:
|
||||||
|
case 720:
|
||||||
|
case 730:
|
||||||
|
case 740:
|
||||||
|
case 760:
|
||||||
|
case 800:
|
||||||
|
case 810:
|
||||||
|
case 820:
|
||||||
|
case 830:
|
||||||
|
case 840:
|
||||||
|
case 850:
|
||||||
|
case 860:
|
||||||
|
case 870:
|
||||||
|
case 880:
|
||||||
|
case 890:
|
||||||
|
return 1;
|
||||||
|
case 170:
|
||||||
|
case 180:
|
||||||
|
case 190:
|
||||||
|
return 2;
|
||||||
|
case 900:
|
||||||
|
case 910:
|
||||||
|
return 3;
|
||||||
|
case 901:
|
||||||
|
case 911:
|
||||||
|
return 4;
|
||||||
|
case 930:
|
||||||
|
case 940:
|
||||||
|
case 950:
|
||||||
|
return 5;
|
||||||
|
case 200:
|
||||||
|
case 210:
|
||||||
|
case 7000:
|
||||||
|
case 7100:
|
||||||
|
return 6;
|
||||||
|
case 400:
|
||||||
|
case 410:
|
||||||
|
case 411:
|
||||||
|
case 420:
|
||||||
|
case 421:
|
||||||
|
return 7;
|
||||||
|
case 430:
|
||||||
|
case 431:
|
||||||
|
case 432:
|
||||||
|
case 434:
|
||||||
|
case 435:
|
||||||
|
case 490:
|
||||||
|
return 8;
|
||||||
|
case 980:
|
||||||
|
case 990:
|
||||||
|
return 10;
|
||||||
|
case 540:
|
||||||
|
case 550:
|
||||||
|
case 560:
|
||||||
|
case 570:
|
||||||
|
case 580:
|
||||||
|
case 590:
|
||||||
|
case 591:
|
||||||
|
case 592:
|
||||||
|
case 593:
|
||||||
|
return 12;
|
||||||
|
case 611:
|
||||||
|
case 640:
|
||||||
|
return 13;
|
||||||
|
case 960:
|
||||||
|
case 970:
|
||||||
|
return 14;
|
||||||
|
case 70:
|
||||||
|
case 80:
|
||||||
|
return 15;
|
||||||
|
case 922:
|
||||||
|
case 923:
|
||||||
|
return 16;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int supported_linuxcnc_m_modal_group(int value) {
|
||||||
|
if (value >= 100 && value <= 199) {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
switch (value) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
case 2:
|
||||||
|
case 30:
|
||||||
|
case 60:
|
||||||
|
case 99:
|
||||||
|
return 4;
|
||||||
|
case 62:
|
||||||
|
case 63:
|
||||||
|
case 64:
|
||||||
|
case 65:
|
||||||
|
case 66:
|
||||||
|
return 5;
|
||||||
|
case 6:
|
||||||
|
case 61:
|
||||||
|
return 6;
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
case 19:
|
||||||
|
case 70:
|
||||||
|
case 71:
|
||||||
|
case 72:
|
||||||
|
case 73:
|
||||||
|
return 7;
|
||||||
|
case 7:
|
||||||
|
case 8:
|
||||||
|
case 9:
|
||||||
|
return 8;
|
||||||
|
case 48:
|
||||||
|
case 49:
|
||||||
|
case 50:
|
||||||
|
case 51:
|
||||||
|
case 52:
|
||||||
|
case 53:
|
||||||
|
return 9;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check_linuxcnc_modal_group_conflicts(const std::vector<Word> &word_list, std::string *error) {
|
||||||
|
std::array<bool, 17> g_modes{};
|
||||||
|
std::array<bool, 11> m_modes{};
|
||||||
|
for (const Word &word : word_list) {
|
||||||
|
if (word.letter == 'G') {
|
||||||
|
const int mode = supported_linuxcnc_g_modal_group(word.value);
|
||||||
|
if (mode < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (g_modes[static_cast<size_t>(mode)]) {
|
||||||
|
if (error) {
|
||||||
|
*error = "Two G codes used from same modal group";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
g_modes[static_cast<size_t>(mode)] = true;
|
||||||
|
} else if (word.letter == 'M') {
|
||||||
|
const int mode = supported_linuxcnc_m_modal_group(rounded_value(word.value));
|
||||||
|
if (mode < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (m_modes[static_cast<size_t>(mode)]) {
|
||||||
|
if (error) {
|
||||||
|
*error = "Two M codes used from same modal group";
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
m_modes[static_cast<size_t>(mode)] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string lower_compact(const std::string &value) {
|
std::string lower_compact(const std::string &value) {
|
||||||
std::string out;
|
std::string out;
|
||||||
out.reserve(value.size());
|
out.reserve(value.size());
|
||||||
@@ -2927,6 +3108,9 @@ int SmokeGcodeParser::parse(const char *program, size_t program_len, std::string
|
|||||||
if (!parse_word_list_strict(line, &word_list, error)) {
|
if (!parse_word_list_strict(line, &word_list, error)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
if (!check_linuxcnc_modal_group_conflicts(word_list, error)) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
refresh_readonly_named_parameters(line_number);
|
refresh_readonly_named_parameters(line_number);
|
||||||
const std::string o_identifier = first_o_identifier(keyword_line, word_list);
|
const std::string o_identifier = first_o_identifier(keyword_line, word_list);
|
||||||
const bool has_o_word = !o_identifier.empty();
|
const bool has_o_word = !o_identifier.empty();
|
||||||
|
|||||||
@@ -3572,6 +3572,25 @@ int main() {
|
|||||||
sizeof(duplicate_axis_word_program) - 1) != 0,
|
sizeof(duplicate_axis_word_program) - 1) != 0,
|
||||||
"expected LinuxCNC to reject multiple X words on one line");
|
"expected LinuxCNC to reject multiple X words on one line");
|
||||||
|
|
||||||
|
const char same_modal_group_g_program[] =
|
||||||
|
"G21 G90\n"
|
||||||
|
"F100\n"
|
||||||
|
"G0 G1 X1\n";
|
||||||
|
events.clear();
|
||||||
|
ok &= expect(cnc_sim_parse_program(sim,
|
||||||
|
same_modal_group_g_program,
|
||||||
|
sizeof(same_modal_group_g_program) - 1) != 0,
|
||||||
|
"expected LinuxCNC to reject two G codes from the same modal group");
|
||||||
|
|
||||||
|
const char same_modal_group_m_program[] =
|
||||||
|
"G21 G90\n"
|
||||||
|
"M3 M4\n";
|
||||||
|
events.clear();
|
||||||
|
ok &= expect(cnc_sim_parse_program(sim,
|
||||||
|
same_modal_group_m_program,
|
||||||
|
sizeof(same_modal_group_m_program) - 1) != 0,
|
||||||
|
"expected LinuxCNC to reject two M codes from the same modal group");
|
||||||
|
|
||||||
const char scientific_notation_word_program[] =
|
const char scientific_notation_word_program[] =
|
||||||
"G21 G90\n"
|
"G21 G90\n"
|
||||||
"F100\n"
|
"F100\n"
|
||||||
|
|||||||
Reference in New Issue
Block a user