diff --git a/CHANGES.md b/CHANGES.md index 794f4f4747..5c8f7c2ff8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -39,6 +39,7 @@ Core Grammars: - enh(markdown) add entity support [David Schach][] [TaraLei][] - enh(css) add `justify-items` and `justify-self` attributes [Vasily Polovnyov][] - enh(css) add `accent-color`, `appearance`, `color-scheme`, `rotate`, `scale` and `translate` attributes [Carl Räfting][] +- enh(gcode) rewrote language for modern gcode support [Barthélémy Bonhomme][] New Grammars: @@ -88,6 +89,7 @@ Themes: [Rúnar Bjarnason]: https://github.com/runarorama [Carl Räfting]: https://github.com/carlrafting [BackupMiles]: https://github.com/BackupMiles +[Barthélémy Bonhomme]: https://github.com/barthy-koeln diff --git a/src/languages/gcode.js b/src/languages/gcode.js index 15bf97af7c..822d997514 100644 --- a/src/languages/gcode.js +++ b/src/languages/gcode.js @@ -7,58 +7,116 @@ */ export default function(hljs) { - const GCODE_IDENT_RE = '[A-Z_][A-Z0-9_.]*'; - const GCODE_CLOSE_RE = '%'; const GCODE_KEYWORDS = { - $pattern: GCODE_IDENT_RE, - keyword: 'IF DO WHILE ENDWHILE CALL ENDIF SUB ENDSUB GOTO REPEAT ENDREPEAT ' - + 'EQ LT GT NE GE LE OR XOR' - }; - const GCODE_START = { - className: 'meta', - begin: '([O])([0-9]+)' + $pattern: /[A-Z]+|%/, + meta: [ + // conditions + 'THEN', + 'ELSE', + 'ENDIF', + 'IF', + + // controls + 'GOTO', + 'DO', + 'WHILE', + 'WH', + 'END', + 'CALL', + + // scoping + 'SUB', + 'ENDSUB', + + // comparisons + 'EQ', + 'NE', + 'LT', + 'GT', + 'LE', + 'GE', + 'AND', + 'OR', + 'XOR', + + // start/end of program + '%' + ], + built_in: [ + 'ATAN', + 'ABS', + 'ACOS', + 'ASIN', + 'COS', + 'EXP', + 'FIX', + 'FUP', + 'ROUND', + 'LN', + 'SIN', + 'SQRT', + 'TAN', + 'EXISTS' + ] }; - const NUMBER = hljs.inherit(hljs.C_NUMBER_MODE, { begin: '([-+]?((\\.\\d+)|(\\d+)(\\.\\d*)?))|' + hljs.C_NUMBER_RE }); + + + const NUMBER = /[+-]?((\.\d+)|(\d+)(\.\d*)?)/; + const GCODE_CODE = [ - hljs.C_LINE_COMMENT_MODE, - hljs.C_BLOCK_COMMENT_MODE, + // comments hljs.COMMENT(/\(/, /\)/), - NUMBER, - hljs.inherit(hljs.APOS_STRING_MODE, { illegal: null }), - hljs.inherit(hljs.QUOTE_STRING_MODE, { illegal: null }), + hljs.COMMENT(/;/, /$/), + hljs.APOS_STRING_MODE, + hljs.QUOTE_STRING_MODE, + hljs.C_NUMBER_MODE, + + // gcodes { - className: 'name', - begin: '([G])([0-9]+\\.?[0-9]?)' + scope: 'title.function', + relevance: 10, + variants: [ + // G General functions: G0, G5.1, G5.2, … + // M Misc functions: M0, M55.6, M199, … + { match: /(?, … + { match: /(?/ }, + // Checksum at end of line: *71, *199, … + { match: /\*\s*\d+\s*$/ } + ] }, + { - className: 'attr', - begin: '(VC|VS|#)', - end: '(\\d+)' + scope: 'operator', // N Line number: N1, N2, N1020, … + match: /^N\s*\d+/ }, + { - className: 'attr', - begin: '(VZOFX|VZOFY|VZOFZ)' + scope: 'variable', + relevance: 0, + match: /-?#\s*\d+/, }, + { - className: 'built_in', - begin: '(ATAN|ABS|ACOS|ASIN|SIN|COS|EXP|FIX|FUP|ROUND|LN|TAN)(\\[)', - contains: [ NUMBER ], - end: '\\]' + scope: 'property', // Physical axes + match: new RegExp(`(?O003 (DIAMOND SQUARE) -N2 G54 G90 G49 G80 -N3 M6 T1 (1.ENDMILL) -N4 M3 S1800 -N5 G0 X-.6 Y2.050 -N6 G43 H1 Z.1 -N7 G1 Z-.3 F50. -N8 G41 D1 Y1.45 -N9 G1 X0 F20. -N10 G2 J-1.45 +O003 (DIAMOND SQUARE) +N2 G54 G90 G49 G80 +N3 M6 T1 (1.ENDMILL) +N4 M3 S1800 +N5 G0 X-.6 Y2.050 +N6 G43 H1 Z.1 +N7 G1 Z-.3 F50. +N8 G41 D1 Y1.45 +N9 G1 X0 F20. +N10 G2 J-1.45 (CUTTER COMP CANCEL) -N11 G1 Z-.2 F50. -N12 Y-.990 -N13 G40 -N14 G0 X-.6 Y1.590 -N15 G0 Z.1 -N16 M5 G49 G28 G91 Z0 -N17 CALL O9456 -N18 #500=0.004 -N19 #503=[#500+#501] -N20 VC45=0.0006 -VS4=0.0007 -N21 G90 G10 L20 P3 X5.Y4. Z6.567 -N22 G0 X5000 -N23 IF [#1 LT 0.370] GOTO 49 -N24 X-0.678 Y+.990 -N25 G84.3 X-0.1 -N26 #4=#5*COS[45] -N27 #4=#5*SIN[45] -N28 VZOFZ=652.9658 +N11 G1 Z-.2 F50. +N12 Y-.990 +N13 G40 +N14 G0 X-.6 Y1.590 +N15 G0 Z.1 +N16 M5 G49 G28 G91 Z0 +N17 CALL O9456 +N18 #500=0.004 +N19 #503=[#500+#501] +N20 VC45=0.0006 +VS4=0.0007 +N21 G90 G10 L20 P3 X5.Y4. Z6.567 +N22 G0 X5000 +N23 IF [#1 LT 0.370] GOTO 49 +N24 X-0.678 Y+.990 +N25 G84.3 X-0.1 +N26 #4=#5*COS[45] +N27 #4=#5*SIN[45] +N28 VZOFZ=652.9658 % diff --git a/test/markup/gcode/extended.expect.txt b/test/markup/gcode/extended.expect.txt new file mode 100644 index 0000000000..1881720832 --- /dev/null +++ b/test/markup/gcode/extended.expect.txt @@ -0,0 +1,84 @@ +%; something important + +; another comment + +(yet another more different comment) +( + multi + line + madness +) + +M500; comment after code +M500 (comment after code) + +O<boring> SUB + +#20 = [#1 * SIN[#1]] +#21 = [-#2 * COS[#2]] +#22 = [#3 / COS[#3]] +#23 = [#4 + #4 - #4] +#24 = [[#5 - #5] * TAN[#5]] +#25=FIX[#101/2.75] +#26=ROUND[#104] +#27=ABS[#104] + +; WITH SANE SPACING + +N1 O107 IF [#10 GT 5] +N2 G0 A0 B0 C0 U0 V0 W0 X0 Y0 Z0 *71 +N3 G100 A100 B0 +N4 G5.2 A10.2 B0 +N5 G100 A.2 B0 +N6 G100 A-.2 B0 +N7 G100 A+.2 B0 +N8 T0 +N9 M100 F1 H2 I3 J4 K5 P6 Q7 R8 S9 +N10 M587 S"MYROUTER" P"ABCxyz;" "123" +N10 O107 ENDIF + + +; WITH EXCESSIVE SPACING + +O 108 IF [#10 GT 5] +N 102 G 0 A 0 B 0 C 0 U 0 V 0 W 0 X 0 Y 0 Z 0 *71 +N 103 G 100 A 100 B 0 +N 104 G 5.2 A 10.2 B 0 +N 105 G 100 A .2 B 0 +N 106 G 100 A -.2 B 0 +N 107 G 100 A +.2 B 0 +N 108 T 0 +N 109 M 100 F 1 H 2 I 3 J 4 K 5 P 6 Q 7 R 8 S 9 +N 110 M 587 S "MYROUTER" P "ABCxyz;" "123" +O 108 ENDIF + + +; WITHOUT SPACING + +O109IF[#10GT5] +N202G0A0B0C0U0V0W0X0Y0Z0*71 +N203G100A100B0 +N204G5.2A10.2B0 +N205G100A.2B0 +N206G100A-.2B0 +N207G100A+.2B0 +N208T0 +N209M100F1H2I3J4K5P6Q7R8S9 +N210M587S"MYROUTER"P"ABCxyz;""123" +0O109ENDIF + +O<boring> ENDSUB + +O<boring> CALL [1] [2] [3] [4] [5] + +; Words as see in Klipper Firmware GCode + +GET_RETRACTION +TURN_OFF_HEATERS +MANUAL_STEPPER STEPPER=config_name ENABLE=0 SET_POSITION=11.1 SPEED=22.2 ACCEL=33.3 MOVE=44.4 STOP_ON_ENDSTOP=-1 SYNC=0 + +SET_SKEW XY=100.0000,100.0000,70.7107 +SKEW_PROFILE SAVE="this name has spaces" +SAVE_CONFIG + +% diff --git a/test/markup/gcode/extended.txt b/test/markup/gcode/extended.txt new file mode 100644 index 0000000000..5e19021d7f --- /dev/null +++ b/test/markup/gcode/extended.txt @@ -0,0 +1,84 @@ +%; something important + +; another comment + +(yet another more different comment) +( + multi + line + madness +) + +M500; comment after code +M500 (comment after code) + +O SUB + +#20 = [#1 * SIN[#1]] +#21 = [-#2 * COS[#2]] +#22 = [#3 / COS[#3]] +#23 = [#4 + #4 - #4] +#24 = [[#5 - #5] * TAN[#5]] +#25=FIX[#101/2.75] +#26=ROUND[#104] +#27=ABS[#104] + +; WITH SANE SPACING + +N1 O107 IF [#10 GT 5] +N2 G0 A0 B0 C0 U0 V0 W0 X0 Y0 Z0 *71 +N3 G100 A100 B0 +N4 G5.2 A10.2 B0 +N5 G100 A.2 B0 +N6 G100 A-.2 B0 +N7 G100 A+.2 B0 +N8 T0 +N9 M100 F1 H2 I3 J4 K5 P6 Q7 R8 S9 +N10 M587 S"MYROUTER" P"ABCxyz;" "123" +N10 O107 ENDIF + + +; WITH EXCESSIVE SPACING + +O 108 IF [#10 GT 5] +N 102 G 0 A 0 B 0 C 0 U 0 V 0 W 0 X 0 Y 0 Z 0 *71 +N 103 G 100 A 100 B 0 +N 104 G 5.2 A 10.2 B 0 +N 105 G 100 A .2 B 0 +N 106 G 100 A -.2 B 0 +N 107 G 100 A +.2 B 0 +N 108 T 0 +N 109 M 100 F 1 H 2 I 3 J 4 K 5 P 6 Q 7 R 8 S 9 +N 110 M 587 S "MYROUTER" P "ABCxyz;" "123" +O 108 ENDIF + + +; WITHOUT SPACING + +O109IF[#10GT5] +N202G0A0B0C0U0V0W0X0Y0Z0*71 +N203G100A100B0 +N204G5.2A10.2B0 +N205G100A.2B0 +N206G100A-.2B0 +N207G100A+.2B0 +N208T0 +N209M100F1H2I3J4K5P6Q7R8S9 +N210M587S"MYROUTER"P"ABCxyz;""123" +0O109ENDIF + +O ENDSUB + +O CALL [1] [2] [3] [4] [5] + +; Words as see in Klipper Firmware GCode + +GET_RETRACTION +TURN_OFF_HEATERS +MANUAL_STEPPER STEPPER=config_name ENABLE=0 SET_POSITION=11.1 SPEED=22.2 ACCEL=33.3 MOVE=44.4 STOP_ON_ENDSTOP=-1 SYNC=0 + +SET_SKEW XY=100.0000,100.0000,70.7107 +SKEW_PROFILE SAVE="this name has spaces" +SAVE_CONFIG + +%