将 YACC 应用于 GCODE (GRBL)
Applying YACC to GCODE (GRBL)
GCode 是用于告诉多轴 (CNC) 机器人如何移动的语言。
看起来像这样:
M3 S5000 (Start Spindle Clockwise at 5000 RPM)
G21 (All units in mm)
G00 Z1.000000 (lift Z axis up by 1mm)
G00 X94.720505 Y-14.904622 (Go to this XY coordinate)
G01 Z0.000000 F100.0 (Penetrate at 100mm/m)
G01 X97.298434 Y-14.870127 F400 (cut to here)
G03 X98.003848 Y-14.275867 I-0.028107 J0.749174 (cut an arc)
G00 Z1.000000 (lift Z axis)
etc.
我已将这些命令放在句子中,但每个标记可以单独一行。
事实上,没有关于将数字连接到它们各自的代码字母的规则。然而,我已经有了一个 LEX 解析器,它可以为我获取如下所述的标记。
请注意,某些命令(M 或 G 代码)具有参数。
在 M3 的情况下,它可以有一个 S(主轴速度)参数。
G0 和 G1 可以有 X,Y,Z,F 等。
G3 可以有 X,Y,Z,I,J,R...
然而,每个 G 代码不需要所有这些参数,只需一个、多个或全部。
这里要注意的一点是,我们切割的是单条路径,然后提升z轴。
也就是说,我们移动到工作台面上方的某个位置,穿透,开辟一条路径,然后起飞。
我会称其为 'block' 或 'path',这正是我感兴趣的。
我需要能够解析任何混乱格式的 GCode,然后创建一个 'blocks' 的结构,其中一个块是 z 轴上下之间的任何一系列 'commands'。
我可以使用 LEX(特别是 python PLY)对这种语言进行标记。
并得到:
type M value 3
type S value 5000
type COMMENT value "Start Spindle Clockwise at 5000 RPM"
type G value 31
type COMMENT value "All unites in mm"
type G value 0
type Z value 1.0
etc.
现在使用 Lexx,我需要一个名为 'command' 的东西的规则。
命令是任何注释,或者:
'G' 或 'M' 代码后跟任何适当的参数代码(X、Y、Z 等)
当遇到另一个命令(注释、G 或 M)时,命令结束。
然后我需要一个叫做 'block' 的东西,
其中块是在 Z 向下和 Z 向上之前的任何 'commands' 集合。
有100个G代码和100个M代码和25个参数代码(A-Z减去G和M)
'command' 的规则可能如下所示:
command : G F H I J K L S T W X Y Z (how to specify ONE OF)
| M S F (How to specify one of)
| COMMENT
然后我们如何定义块!?
我知道这很长post,但是如果有人能告诉我 YACC 是否可以做到这一点?否则,我将只编写一些代码,手动将 lex 标记转换为树。
附录@rici
感谢您花时间了解这个问题。
通过反馈方式:
我的全部任务是让 YACC 完成繁重的工作,根据不同的用例将代码块分成块。
例如当'engraving'时,通常一个方块代表一个字母或一些其他形状(在xy平面上)。因此,一个块将由 z 轴进出 xy 平面的移动来定义。
我希望能够 post 处理块:
- 影线填充 'block'。这将涉及一些相当复杂的路径边界计算、这些边界的切线、工具直径等。这是最紧迫的用例,我还没有一个好的解决方案,但我知道它可以完成,因为它可以完成Inkscape(矢量图形应用程序)
- 旋转n度。一个相当简单的坐标翻译,我已经有解决方案了。
- 迭代加深(挤压)。在每次迭代中复制块并调整 Z 深度。简单。
- 等等
如果你只是想确保一个G命令后面跟着一些东西,你可以这样做:
g_modifier: F | H | I | J | K | L | S | T | W | X | Y | Z
m_modifier: S | F
g_command: G g_modifier | g_command g_modifier
m_command: M m_modifier | m_command m_modifier
command: g_command | m_command | COMMENT
如果你想使用 Z 修饰符将它们拆分成序列,那是可以做到的。您可能希望词法分析器能够根据参数的符号生成两种不同的 Z 标记类型,因为解析器只能根据标记而不是语义值做出语法决策。
您的问题至少提供了两个不同的块定义,因此很难提供明确的答案。
”也就是我们移动到工作面上方的位置,穿透,切出一个path then lift off. 我会称之为 'block' 或 'path' 我感兴趣的就是这个."
例如:
G00 X94.7 Y-14.9 (Move)
G01 Z0.0 (Penetrate)
G01 X97.2 Y-14.8 G03 X98.0 Y-14.2 I-0.02 J0.7 (Path)
G00 Z1.0 (Lift)
但稍后你会说,“一个块是 在 之后 和 之前的任何一组 'commands' Z 向上。
这就是前面示例的这一部分:
G01 X97.2 Y-14.8 G03 X98.0 Y-14.2 I-0.02 J0.7 (Path)
这两种都有可能,但明显不同。以下是一些可能的构建块:
# This list doesn't include Z words
g_modifier: F | H | I | J | K | L | S | T | W | X | Y
g_command_no_z: G g_modifier
| g_command_no_z g_modifier
# This doesn't distinguish between Z up and Z down. If you want that to
# affect syntax, you need two different Z tokens, and then two different
# with_z non-terminals.
g_command_with_z: G Z
| g_command_no_z Z
| g_command_with_z g_modifier
# You might or might not want this.
# It's a non-empty sequence of G or M commands with no Z's.
path: command_no_z
| path command_no_z
command_no_z: COMMENT
| m_command
| g_command_no_z
GCode 是用于告诉多轴 (CNC) 机器人如何移动的语言。 看起来像这样:
M3 S5000 (Start Spindle Clockwise at 5000 RPM)
G21 (All units in mm)
G00 Z1.000000 (lift Z axis up by 1mm)
G00 X94.720505 Y-14.904622 (Go to this XY coordinate)
G01 Z0.000000 F100.0 (Penetrate at 100mm/m)
G01 X97.298434 Y-14.870127 F400 (cut to here)
G03 X98.003848 Y-14.275867 I-0.028107 J0.749174 (cut an arc)
G00 Z1.000000 (lift Z axis)
etc.
我已将这些命令放在句子中,但每个标记可以单独一行。 事实上,没有关于将数字连接到它们各自的代码字母的规则。然而,我已经有了一个 LEX 解析器,它可以为我获取如下所述的标记。
请注意,某些命令(M 或 G 代码)具有参数。 在 M3 的情况下,它可以有一个 S(主轴速度)参数。 G0 和 G1 可以有 X,Y,Z,F 等。 G3 可以有 X,Y,Z,I,J,R... 然而,每个 G 代码不需要所有这些参数,只需一个、多个或全部。
这里要注意的一点是,我们切割的是单条路径,然后提升z轴。 也就是说,我们移动到工作台面上方的某个位置,穿透,开辟一条路径,然后起飞。 我会称其为 'block' 或 'path',这正是我感兴趣的。
我需要能够解析任何混乱格式的 GCode,然后创建一个 'blocks' 的结构,其中一个块是 z 轴上下之间的任何一系列 'commands'。
我可以使用 LEX(特别是 python PLY)对这种语言进行标记。 并得到:
type M value 3
type S value 5000
type COMMENT value "Start Spindle Clockwise at 5000 RPM"
type G value 31
type COMMENT value "All unites in mm"
type G value 0
type Z value 1.0
etc.
现在使用 Lexx,我需要一个名为 'command' 的东西的规则。
命令是任何注释,或者: 'G' 或 'M' 代码后跟任何适当的参数代码(X、Y、Z 等) 当遇到另一个命令(注释、G 或 M)时,命令结束。
然后我需要一个叫做 'block' 的东西, 其中块是在 Z 向下和 Z 向上之前的任何 'commands' 集合。
有100个G代码和100个M代码和25个参数代码(A-Z减去G和M)
'command' 的规则可能如下所示:
command : G F H I J K L S T W X Y Z (how to specify ONE OF)
| M S F (How to specify one of)
| COMMENT
然后我们如何定义块!?
我知道这很长post,但是如果有人能告诉我 YACC 是否可以做到这一点?否则,我将只编写一些代码,手动将 lex 标记转换为树。
附录@rici
感谢您花时间了解这个问题。 通过反馈方式: 我的全部任务是让 YACC 完成繁重的工作,根据不同的用例将代码块分成块。
例如当'engraving'时,通常一个方块代表一个字母或一些其他形状(在xy平面上)。因此,一个块将由 z 轴进出 xy 平面的移动来定义。
我希望能够 post 处理块:
- 影线填充 'block'。这将涉及一些相当复杂的路径边界计算、这些边界的切线、工具直径等。这是最紧迫的用例,我还没有一个好的解决方案,但我知道它可以完成,因为它可以完成Inkscape(矢量图形应用程序)
- 旋转n度。一个相当简单的坐标翻译,我已经有解决方案了。
- 迭代加深(挤压)。在每次迭代中复制块并调整 Z 深度。简单。
- 等等
如果你只是想确保一个G命令后面跟着一些东西,你可以这样做:
g_modifier: F | H | I | J | K | L | S | T | W | X | Y | Z
m_modifier: S | F
g_command: G g_modifier | g_command g_modifier
m_command: M m_modifier | m_command m_modifier
command: g_command | m_command | COMMENT
如果你想使用 Z 修饰符将它们拆分成序列,那是可以做到的。您可能希望词法分析器能够根据参数的符号生成两种不同的 Z 标记类型,因为解析器只能根据标记而不是语义值做出语法决策。
您的问题至少提供了两个不同的块定义,因此很难提供明确的答案。
”也就是我们移动到工作面上方的位置,穿透,切出一个path then lift off. 我会称之为 'block' 或 'path' 我感兴趣的就是这个."
例如:
G00 X94.7 Y-14.9 (Move) G01 Z0.0 (Penetrate) G01 X97.2 Y-14.8 G03 X98.0 Y-14.2 I-0.02 J0.7 (Path) G00 Z1.0 (Lift)
但稍后你会说,“一个块是 在 之后 和 之前的任何一组 'commands' Z 向上。
这就是前面示例的这一部分:
G01 X97.2 Y-14.8 G03 X98.0 Y-14.2 I-0.02 J0.7 (Path)
这两种都有可能,但明显不同。以下是一些可能的构建块:
# This list doesn't include Z words
g_modifier: F | H | I | J | K | L | S | T | W | X | Y
g_command_no_z: G g_modifier
| g_command_no_z g_modifier
# This doesn't distinguish between Z up and Z down. If you want that to
# affect syntax, you need two different Z tokens, and then two different
# with_z non-terminals.
g_command_with_z: G Z
| g_command_no_z Z
| g_command_with_z g_modifier
# You might or might not want this.
# It's a non-empty sequence of G or M commands with no Z's.
path: command_no_z
| path command_no_z
command_no_z: COMMENT
| m_command
| g_command_no_z