Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve syntax highlighting #18

Merged
merged 34 commits into from
Sep 10, 2024
Merged
Changes from 28 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
21055f1
Rework comment syntax
jiribenes Jul 19, 2024
3802d3c
Rework strings, add splices, add characters
jiribenes Jul 19, 2024
f6198d8
Reformat file to conform to the current style
jiribenes Jul 19, 2024
e7af33d
Make a separate class for capabilities
jiribenes Jul 19, 2024
a078110
Parse namespace declarations
jiribenes Jul 19, 2024
f6a6d2a
Support capability sets precisely
jiribenes Jul 19, 2024
5765516
Add folding markers
jiribenes Jul 19, 2024
00a0c32
Try to keep a common style throughout the file
jiribenes Jul 19, 2024
cb491ef
Characters can be top-level, escapes synced with lexer
jiribenes Jul 19, 2024
d82dc85
Fix multi-line strings parsed as single-line
jiribenes Jul 19, 2024
45e1173
Add float literals
jiribenes Jul 19, 2024
2739c27
Try to parse extern defs properly
jiribenes Jul 19, 2024
93c019e
Improve typed hole parsing
jiribenes Jul 19, 2024
9c2b2d3
Simplify and extract literals
jiribenes Jul 19, 2024
23d911f
Add supported operators
jiribenes Jul 19, 2024
b2cfffb
Ensure naming conventions are consistent
jiribenes Jul 19, 2024
daaecec
Reformat
jiribenes Jul 19, 2024
dc5fc7f
Reorganize keywords
jiribenes Jul 19, 2024
94ce3e1
Make 'in' a conditional keyword only
jiribenes Jul 20, 2024
974f89d
Definitions shouldn't be stopped by '=>'
jiribenes Jul 20, 2024
1d7d365
More sofisticated end-stops for definitions
jiribenes Jul 20, 2024
812bb81
Support boxed types: 'at {io, global}'
jiribenes Jul 20, 2024
1df2a1b
Fix highlighting type annotations in variables
jiribenes Jul 20, 2024
7dc2c36
Simplify end patterns further
jiribenes Jul 20, 2024
e00c154
Refactor escapes, highlight invalid escapes
jiribenes Jul 20, 2024
edb6a54
Literals have a priority over names
jiribenes Jul 21, 2024
4ae4bdb
Clarify TextMate scopes, fix bugs, add 'module'
jiribenes Jul 21, 2024
2a30140
Add first-class support for regions
jiribenes Jul 21, 2024
65bc391
Add proper support for modules and imports
jiribenes Jul 21, 2024
9052cf5
Use 'keyword.other' to comply with standard TextMate scopes
jiribenes Jul 21, 2024
f6188ec
Region references are also capabilities
jiribenes Jul 22, 2024
35dc0f6
Distinguish the 'global' region as a builtin
jiribenes Jul 22, 2024
00ec30b
Remove duplicate keyword
jiribenes Jul 22, 2024
2d69df2
Resolve keywords, remove 'as'
jiribenes Jul 23, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
275 changes: 219 additions & 56 deletions syntaxes/effekt.tmLanguage.json
Original file line number Diff line number Diff line change
@@ -1,123 +1,286 @@
{
"$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
"name": "Effekt",
"foldingStartMarker": "(?<![\"'])(/\\*\\*|\\{\\s*$)",
"foldingStopMarker": "(?<![\"'])(\\*\\*/|^\\s*\\})",
"patterns": [
{ "include": "#comments" },
{ "include": "#definitions" },
{ "include": "#regions" },
{ "include": "#keywords" },
{ "include": "#boxed_types" },
{ "include": "#literals" },
{ "include": "#names" },
{ "include": "#strings" },
{ "include": "#numbers" },
{ "include": "#holes" }
{ "include": "#holes" },
{ "include": "#operators" }
],
"repository": {
"comments": {
"patterns": [
{
"match": "//.*$\n?",
"name": "comment.line.double-slash.syntax"
"patterns": [{
"begin": "//",
"end": "\\n",
"beginCaptures": {
"0": { "name": "punctuation.definition.comment.effekt" }
},
{
"begin": "\\s*+(\\/\\*)",
"end": "\\*\\/",
"name": "comment.multiline.syntax"
}
]
"name": "comment.line.double-slash.effekt"
}, {
"begin": "/\\*",
"beginCaptures": {
"0": { "name": "punctuation.definition.comment.effekt" }
},
"end": "\\*/",
"endCaptures": {
"0": { "name": "punctuation.definition.comment.effekt" }
},
"name": "comment.block.effekt"
}]
},
"definitions": {
"patterns": [{
"begin": "\\s*(extern)?\\s*(\\{[^\\}]*\\}|[a-zA-Z][a-z-A-Z0-9_$]*)\\s*(def)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"end" : "[=\\n]",
"beginCaptures": {
"1": { "name": "keyword.declaration.type" },
"2": { "name": "entity.name.type" },
"3": { "name": "keyword.declaration.function" },
"4": { "name": "entity.name.function" }
"begin": "\\s*(extern)\\s+((?:(?:\\{[^\\}]*\\}|[a-zA-Z][a-z-A-Z0-9_$]*)\\s+)?)\\s*(def)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"end": "(?=\\n)|(?<=\\S)\\s*(?==(?!>))",
"captures": {
"1": { "name": "storage.modifier.extern.effekt" },
"2": { "patterns": [{ "include": "#capabilities" }] },
"3": { "name": "keyword.declaration.function.extern.effekt" },
"4": { "name": "entity.name.function.effekt" }
},
"patterns": [{ "include": "#parameters" }]
}, {
"begin": "\\s*(def)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"end": "(?=\\n)|(?<=\\S)\\s*(?==(?!>))",
"captures": {
"1": { "name": "keyword.declaration.function.effekt" },
"2": { "name": "entity.name.function.effekt" }
},
"patterns": [{ "include": "#parameters" }]
}, {
"match": "\\s*(val)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"captures": {
"1": { "name": "keyword.declaration.val" },
"2": { "name": "variable" }
"1": { "name": "keyword.declaration.val.effekt" },
"2": { "name": "variable.other.effekt" }
}
}, {
"begin": "\\s*(var)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"beginCaptures": {
"1": { "name": "keyword.declaration.var.effekt" },
"2": { "name": "variable.other.effekt" }
},
"end": "(?:;|(?=\\n)|(?<=\\S)\\s*(?==(?!>)))",
"patterns": [{
"match": "\\s+(in)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"captures": {
"1": { "name": "keyword.syntax.in.effekt" },
"2": { "name": "entity.name.region.effekt" }
jiribenes marked this conversation as resolved.
Show resolved Hide resolved
}
}, {
"include": "#parameters"
}]
}, {
"match": "\\s*(extern)?\\s*(type|effect|interface|resource)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"captures": {
"1": { "name": "storage.modifier.extern.effekt" },
"2": { "name": "keyword.declaration.type.effekt" },
"3": { "name": "entity.name.type.effekt" }
}
}, {
"match": "\\s*(var)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"match": "\\s*(namespace)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"captures": {
"1": { "name": "keyword.declaration.var" },
"2": { "name": "variable" }
"1": { "name": "keyword.declaration.namespace.effekt" },
"2": { "name": "entity.name.namespace.effekt" }
}
}, {
"match": "\\s*(extern)?\\s*(type|effect|interface|resource)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"match": "\\s*(module)\\s+([a-zA-Z][a-z-A-Z0-9_$]*)\\b",
"captures": {
"1": { "name": "keyword.declaration.type" },
"2": { "name": "keyword.declaration.type" },
"3": { "name": "entity.name.type" }
"1": { "name": "keyword.declaration.module.effekt" },
"2": { "name": "entity.name.module.effekt" }
}
}]
},
"boxed_types": {
"comment": "Used for boxed types like 'at {}', 'at {io}', 'at {io, global}', etc.",
"patterns": [{
"begin": "\\b(at)\\s*\\{",
"beginCaptures": {
"1": { "name": "keyword.other.at.effekt" }
},
"end": "\\}",
"patterns": [{
"include": "#capabilities"
}]
}]
},
"parameters": {
"patterns": [{
"include": "#boxed_types"
}, {
"match": "\\b([a-z][a-zA-Z0-9_$]*)(?:)",
"name": "variable.parameter"
"name": "variable.parameter.effekt"
}, {
"match": "\\b([A-Z][a-zA-Z0-9_$]*)(?:)",
"name": "entity.name.type"
"name": "entity.name.type.effekt"
}]
},
"capabilities": {
"patterns": [{
"match": "\\b(pure)\\b",
"name": "keyword.other.capability.pure.effekt"
}, {
"match": "\\b([a-z][a-zA-Z0-9_]*)\\b",
"name": "variable.other.capability.effekt"
}, {
"match": ",",
"name": "punctuation.separator.capability.effekt"
}]
},
"keywords": {
"patterns": [{
"match": "\\b(module|import|def|fun|val|var|effect|type|match|case|record|extern|include|box|unbox|in|region|new|resource|interface|namespace|module|include|export|as)\\b",
"name": "keyword.syntax"
"match": "\\b(module|import|def|fun|val|var|effect|type|record|include|box|unbox|region|new|resource|interface|namespace|module|include|export|as)\\b",
"name": "keyword.syntax.effekt"
}, {
"match": "\\b(resume|return)\\b",
"name": "keyword.control.jump.effekt"
}, {
"match": "\\b(do|try|with)\\b",
"name": "keyword.control.effect.effekt"
}, {
"match": "\\b(while|match|case|if|else)\\b",
"name": "keyword.control.flow.effekt"
}, {
"match": "\\b(is|and)\\b",
"name": "keyword.operator.effekt"
jiribenes marked this conversation as resolved.
Show resolved Hide resolved
}, {
"match": "\\b(resume|while|try|with|if|else|do|return|is|and)\\b",
"name": "keyword.control"
"match": "\\b(extern)\\b",
"name": "storage.modifier.extern.effekt"
}]
},
"names": {
"literals": {
"patterns": [{
"match": "\\b(true|false)\\b",
"name": "constant.language"
"name": "constant.language.boolean.effekt"
}, {
"match": "\\b([a-z][a-zA-Z0-9_]*)\\b[\\s]*[({\\[]",
"captures": {
"1": { "name": "entity.name.function" }
}
"match": "\\b([0-9]+\\.[0-9]+)\\b",
"name": "constant.numeric.float.effekt"
}, {
"match": "\\b[a-z][a-zA-Z0-9_]*\\b",
"name": "variable"
"match": "\\b([0-9]+)\\b",
"name": "constant.numeric.integer.effekt"
}, {
"match": "\\b[A-Z][a-zA-Z0-9_]*\\b",
"name": "entity.name.type"
"include": "#characters"
}, {
"include": "#strings"
}]
},
"characters": {
"name": "string.quoted.single.effekt",
"begin": "'",
"end": "'",
"patterns": [{
"include": "#escapes"
}, {
"include": "#invalidEscapes"
}]
},
"strings": {
"patterns": [{
"name": "string.quoted.triple.effekt",
"begin": "\"\"\"",
"end": "\"\"\"",
"comment": "Important: only single-line strings can have escapes!",
"patterns": [{
"include": "#stringTemplates"
}]
}, {
"name": "string.quoted.double.effekt",
"begin": "\"",
"end": "\"",
"name": "string.quoted.double.literal"
"patterns": [{
"include": "#escapes"
}, {
"include": "#invalidEscapes"
}, {
"include": "#stringTemplates"
}]
}]
},
"numbers": {
"escapes": {
"match": "\\\\([btnfr\\\\\"']|u[0-9A-Fa-f]{4})",
"name": "constant.character.escape.effekt"
},
"invalidEscapes": {
"match": "\\\\.",
"name": "invalid.illegal.unknown-escape.effekt",
"comment": "Represents any possible escape, therefore should always be used _after_ #escapes!"
},
"names": {
"patterns": [{
"match": "\\b[0-9]+",
"name": "constant.numeric"
"match": "\\b([a-z][a-zA-Z0-9_]*)\\b[\\s]*[({\\[]",
"captures": {
"1": { "name": "entity.name.function.effekt" }
}
}, {
"match": "\\b[a-z][a-zA-Z0-9_]*\\b",
"name": "variable.other.effekt"
}, {
"match": "\\b[A-Z][a-zA-Z0-9_]*\\b",
"name": "entity.name.type.effekt"
}]
},
"stringTemplates": {
"begin": "\\$\\{",
"beginCaptures": {
"0": { "name": "punctuation.definition.template-expression.begin.effekt" }
},
"end": "\\}",
"endCaptures": {
"0": { "name": "punctuation.definition.template-expression.end.effekt" }
},
"name": "meta.embedded.line.effekt",
"patterns": [
{ "include": "$self" }
]
},
"punctuation": {
"patterns": [{
"match": "[{}\\(\\)\\[\\];,]",
"name": "punctuation.separator"
"name": "punctuation.separator.effekt"
}]
},
"holes": {
"begin": "<{",
"end": "}>",
"name": "meta.hole.effekt",
"patterns": [{
"begin": "<{",
"end" : "}>",
"name": "effekt.hole",
"patterns": [{
"include": "source.effekt"
}]
"include": "$self"
}]
},
"operators": {
"patterns": [{
"match": "\\|\\||&&",
"name": "keyword.operator.logical.effekt"
}, {
"match": "==|!=|<=|>=|<|>",
"name": "keyword.operator.comparison.effekt"
}, {
"match": "\\+\\+",
"name": "keyword.operator.concatenation.effekt"
}, {
"match": "\\+|-|\\*|/",
"name": "keyword.operator.arithmetic.effekt"
}, {
"match": "::",
"name": "keyword.operator.namespace.effekt"
}, {
"match": "=>",
"name": "keyword.operator.arrow.effekt"
}]
},
"regions": {
"patterns": [{
"match": "\\b(region)\\s+([a-zA-Z][a-zA-Z0-9_]*)\\b",
"captures": {
"1": { "name": "keyword.syntax.region.effekt" },
"2": { "name": "entity.name.region.effekt" }
}
}]
}
},
Expand Down
Loading