%YAML 1.2 --- # See http://www.sublimetext.com/docs/3/syntax.html # Syntax highlighting for: # - ZX BASIC SDK - an enhanced BASIC dialect which compiles to optimized Z80 machine code for the Sinclair ZX Spectrum # - ZX Spectrum Sinclair BASIC # - zmakebas # # Like Sublime Text, ZX BASIC is available for Windows, Linux, and Mac OS - at www.boriel.com # The aim of this syntax definition is to maximise code clarity, not to simply highlight every possible BASIC keyword # Built-in colour scheme 'Mariana' is recommended # ZX BASIC inline assembly highlighting depends on https://github.com/mrcook/Z80Assembly name: ZX BASIC file_extensions: - bas scope: source.zx-basic variables: identifier: \b[[:alpha:]_][[:alnum:]_]*\b #alphabetical char or _, followed by zero or more alphanumeric chars or _ contexts: main: - include: comments - include: labels - include: expressions - include: inline-asm # line numbers - match: '^\s*\d+\s' scope: entity.name.function.line-number.zx-basic # special case for these statements which can contain single quote as a line break, rather than to denote a comment - match: '\b(?i:LPRINT|PRINT|INPUT)\b' push: - meta_content_scope: source.zx-basic - include: expressions - match: ':|$' pop: true # variable types - match: '\b(?i:UBYTE|BYTE|UINTEGER|INTEGER|ULONG|LONG|FIXED|FLOAT|STRING)\b' scope: storage.type.zx-basic # function and subroutine definitions # uncomment the scopes below to highlight FUNCTION and SUB keywords to match ASM keyword # I judged this to be too cluttered, ideally these blocks should be nested for clarity. Inline ASM on the other hand definitely needs emphasis - match: '\b(?i:FUNCTION FASTCALL|FUNCTION|SUB)\b\s*({{identifier}})\b' captures: #0: punctuation.section.group.begin.zx-basic 1: entity.name.function.zx-basic push: - meta_content_scope: meta.function.zx-basic - include: main - match: '\b(?i:END FUNCTION|END SUB)\b' #scope: punctuation.section.group.end.zx-basic pop: true - match: '\b(?i:FOR|NEXT|DO|LOOP|CONTINUE|EXIT)\b' scope: keyword.control.zx-basic - match: '\b(?i:GOTO|GO TO|GOSUB|GO SUB|RETURN)\b' scope: keyword.control.flow.zx-basic - match: '\b(?i:IF|THEN|ELSE|ELSEIF|END IF|WHILE|END WHILE|WEND|UNTIL)\b' scope: keyword.control.conditional.zx-basic # too visually distracting - sometimes less is more. I prefer to accentuate only the control keywords and the custom functions (and arrays) #- match: '\b(?i:CHR\$|INKEY\$|SCREEN\$|STR\$)|\b(?i:ABS|ACS|ASN|ATN|CAST|CHR|CODE|COS|EXP|IN|INKEY|INPUT|INT|LBOUND|LEN|LN|PEEK|SCREEN|SGN|SIN|SQR|STR|TAN|UBOUND|VAL)\b' # scope: support.function.zx-basic # too visually distracting - sometimes less is more #- match: '\b(?i:AND|NOT|OR|XOR|BAND|BNOT|BOR|BXOR|SHL|SHR|<<|>>)\b' # scope: keyword.operator.word.zx-basic # function or sub call, however this is indistinguishable from an array reference since the syntax is analysed one line at a time with REGEXP matching only - match: (?={{identifier}}\s*\() push: - meta_content_scope: meta.function-call.zx-basic - match: '(?!\b[A-Z]+\b){{identifier}}' #exclude identifiers in all caps which are likely to be BASIC native functions scope: variable.function.zx-basic - match: '\(' scope: meta.group.zx-basic punctuation.section.group.begin.zx-basic set: - include: main - meta_content_scope: meta.function-call.zx-basic meta.group.zx-basic - match : \) scope: meta.function-call.zx-basic meta.group.zx-basic punctuation.section.group.end.zx-basic pop: true expressions: - include: strings - match: '(%[0-1]+|\b[0-1]+b)\b' scope: constant.numeric.integer.binary.zx-basic # although it's not in the spec, 0x prefixed hex numbers do seem to be required as parameters for HRPrint library (high res print) - match: '(\$[A-Fa-f0-9]+|\b(?i:0x)[A-Fa-f0-9]+|\b[A-Fa-f0-9]+h)\b' scope: constant.numeric.integer.hexadecimal.zx-basic - match: '\b\d+(\.\d+)?\b' scope: constant.numeric.zx-basic - match: '<\=|>\=|<|>' scope: keyword.operator.comparison.zx-basic - match: '\+|\-|\*|/|<<|>>|\^|~|\b(?i:MOD)\b' scope: keyword.operator.arithmetic.zx-basic - match: '@' scope: keyword.operator.zx-basic - match: '\=' scope: keyword.operator.assignment.zx-basic - match: '_|\\$' scope: punctuation.separator.continuation.zx-basic - match: ':|,|;|''' scope: punctuation.separator.zx-basic strings: - match: '"' scope: punctuation.definition.string.begin.zx-basic push: - meta_scope: string.quoted.double.zx-basic # you can break a string over multiple lines in zmakebas - match: '\\$' scope: punctuation.separator.continuation.zx-basic # valid escape character sequences from https://zxbasic.readthedocs.io/en/docs/syntax/#graphic-characters # these have to be escaped in for YAML first, then for the REGEXP, then for the compiler! # note the trailing empty match to ensure a single \ is highlighted as an escape character - match: '\\(\\|\*|\`|\#[0-9]{3}|\{i[0-8]\}|\{p[0-8]\}|\{b[0-1]\}|\{f[0-1]\}|[a-u]|[A-U]|\ | ''|\'' |''''| \.| :|\''\.|'':|\. |\.''|: |:''|\.\.|\.:|:\.|::)' scope: constant.character.escape.zx-basic # valid zmakebas escape character sequences from https://github.com/chris-y/zmakebas#user-defined-graphics-udg - match: '\\(\{[0-9]{1,3}\}|\{0x[A-Za-z0-9]{1,2}\}|@)' scope: constant.character.escape.zx-basic # a quote can be escaped by using a double quote within a string - match: '""' scope: constant.character.escape.zx-basic - match: '"' scope: punctuation.definition.string.end.zx-basic pop: true #zmakebas labels labels: - match: '@[0-9A-Za-z_-]*' scope: entity.name.function.line-number.zx-basic comments: # Note that blackslashes don't need to be escaped within single quoted # strings in YAML. When using single quoted strings, only single quotes # need to be escaped: this is done by using two single quotes next to each # other. - include: preprocessor # ZX BASIC comments follow a single quote # Sinclair BASIC comments follow REM # zmakebas comments must start the line with hash - match: '''|\b(?i)REM\b|^#' scope: punctuation.definition.comment.zx-basic push: - meta_scope: comment.line.zx-basic - match: $ pop: true - match: '/''' scope: punctuation.definition.comment.begin.zx-basic push: - meta_scope: comment.block.zx-basic - match: '''/' scope: punctuation.definition.comment.end.zx-basic pop: true preprocessor: - match: '^\s*(#\s*(?:(?i)include))\b' captures: 1: keyword.control.import.include.zx-basic push: - meta_scope: meta.preprocessor.include.zx-basic - match: '"' scope: punctuation.definition.string.begin.zx-basic push: - meta_scope: string.quoted.double.include.zx-basic - match: '"' scope: punctuation.definition.string.end.zx-basic pop: true - match: < scope: punctuation.definition.string.begin.zx-basic push: - meta_scope: string.quoted.other.lt-gt.include.zx-basic - match: ">" scope: punctuation.definition.string.end.zx-basic pop: true - match: $ pop: true - match: '^\s*(#\s*(?i)define)\b' captures: 1: keyword.control.import.define.zx-basic push: - meta_content_scope: meta.preprocessor.macro.zx-basic - include: main - match: $ pop: true inline-asm: #use an external syntax for ASM, e.g.: https://github.com/mrcook/SkoolkitZ80 or https://github.com/mrcook/Z80Assembly #his doesn't work so well because this one in particular is quite dependent on a dedicated theme - non-standard scopes perhaps? - match: '\b(?i:ASM)\b' scope: punctuation.section.group.begin.zx-basic push: Packages/User/Z80Assembly.tmLanguage.sublime-syntax with_prototype: - match: '\b(?i:END ASM)\b' scope: punctuation.section.group.end.zx-basic pop: true # inline-asm: # - match: '\b(?i:ASM)\b' # scope: punctuation.section.group.begin.zx-basic # push: # - meta_content_scope: meta.function.inline-asm.zx-basic # - include: asm-comments #comments are highlighted as a bare minimum, but not much else as this is not my focus # #try the commented block below as a replacement for this context if you need ASM highlighting # - match: '\b(?i:END ASM)\b' # scope: punctuation.section.group.end.zx-basic # pop: true # # # # asm-comments: # #asm comments begin with ; and finish at the end of the line # - match: ';' # scope: punctuation.definition.comment.inline-asm.zx-basic # push: # - meta_scope: comment.line.inline-asm.zx-basic # - match: $ # pop: true