7
7
*/
8
8
9
9
export default function ( hljs ) {
10
- const GCODE_IDENT_RE = '[A-Z_][A-Z0-9_.]*' ;
11
- const GCODE_CLOSE_RE = '%' ;
10
+ const regex = hljs . regex ;
12
11
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
+ ]
20
62
} ;
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
+
22
95
const GCODE_CODE = [
23
- hljs . C_LINE_COMMENT_MODE ,
24
- hljs . C_BLOCK_COMMENT_MODE ,
96
+ // comments
25
97
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
29
104
{
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
+ ]
32
121
} ,
122
+
33
123
{
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
+ ]
36
141
} ,
142
+
37
143
{
38
- className : 'attr' ,
39
- begin : '(VC|VS|#)' ,
40
- end : '(\\d+)'
144
+ scope : 'operator' , // N Line number: N1, N2, N1020, …
145
+ match : / ^ N \s * \d + /
41
146
} ,
147
+
42
148
{
43
- className : 'attr ' ,
44
- begin : '(VZOFX|VZOFY|VZOFZ)'
149
+ scope : 'variable ' ,
150
+ match : / - ? # \s * \d + /
45
151
} ,
152
+
46
153
{
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
+ ]
51
162
} ,
163
+
52
164
{
53
- className : 'symbol' ,
165
+ scope : 'params' , // Different types of parameters
54
166
variants : [
167
+ { match : regex . concat ( LETTER_BOUNDARY_RE , PARAMETERS_RE , NUMBER_RE ) } ,
55
168
{
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
+ } ,
60
172
]
61
- }
173
+ } ,
62
174
] ;
63
175
64
176
return {
@@ -67,13 +179,9 @@ export default function(hljs) {
67
179
// Some implementations (CNC controls) of G-code are interoperable with uppercase and lowercase letters seamlessly.
68
180
// However, most prefer all uppercase and uppercase is customary.
69
181
case_insensitive : true ,
182
+ // TODO: post v12 with the use of look-behind this can be enabled
183
+ disableAutodetect : true ,
70
184
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
78
186
} ;
79
187
}
0 commit comments