77 */
88
99export default function ( hljs ) {
10- const GCODE_IDENT_RE = '[A-Z_][A-Z0-9_.]*' ;
11- const GCODE_CLOSE_RE = '%' ;
10+ const regex = hljs . regex ;
1211 const GCODE_KEYWORDS = {
13- $pattern : GCODE_IDENT_RE ,
14- keyword : 'IF DO WHILE ENDWHILE CALL ENDIF SUB ENDSUB GOTO REPEAT ENDREPEAT '
15- + 'EQ LT GT NE GE LE OR XOR'
16- } ;
17- const GCODE_START = {
18- className : 'meta' ,
19- begin : '([O])([0-9]+)'
12+ $pattern : / [ A - Z ] + | % / ,
13+ keyword : [
14+ // conditions
15+ 'THEN' ,
16+ 'ELSE' ,
17+ 'ENDIF' ,
18+ 'IF' ,
19+
20+ // controls
21+ 'GOTO' ,
22+ 'DO' ,
23+ 'WHILE' ,
24+ 'WH' ,
25+ 'END' ,
26+ 'CALL' ,
27+
28+ // scoping
29+ 'SUB' ,
30+ 'ENDSUB' ,
31+
32+ // comparisons
33+ 'EQ' ,
34+ 'NE' ,
35+ 'LT' ,
36+ 'GT' ,
37+ 'LE' ,
38+ 'GE' ,
39+ 'AND' ,
40+ 'OR' ,
41+ 'XOR' ,
42+
43+ // start/end of program
44+ '%'
45+ ] ,
46+ built_in : [
47+ 'ATAN' ,
48+ 'ABS' ,
49+ 'ACOS' ,
50+ 'ASIN' ,
51+ 'COS' ,
52+ 'EXP' ,
53+ 'FIX' ,
54+ 'FUP' ,
55+ 'ROUND' ,
56+ 'LN' ,
57+ 'SIN' ,
58+ 'SQRT' ,
59+ 'TAN' ,
60+ 'EXISTS'
61+ ]
2062 } ;
21- const NUMBER = hljs . inherit ( hljs . C_NUMBER_MODE , { begin : '([-+]?((\\.\\d+)|(\\d+)(\\.\\d*)?))|' + hljs . C_NUMBER_RE } ) ;
63+
64+
65+ // TODO: post v12 lets use look-behind, until then \b and a callback filter will be used
66+ // const LETTER_BOUNDARY_RE = /(?<![A-Z])/;
67+ const LETTER_BOUNDARY_RE = / \b / ;
68+
69+ function LETTER_BOUNDARY_CALLBACK ( matchdata , response ) {
70+ if ( matchdata . index === 0 ) {
71+ return ;
72+ }
73+
74+ const charBeforeMatch = matchdata . input [ matchdata . index - 1 ] ;
75+ if ( charBeforeMatch >= '0' && charBeforeMatch <= '9' ) {
76+ return ;
77+ }
78+
79+ if ( charBeforeMatch === '_' ) {
80+ return ;
81+ }
82+
83+ response . ignoreMatch ( ) ;
84+ }
85+
86+ const NUMBER_RE = / [ + - ] ? ( ( \. \d + ) | ( \d + ) ( \. \d * ) ? ) / ;
87+
88+ const GENERAL_MISC_FUNCTION_RE = / [ G M ] \s * \d + ( \. \d + ) ? / ;
89+ const TOOLS_RE = / T \s * \d + / ;
90+ const SUBROUTINE_RE = / O \s * \d + / ;
91+ const SUBROUTINE_NAMED_RE = / O < .+ > / ;
92+ const AXES_RE = / [ A B C U V W X Y Z ] \s * / ;
93+ const PARAMETERS_RE = / [ F H I J K P Q R S ] \s * / ;
94+
2295 const GCODE_CODE = [
23- hljs . C_LINE_COMMENT_MODE ,
24- hljs . C_BLOCK_COMMENT_MODE ,
96+ // comments
2597 hljs . COMMENT ( / \( / , / \) / ) ,
26- NUMBER ,
27- hljs . inherit ( hljs . APOS_STRING_MODE , { illegal : null } ) ,
28- hljs . inherit ( hljs . QUOTE_STRING_MODE , { illegal : null } ) ,
98+ hljs . COMMENT ( / ; / , / $ / ) ,
99+ hljs . APOS_STRING_MODE ,
100+ hljs . QUOTE_STRING_MODE ,
101+ hljs . C_NUMBER_MODE ,
102+
103+ // gcodes
29104 {
30- className : 'name' ,
31- begin : '([G])([0-9]+\\.?[0-9]?)'
105+ scope : 'title.function' ,
106+ variants : [
107+ // G General functions: G0, G5.1, G5.2, …
108+ // M Misc functions: M0, M55.6, M199, …
109+ { match : regex . concat ( LETTER_BOUNDARY_RE , GENERAL_MISC_FUNCTION_RE ) } ,
110+ {
111+ begin : GENERAL_MISC_FUNCTION_RE ,
112+ 'on:begin' : LETTER_BOUNDARY_CALLBACK
113+ } ,
114+ // T Tools
115+ { match : regex . concat ( LETTER_BOUNDARY_RE , TOOLS_RE ) , } ,
116+ {
117+ begin : TOOLS_RE ,
118+ 'on:begin' : LETTER_BOUNDARY_CALLBACK
119+ }
120+ ]
32121 } ,
122+
33123 {
34- className : 'name' ,
35- begin : '([M])([0-9]+\\.?[0-9]?)'
124+ scope : 'symbol' ,
125+ variants : [
126+ // O Subroutine ID: O100, O110, …
127+ { match : regex . concat ( LETTER_BOUNDARY_RE , SUBROUTINE_RE ) } ,
128+ {
129+ begin : SUBROUTINE_RE ,
130+ 'on:begin' : LETTER_BOUNDARY_CALLBACK
131+ } ,
132+ // O Subroutine name: O<some>, …
133+ { match : regex . concat ( LETTER_BOUNDARY_RE , SUBROUTINE_NAMED_RE ) } ,
134+ {
135+ begin : SUBROUTINE_NAMED_RE ,
136+ 'on:begin' : LETTER_BOUNDARY_CALLBACK
137+ } ,
138+ // Checksum at end of line: *71, *199, …
139+ { match : / \* \s * \d + \s * $ / }
140+ ]
36141 } ,
142+
37143 {
38- className : 'attr' ,
39- begin : '(VC|VS|#)' ,
40- end : '(\\d+)'
144+ scope : 'operator' , // N Line number: N1, N2, N1020, …
145+ match : / ^ N \s * \d + /
41146 } ,
147+
42148 {
43- className : 'attr ' ,
44- begin : '(VZOFX|VZOFY|VZOFZ)'
149+ scope : 'variable ' ,
150+ match : / - ? # \s * \d + /
45151 } ,
152+
46153 {
47- className : 'built_in' ,
48- begin : '(ATAN|ABS|ACOS|ASIN|SIN|COS|EXP|FIX|FUP|ROUND|LN|TAN)(\\[)' ,
49- contains : [ NUMBER ] ,
50- end : '\\]'
154+ scope : 'property' , // Physical axes,
155+ variants : [
156+ { match : regex . concat ( LETTER_BOUNDARY_RE , AXES_RE , NUMBER_RE ) } ,
157+ {
158+ begin : regex . concat ( AXES_RE , NUMBER_RE ) ,
159+ 'on:begin' : LETTER_BOUNDARY_CALLBACK
160+ } ,
161+ ]
51162 } ,
163+
52164 {
53- className : 'symbol' ,
165+ scope : 'params' , // Different types of parameters
54166 variants : [
167+ { match : regex . concat ( LETTER_BOUNDARY_RE , PARAMETERS_RE , NUMBER_RE ) } ,
55168 {
56- begin : 'N' ,
57- end : '\\d+' ,
58- illegal : '\\W'
59- }
169+ begin : regex . concat ( PARAMETERS_RE , NUMBER_RE ) ,
170+ 'on:begin' : LETTER_BOUNDARY_CALLBACK
171+ } ,
60172 ]
61- }
173+ } ,
62174 ] ;
63175
64176 return {
@@ -67,13 +179,9 @@ export default function(hljs) {
67179 // Some implementations (CNC controls) of G-code are interoperable with uppercase and lowercase letters seamlessly.
68180 // However, most prefer all uppercase and uppercase is customary.
69181 case_insensitive : true ,
182+ // TODO: post v12 with the use of look-behind this can be enabled
183+ disableAutodetect : true ,
70184 keywords : GCODE_KEYWORDS ,
71- contains : [
72- {
73- className : 'meta' ,
74- begin : GCODE_CLOSE_RE
75- } ,
76- GCODE_START
77- ] . concat ( GCODE_CODE )
185+ contains : GCODE_CODE
78186 } ;
79187}
0 commit comments