226 lines
5.0 KiB
Plaintext
226 lines
5.0 KiB
Plaintext
|
%YAML 1.2
|
||
|
---
|
||
|
#
|
||
|
# G-Code (RepRap, not ISO-6983)
|
||
|
# Author: @thinkyhead
|
||
|
#
|
||
|
# RapRap G-Code is very simple.
|
||
|
#
|
||
|
# TODO: Lines that start with N get a different context, accepting a checksum.
|
||
|
#
|
||
|
name: G-Code (RepRap)
|
||
|
file_extensions:
|
||
|
- [ g, gco, gcode ]
|
||
|
scope: source.gcode
|
||
|
variables:
|
||
|
decimal: '[+-]?\d+(\.\d*)?'
|
||
|
|
||
|
contexts:
|
||
|
prototype:
|
||
|
- match: \s+
|
||
|
|
||
|
- include: mixin_comment
|
||
|
|
||
|
- match: $
|
||
|
pop: true
|
||
|
|
||
|
main:
|
||
|
- meta_scope: line.gcode
|
||
|
|
||
|
- match: '([Nn]\s*(\d+))'
|
||
|
captures:
|
||
|
1: entity.nword.gcode
|
||
|
2: constant.numeric.line-number.gcode
|
||
|
|
||
|
- match: ()
|
||
|
set: gcode_command
|
||
|
|
||
|
# G, M, or T command
|
||
|
gcode_command:
|
||
|
- meta_content_scope: ctx.command.gcode
|
||
|
|
||
|
# M20 S2 P/path/to/file/name.gco
|
||
|
- match: ([Mm](20))\s*((S)(2)\s*(P))
|
||
|
captures:
|
||
|
1: entity.command.gcode markup.bold.gcode
|
||
|
2: constant.numeric.command.gcode
|
||
|
3: ctx.params.gcode
|
||
|
4: keyword.param.gcode
|
||
|
5: constant.numeric.param.gcode
|
||
|
6: keyword.param.gcode
|
||
|
set: gcode_string_arg
|
||
|
|
||
|
# M117 or M118 - Commands taking a string
|
||
|
- match: ([Mm]\s*(11[78]))\b
|
||
|
captures:
|
||
|
1: entity.command.gcode markup.bold.gcode
|
||
|
2: constant.numeric.command.gcode
|
||
|
set: gcode_string_arg
|
||
|
|
||
|
# Other commands, followed by data
|
||
|
- match: ([GMTgmt]\s*(\d+)((\.)(\d+))?)
|
||
|
captures:
|
||
|
1: entity.command.gcode markup.bold.gcode
|
||
|
2: constant.numeric.command.gcode
|
||
|
4: entity.separator.subcode
|
||
|
5: constant.numeric.subcode
|
||
|
set: gcode_params
|
||
|
|
||
|
- match: ()
|
||
|
set: syntax_error
|
||
|
|
||
|
# Parameters of a command
|
||
|
gcode_params:
|
||
|
- meta_content_scope: ctx.params.gcode
|
||
|
|
||
|
# M32 [S<pos>] [P<bool>] !/path/file.gco#
|
||
|
- match: \!
|
||
|
scope: punctuation.string.path.open.gcode
|
||
|
push: gcode_path_arg
|
||
|
|
||
|
# asterisk starts a checksum
|
||
|
- match: \*
|
||
|
scope: punctuation.marker.checksum.gcode
|
||
|
set: gcode_checksum
|
||
|
|
||
|
# parameter and single-quoted value
|
||
|
- match: ([A-Za-z])\s*(')
|
||
|
captures:
|
||
|
1: keyword.param.gcode
|
||
|
2: punctuation.quote.single.open.gcode
|
||
|
push: gcode_string_arg_quoted_single
|
||
|
|
||
|
# parameter and double-quoted value
|
||
|
- match: ([A-Za-z])\s*(")
|
||
|
captures:
|
||
|
1: keyword.param.gcode
|
||
|
2: punctuation.quote.double.open.gcode
|
||
|
push: gcode_string_arg_quoted_double
|
||
|
|
||
|
# parameter and list of values
|
||
|
- match: ([Ee])\s*(({{decimal}}\s*:\s*)+{{decimal}})
|
||
|
captures:
|
||
|
1: keyword.param.gcode
|
||
|
2: constant.numeric.param.gcode
|
||
|
|
||
|
# parameter and numeric value
|
||
|
- match: ([A-Za-z])\s*({{decimal}})
|
||
|
captures:
|
||
|
1: keyword.param.gcode
|
||
|
2: constant.numeric.param.gcode
|
||
|
|
||
|
# parameter with no value
|
||
|
- match: '[A-Za-z]'
|
||
|
scope: keyword.param.gcode
|
||
|
set: gcode_params
|
||
|
|
||
|
- match: ()
|
||
|
set: syntax_error
|
||
|
|
||
|
gcode_string_arg_quoted_single:
|
||
|
- meta_content_scope: string.quoted.single.gcode
|
||
|
|
||
|
- match: ([^'\\]+)
|
||
|
|
||
|
- match: (\\)
|
||
|
scope: punctuation.string.escape.gcode
|
||
|
push: escape_char
|
||
|
|
||
|
- match: (')
|
||
|
scope: punctuation.quote.single.close.gcode
|
||
|
pop: true
|
||
|
|
||
|
- match: ()
|
||
|
set: syntax_error
|
||
|
|
||
|
gcode_string_arg_quoted_double:
|
||
|
- meta_content_scope: string.quoted.double.gcode
|
||
|
|
||
|
- match: ([^"\\]+)
|
||
|
|
||
|
- match: (\\)
|
||
|
scope: punctuation.string.escape.gcode
|
||
|
push: escape_char
|
||
|
|
||
|
- match: (")
|
||
|
scope: punctuation.quote.double.close.gcode
|
||
|
pop: true
|
||
|
|
||
|
- match: ()
|
||
|
set: syntax_error
|
||
|
|
||
|
gcode_string_arg:
|
||
|
- meta_content_scope: ctx.string.gcode
|
||
|
|
||
|
- match: ([^;]+)
|
||
|
scope: string.unquoted.gcode
|
||
|
|
||
|
escape_char:
|
||
|
- meta_scope: string.escape.gcode punctuation.string.escape.gcode
|
||
|
|
||
|
- match: '.'
|
||
|
pop: true
|
||
|
|
||
|
gcode_path_arg:
|
||
|
- meta_content_scope: string.unquoted.path.gcode
|
||
|
|
||
|
- match: (#)
|
||
|
scope: punctuation.string.path.close.gcode
|
||
|
pop: true
|
||
|
|
||
|
gcode_checksum:
|
||
|
- meta_content_scope: constant.numeric.checksum.gcode
|
||
|
- meta_include_prototype: false
|
||
|
|
||
|
- match: \d+
|
||
|
|
||
|
- match: ( *)$
|
||
|
pop: true
|
||
|
|
||
|
- include: mixin_comment
|
||
|
|
||
|
- match: ()
|
||
|
set: syntax_error
|
||
|
|
||
|
# Done interpreting to the end of the line
|
||
|
gcode_line_done:
|
||
|
- match: \s*$
|
||
|
pop: true
|
||
|
|
||
|
# Comments begin with a ';' and finish at the end of the line.
|
||
|
mixin_comment:
|
||
|
- match: ^\s*;
|
||
|
scope: punctuation.comment.line.start
|
||
|
set: gcode_comment
|
||
|
- match: \s*;
|
||
|
scope: punctuation.comment.eol.start
|
||
|
set: gcode_comment
|
||
|
- match: \s*\(
|
||
|
scope: punctuation.paren.comment.open
|
||
|
push: gcode_comment_paren
|
||
|
|
||
|
# Comment to end of line.
|
||
|
gcode_comment:
|
||
|
- meta_content_scope: comment.gcode
|
||
|
- match: \s*$
|
||
|
pop: true
|
||
|
|
||
|
gcode_comment_paren:
|
||
|
- meta_content_scope: paren.comment.gcode
|
||
|
|
||
|
- match: '[^)]+'
|
||
|
|
||
|
- match: '[)]'
|
||
|
scope: punctuation.paren.comment.close
|
||
|
pop: true
|
||
|
|
||
|
- match: \s*$
|
||
|
pop: true
|
||
|
|
||
|
# Everything after this point is broken by a syntax error
|
||
|
syntax_error:
|
||
|
- meta_scope: invalid.error.syntax.gcode
|
||
|
|
||
|
- match: .*$
|
||
|
pop: true
|