123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- /*
- Language: G-code (ISO 6983)
- Contributors: Adam Joseph Cook <adam.joseph.cook@gmail.com>
- Description: G-code syntax highlighter for Fanuc and other common CNC machine tool controls.
- Website: https://www.sis.se/api/document/preview/911952/
- Category: hardware
- */
- function gcode(hljs) {
- const regex = hljs.regex;
- const GCODE_KEYWORDS = {
- $pattern: /[A-Z]+|%/,
- keyword: [
- // 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'
- ]
- };
- // TODO: post v12 lets use look-behind, until then \b and a callback filter will be used
- // const LETTER_BOUNDARY_RE = /(?<![A-Z])/;
- const LETTER_BOUNDARY_RE = /\b/;
- function LETTER_BOUNDARY_CALLBACK(matchdata, response) {
- if (matchdata.index === 0) {
- return;
- }
- const charBeforeMatch = matchdata.input[matchdata.index - 1];
- if (charBeforeMatch >= '0' && charBeforeMatch <= '9') {
- return;
- }
- if (charBeforeMatch === '_') {
- return;
- }
- response.ignoreMatch();
- }
- const NUMBER_RE = /[+-]?((\.\d+)|(\d+)(\.\d*)?)/;
- const GENERAL_MISC_FUNCTION_RE = /[GM]\s*\d+(\.\d+)?/;
- const TOOLS_RE = /T\s*\d+/;
- const SUBROUTINE_RE = /O\s*\d+/;
- const SUBROUTINE_NAMED_RE = /O<.+>/;
- const AXES_RE = /[ABCUVWXYZ]\s*/;
- const PARAMETERS_RE = /[FHIJKPQRS]\s*/;
- const GCODE_CODE = [
- // comments
- hljs.COMMENT(/\(/, /\)/),
- hljs.COMMENT(/;/, /$/),
- hljs.APOS_STRING_MODE,
- hljs.QUOTE_STRING_MODE,
- hljs.C_NUMBER_MODE,
- // gcodes
- {
- scope: 'title.function',
- variants: [
- // G General functions: G0, G5.1, G5.2, …
- // M Misc functions: M0, M55.6, M199, …
- { match: regex.concat(LETTER_BOUNDARY_RE, GENERAL_MISC_FUNCTION_RE) },
- {
- begin: GENERAL_MISC_FUNCTION_RE,
- 'on:begin': LETTER_BOUNDARY_CALLBACK
- },
- // T Tools
- { match: regex.concat(LETTER_BOUNDARY_RE, TOOLS_RE), },
- {
- begin: TOOLS_RE,
- 'on:begin': LETTER_BOUNDARY_CALLBACK
- }
- ]
- },
- {
- scope: 'symbol',
- variants: [
- // O Subroutine ID: O100, O110, …
- { match: regex.concat(LETTER_BOUNDARY_RE, SUBROUTINE_RE) },
- {
- begin: SUBROUTINE_RE,
- 'on:begin': LETTER_BOUNDARY_CALLBACK
- },
- // O Subroutine name: O<some>, …
- { match: regex.concat(LETTER_BOUNDARY_RE, SUBROUTINE_NAMED_RE) },
- {
- begin: SUBROUTINE_NAMED_RE,
- 'on:begin': LETTER_BOUNDARY_CALLBACK
- },
- // Checksum at end of line: *71, *199, …
- { match: /\*\s*\d+\s*$/ }
- ]
- },
- {
- scope: 'operator', // N Line number: N1, N2, N1020, …
- match: /^N\s*\d+/
- },
- {
- scope: 'variable',
- match: /-?#\s*\d+/
- },
- {
- scope: 'property', // Physical axes,
- variants: [
- { match: regex.concat(LETTER_BOUNDARY_RE, AXES_RE, NUMBER_RE) },
- {
- begin: regex.concat(AXES_RE, NUMBER_RE),
- 'on:begin': LETTER_BOUNDARY_CALLBACK
- },
- ]
- },
- {
- scope: 'params', // Different types of parameters
- variants: [
- { match: regex.concat(LETTER_BOUNDARY_RE, PARAMETERS_RE, NUMBER_RE) },
- {
- begin: regex.concat(PARAMETERS_RE, NUMBER_RE),
- 'on:begin': LETTER_BOUNDARY_CALLBACK
- },
- ]
- },
- ];
- return {
- name: 'G-code (ISO 6983)',
- aliases: [ 'nc' ],
- // Some implementations (CNC controls) of G-code are interoperable with uppercase and lowercase letters seamlessly.
- // However, most prefer all uppercase and uppercase is customary.
- case_insensitive: true,
- // TODO: post v12 with the use of look-behind this can be enabled
- disableAutodetect: true,
- keywords: GCODE_KEYWORDS,
- contains: GCODE_CODE
- };
- }
- export { gcode as default };
|