diff --git a/WolframLanguage.sublime-syntax b/WolframLanguage.sublime-syntax index 6557c64..377f501 100644 --- a/WolframLanguage.sublime-syntax +++ b/WolframLanguage.sublime-syntax @@ -10,7 +10,6 @@ file_extensions: - m - wl - wls - # FIXME: special process when rendering .nb file - nb first_line_match: ^#!.*\b(math|wolfram).*$ @@ -19,8 +18,9 @@ scope: source.wolfram # Partly based on https://github.com/JuliaEditorSupport/Julia-sublime/blob/master/Julia.sublime-syntax variables: + number: (?:\d+\.?|\.\d)\d* symbol: '[$[:alpha:]]+[$[:alnum:]]*' - identifier: (?:{{symbol}}`)*({{symbol}}) + identifier: (?:{{symbol}}`)*{{symbol}} # Built-in functions built_in_functions: |- @@ -47,16 +47,15 @@ variables: Catalan|Degree|E|EulerGamma|Glaisher|GoldenAngle|GoldenRatio|I|Khinchin|MachinePrecision|Pi )\b - nb_code_styles: (Input) - + scoping_functions: Block|Module|With|Function|DynamicModule contexts: main: - - include: declarations - include: expressions expressions: + - include: declarations - include: pattern - include: expressions-nopattern @@ -65,14 +64,12 @@ contexts: - include: literals - include: shorthand - include: operators - - include: pattern-short - - include: scoping - include: function - include: variable - include: nested comments: - - match: '(\(\*\s*)(::)([[:alnum:]]+)(::)(\s*\*\))' + - match: (\(\*\s*)(::)([[:alnum:]]+)(::)(\s*\*\)) captures: 1: comment.line.wolfram 2: constant.numeric.line-number.find-in-files @@ -83,21 +80,45 @@ contexts: push: comment-block comment-block: - - meta_scope: comment.block.wolfram - - match: \(\* - push: comment-block - - match: \*\) - pop: true + - meta_scope: comment.block.wolfram + - match: \(\* + push: comment-block + - match: \*\) + pop: true literals: - - match: (?:\d+\.?|\.\d)\d*\`{0,2} - scope: constant.numeric.wolfram + - match: |- + (?x) + (?: + ([1-9]\d*\^\^) # base + ((?:[[:alnum:]]+\.?|\.[[:alnum:]])[[:alnum:]]*) # value + | + ({{number}}) # value + ) + (?: + (\`\`(?:{{number}})?) # accuracy + | + (\`(?:{{number}})?) # precision + )? + (\*\^[+-]?{{number}})? # exponent + scope: meta.numeric.wolfram + captures: + 1: constant.numeric.base.wolfram + 2: constant.numeric.wolfram + 3: constant.numeric.wolfram + 4: constant.numeric.accuracy.wolfram + 5: constant.numeric.precision.wolfram + 6: constant.numeric.exponent.wolfram + + # built-in symbols - match: ((?:System`)?{{built_in_numeric_constants}}) scope: constant.numeric.wolfram - match: ((?:System`)?{{built_in_constants}}) scope: constant.language.wolfram - match: ((?:System`)?{{built_in_options}}) - scope: variable.function.wolfram + scope: variable.parameter.wolfram + + # strings - match: \" scope: punctuation.definition.string.begin push: @@ -115,15 +136,33 @@ contexts: scope: constant.other.placeholder.wolfram shorthand: + # Out + - match: '%(\d*|%*)' + scope: storage.type.Out.wolfram + + # MessageName - match: (::)\s*([[:alnum:]]+) captures: 1: keyword.operator.MessageName.wolfram 2: string.unquoted.wolfram - # ENHANCEMENT: infix - - match: (//)\s*({{identifier}}) + + # Infix + - match: ~ + scope: keyword.operator.call.wolfram + push: + - meta_content_scope: meta.infix.wolfram + - match: ({{identifier}})?\s*(~) + captures: + 1: variable.function.wolfram + 2: keyword.operator.call.wolfram + pop: true + - include: expressions + + # Postfix and compound functions + - match: (//|[@/]\*)\s*({{identifier}}) captures: - 1: keyword.operator.Postfix.wolfram - 3: variable.function.wolfram + 1: keyword.operator.call.wolfram + 2: variable.function.wolfram operators: - match: (@\*|@{1,3}|\/[@*]) @@ -136,9 +175,9 @@ contexts: scope: keyword.operator.logical.wolfram - match: (:?=|\/:|[-:]>|[+\-*/]=|<->) scope: keyword.operator.assignment.wolfram - - match: '\/;' + - match: \/; scope: keyword.operator.condition.wolfram - - match: (\+\+|--|[+\-*/]) + - match: (\+\+|--|[+\-*/^]) scope: keyword.operator.arithmetic.wolfram - match: (>>>?|<<=]) - captures: - 1: keyword.operator.Optional.wolfram - pop: true - - match: (?=.) - pop: true + scope: keyword.operator.function variable.function.wolfram + - match: \?\?? + scope: keyword.operator.definition.wolfram pattern: - - match: '({{identifier}})\s*(:(?=[^:>=]))' + - match: ({{identifier}})\s*(:(?=[^:>=])) captures: 1: variable.parameter.wolfram - 3: keyword.operator.Pattern.wolfram + 2: keyword.operator.Pattern.wolfram push: - meta_content_scope: meta.pattern.wolfram - match: \? scope: keyword.operator.PatternTest.wolfram - - match: ':(?=[^:>=])' + - match: :(?=[^:>=]) scope: keyword.operator.Optional.wolfram pop: true # we should check the precedence here @@ -190,54 +213,84 @@ contexts: pop: true - include: expressions-nopattern - function: - - match: ({{identifier}})\s*(\[(?!\[)) + variable: + # parameters + - match: |- + (?x) + ({{identifier}})? + (?: + (_\.) # Default + | + (_{1,3}) # Blank, BlankSequence, BlankNullSequence + ({{identifier}})? # Head + ) + scope: meta.parameter.wolfram captures: - 1: variable.function.wolfram - 3: punctuation.section.brackets.begin.wolfram - push: - - meta_scope: meta.block.wolfram - - match: \] - scope: punctuation.section.brackets.end.wolfram + 1: variable.parameter.wolfram + 2: variable.parameter.default.wolfram + 3: variable.parameter.blank.wolfram + 4: variable.parameter.head.wolfram + push: + - match: (?:\s*)(\?) # PatternTest + scope: meta.pattern.wolfram + captures: + 1: keyword.operator.PatternTest.wolfram pop: true - - include: expressions - - match: ({{identifier}})(?=\s*(@\*|@{1,3}|\/[@*])) - scope: variable.function.wolfram - - variable: - - match: '(?:System`)?({{built_in_functions}})' + - match: (?:\s*)(:)(?=[^:>=]) # Optional + scope: meta.pattern.wolfram + captures: + 1: keyword.operator.Optional.wolfram + pop: true + - match: (?=.) + pop: true + + # variables + - match: (?:System`)?({{built_in_functions}}) scope: variable.function - match: '{{identifier}}' scope: variable.other + + # slots - match: (#[a-zA-Z][[:alnum:]]*|#\d*) scope: variable.parameter - scoping: - - match: (Block|Module|With|Function)\s*(\[(?!\[)) + function: + # scoping functions + - match: ({{scoping_functions}})\s*(\[(?!\[)) captures: 1: variable.function.scoping.wolfram 2: punctuation.section.brackets.begin.wolfram push: - meta_content_scope: meta.block.wolfram - - match: '\{' + - match: \{ + scope: punctuation.section.braces.begin.wolfram set: [localized, local] - - match: '\]' - scope: punctuation.section.brackets.end.wolfram - pop: true - - include: expressions + - include: meta-block + + # general functions + - match: ({{identifier}})\s*(\[(?!\[)) + captures: + 1: variable.function.wolfram + 3: punctuation.section.brackets.begin.wolfram + push: meta-block + - match: ({{identifier}})\s*(?=@{1,3}|//?@) + scope: variable.function.wolfram localized: - meta_content_scope: meta.block.local.wolfram - - match: '\,' + - match: ',' + scope: punctuation.separator.sequence.wolfram push: local - - match: '\}' + - match: \} + scope: punctuation.section.braces.end.wolfram set: - meta_content_scope: meta.block.wolfram - - match: '\]' + - match: \] scope: punctuation.section.brackets.end.wolfram pop: true - include: expressions - - match: '\]' + - match: \] + scope: punctuation.section.brackets.end.wolfram pop: true - include: expressions @@ -249,7 +302,6 @@ contexts: pop: true - include: expressions - declarations: - match: |- (?x) @@ -278,8 +330,22 @@ contexts: - include: sequence - match: (?=[^\[]) pop: true - - match: ((?:{{symbol}}`)*(\${{symbol}}))(?=\s*:?=) - scope: entity.name.constant.wolfram + # - match: ((?:{{symbol}}`)*(\${{symbol}}))(?=\s*:?=) + # scope: entity.name.constant.wolfram + - match: |- + (?x) + {{identifier}} + (?= + \s*:?=\s* + ( + [^\(\)]+| + \((?>\g<-1>)*\) + )* + &(;|$) + ) + scope: entity.name.function.wolfram + - match: ({{identifier}})(?=\s*:?=\s*Function\s*\[(?!\s*\[)) + scope: entity.name.function.wolfram sequence: - meta_scope: meta.sequence.wolfram @@ -330,3 +396,17 @@ contexts: scope: punctuation.section.association.end.wolfram pop: true - include: expressions + + meta-block: + - meta_scope: meta.block.wolfram + - match: \] + scope: punctuation.section.brackets.end.wolfram + pop: true + - include: expressions + + meta-parameter: + - meta_scope: meta.parameter.wolfram + - match: \} + scope: punctuation.section.braces.end.wolfram + pop: true + - include: expressions diff --git a/syntax_test_wolfram_language.wl b/syntax_test_wolfram_language.wl index 35a354b..3792ea3 100644 --- a/syntax_test_wolfram_language.wl +++ b/syntax_test_wolfram_language.wl @@ -8,18 +8,24 @@ (* NUMBERS *) - 11 -(* ^^ constant.numeric *) - .11 -(* ^^^ constant.numeric *) - 11. -(* ^^^ constant.numeric *) - 11.11 -(* ^^^^^ constant.numeric *) - 11.11` -(* ^^^^^^ constant.numeric *) - 11.11`11.11 -(* ^^^^^^^^^^^ constant.numeric *) + 11` +(*^^ constant.numeric *) +(* ^ constant.numeric.precision *) + 11.`11 +(*^^^ constant.numeric *) +(* ^^^ constant.numeric.precision *) + .11`` +(*^^^ constant.numeric *) +(* ^^ constant.numeric.accuracy *) + 11.11``11 +(*^^^^^ constant.numeric *) +(* ^^^^ constant.numeric.accuracy *) + 11^^1a +(*^^^^ constant.numeric.base *) +(* ^^ constant.numeric *) + 11.11*^-11 +(*^^^^^ constant.numeric.wolfram *) +(* ^^^^^ constant.numeric.exponent *) (* NUMERIC CONSTANTS *) @@ -45,6 +51,8 @@ (*^ keyword.operator.arithmetic*) * (*^ keyword.operator.arithmetic*) + ^ +(*^ keyword.operator.arithmetic*) ! (*^ keyword.operator.logical*) @@ -69,19 +77,19 @@ (*^^^ keyword.operator.comparison*) @ -(* ^ keyword.operator *) +(* ^ keyword.operator.call *) @@ -(* ^^ keyword.operator *) +(* ^^ keyword.operator.call *) @@@ -(* ^^^ keyword.operator *) +(* ^^^ keyword.operator.call *) @* -(* ^^ keyword.operator *) +(* ^^ keyword.operator.call *) /* -(* ^^ keyword.operator *) +(* ^^ keyword.operator.call *) /@ -(* ^^ keyword.operator *) +(* ^^ keyword.operator.call *) /; -(* ^^ keyword.operator *) +(* ^^ keyword.operator.condition *) // (* ^^ keyword.operator *) /: @@ -97,8 +105,14 @@ <-> (* ^^^ keyword.operator *) + (* VARIABLES *) + %%% +(*^^^ storage.type.Out *) + %12 +(*^^^ storage.type.Out *) + f[x] (*^ variable.function*) foo$bar12 @@ -115,33 +129,48 @@ Image[Red, Interleaving -> True] (*^^^^^ variable.function *) -(* ^ constant.language *) (* seems wrong to me *) -(* ^^^^^^^^^^^^ variable.function.wolfram *) +(* ^ constant.language *) +(* ^^^^^^^^^^^^ variable.parameter *) (* ^^ keyword.operator *) + Sum[x, {x, 1, 100}] +(* ^ variable.parameter *) + + Map[func, list] +(* ^^^^ variable.function *) + + TakeWhile[list, func] +(* ^^^^ variable.function *) + + a ~ f ~ b ~ g ~ c +(* ^ variable.function *) +(* ^ variable.function *) + (* PATTERNS *) - var_head foo -(*^^^^^^^^ meta.pattern.blank.wolfram variable.parameter.wolfram *) -(* ^ variable.other *) + _. +(*^^ variable.parameter.default *) + + var_head +(*^^^^^^^^ meta.parameter *) +(*^^^ variable.parameter *) +(* ^ variable.parameter.blank *) +(* ^^^^ variable.parameter.head *) - var_head:foo -(*^^^^^^^^ meta.pattern.blank.wolfram variable.parameter.wolfram *) -(* ^ meta.pattern.blank.wolfram keyword.operator.Optional.wolfram *) -(* ^^^ variable.other *) + var__head : foo +(* ^ meta.pattern keyword.operator.Optional *) - var_head ? EvenQ -(*^^^^^^^^ meta.pattern.blank.wolfram variable.parameter.wolfram *) -(* ^ meta.pattern.blank.wolfram keyword.operator.PatternTest.wolfram *) -(* ^^^^^ variable.function *) + var___head ? EvenQ +(* ^ meta.pattern keyword.operator.PatternTest *) var: patt ? EvenQ : foo -(*^^^ variable.parameter.wolfram *) -(* ^ keyword.operator.Pattern.wolfram *) -(* ^^^ meta.pattern.wolfram variable.other *) -(* ^ meta.pattern.wolfram keyword.operator.PatternTest.wolfram *) -(* ^^^^^ meta.pattern.wolfram variable.function *) -(* ^ keyword.operator.Optional.wolfram *) +(*^^^ variable.parameter *) +(* ^ keyword.operator.Pattern *) +(* ^^^^^^^^^^^^ meta.pattern *) +(* ^^^^ variable.other*) +(* ^ keyword.operator.PatternTest *) +(* ^^^^^ variable.function *) +(* ^ keyword.operator.Optional *) (* ^^^ variable.other *) @@ -180,6 +209,12 @@ f[x_] /; x > 0 := x (*^ entity.name.function *) + f = Function[x, x ^ 2] +(*^ entity.name.function *) + + f = # ^ 2 &; +(*^ entity.name.function *) + f[[]]