84 lines
1.9 KiB
JavaScript
84 lines
1.9 KiB
JavaScript
class GCodeParser {
|
|
|
|
static normalizeInput(raw) {
|
|
if (raw === undefined || raw === null) {
|
|
return '';
|
|
}
|
|
|
|
if (Buffer.isBuffer(raw)) {
|
|
raw = raw.toString('utf8');
|
|
}
|
|
|
|
return String(raw).trim();
|
|
}
|
|
|
|
static splitCommands(input) {
|
|
if (!input) {
|
|
return [];
|
|
}
|
|
|
|
// Preserve leading G/M on each segment.
|
|
return input
|
|
.trim()
|
|
.split(/ (?=G|M)/i)
|
|
.map(segment => segment.trim())
|
|
.filter(Boolean);
|
|
}
|
|
|
|
static parseCommand(commandString) {
|
|
if (!commandString || commandString.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const tokens = commandString.trim().split(/\s+/);
|
|
if (tokens.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
const commandToken = tokens[0].toUpperCase();
|
|
if (!/^[GM]\d+/i.test(commandToken)) {
|
|
return null;
|
|
}
|
|
|
|
const params = {};
|
|
for (let i = 1; i < tokens.length; i++) {
|
|
const token = tokens[i].trim();
|
|
if (token.length < 2) {
|
|
continue;
|
|
}
|
|
|
|
const key = token.charAt(0).toUpperCase();
|
|
const valueString = token.substring(1);
|
|
const value = Number(valueString);
|
|
if (!Number.isNaN(value)) {
|
|
params[key] = value;
|
|
}
|
|
}
|
|
|
|
return {
|
|
command: commandToken,
|
|
params,
|
|
raw: commandString.trim()
|
|
};
|
|
}
|
|
|
|
static parse(raw) {
|
|
const input = this.normalizeInput(raw);
|
|
if (!input) {
|
|
return [];
|
|
}
|
|
|
|
if (input.startsWith('$J=')) {
|
|
return this.parse(input.substring(3).trim());
|
|
}
|
|
|
|
const commands = this.splitCommands(input)
|
|
.map(commandString => this.parseCommand(commandString))
|
|
.filter(Boolean);
|
|
|
|
return commands;
|
|
}
|
|
}
|
|
|
|
module.exports = GCodeParser;
|