Skip to content

Commit

Permalink
Merge pull request #14 from SWAT-engineering/pico-vscode-extension
Browse files Browse the repository at this point in the history
Pico VS Code extension
  • Loading branch information
sungshik authored Sep 2, 2024
2 parents 1a3b465 + 7c7bec8 commit c7ed45e
Show file tree
Hide file tree
Showing 9 changed files with 360 additions and 75 deletions.
3 changes: 2 additions & 1 deletion rascal-textmate-core/src/main/rascal/Main.rsc
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ module Main
import Grammar;
import lang::textmate::Conversion;
import lang::textmate::Grammar;
import lang::textmate::NameGeneration;

int main(type[&T <: Tree] tree, str scopeName, loc f) {
RscGrammar rsc = Grammar::grammar(tree);
return main(rsc, scopeName, f);
}

int main(RscGrammar rsc, str scopeName, loc l) {
TmGrammar tm = toTmGrammar(rsc, scopeName);
TmGrammar tm = toTmGrammar(rsc, scopeName, nameGeneration = short());
toJSON(tm, indent = 2, l = l);
return 0;
}
63 changes: 6 additions & 57 deletions rascal-textmate-core/src/main/rascal/VSCode.rsc
Original file line number Diff line number Diff line change
@@ -1,66 +1,15 @@
@synopsis{
Main function to generate a new TextMate grammar for use in the special VS
Code extension
Main function to generate new TextMate grammars for Rascal and Pico, to be
used in the special VS Code extension
}

module VSCode

import Grammar;
import lang::rascal::\syntax::Rascal;
import lang::textmate::Conversion;
import lang::textmate::Grammar;
import lang::textmate::NameGeneration;
import VSCodePico;
import VSCodeRascal;

int main() {
str scopeName = "source.rascalmpl.injection";
RscGrammar rsc = getRscGrammar();
TmGrammar tm = toTmGrammar(rsc, scopeName, nameGeneration = short())[injectionSelector = "R:source.rascalmpl"];
toJSON(tm, indent = 2, l = |project://vscode-extension/syntaxes/rascal.tmLanguage.json|);
VSCodePico::main();
VSCodeRascal::main();
return 0;
}

RscGrammar getRscGrammar() {
Production setCategory(p: prod(_, _, attributes), str category)
= {\tag("category"(_)), *rest} := attributes
? p[attributes = rest + \tag("category"(category))]
: p[attributes = attributes + \tag("category"(category))];

return visit (Grammar::grammar(#Module)) {

// The following mapping is based on:
// - https://github.com/usethesource/rascal/blob/83023f60a6eb9df7a19ccc7a4194b513ac7b7157/src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L44-L59
// - https://github.com/usethesource/rascal-language-servers/blob/752fea3ea09101e5b22ee426b11c5e36db880225/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/SemanticTokenizer.java#L121-L142
// With updates based on:
// - https://github.com/eclipse-lsp4j/lsp4j/blob/f235e91fbe2e45f62e185bbb9f6d21bed48eb2b9/org.eclipse.lsp4j/src/main/java/org/eclipse/lsp4j/Protocol.xtend#L5639-L5695
// - https://github.com/usethesource/rascal-language-servers/blob/88be4a326128da8c81d581c2b918b4927f2185be/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/SemanticTokenizer.java#L134-L152
case \tag("category"("Normal")) => \tag("category"("source"))
case \tag("category"("Type")) => \tag("category"("type")) // Updated (before: storage.type)
case \tag("category"("Identifier")) => \tag("category"("variable"))
case \tag("category"("Variable")) => \tag("category"("variable"))
case \tag("category"("Constant")) => \tag("category"("string")) // Updated (before: constant)
case \tag("category"("Comment")) => \tag("category"("comment"))
case \tag("category"("Todo")) => \tag("category"("comment"))
case \tag("category"("Quote")) => \tag("category"("string")) // Updated (before: meta.string)
case \tag("category"("MetaAmbiguity")) => \tag("category"("invalid"))
case \tag("category"("MetaVariable")) => \tag("category"("variable"))
case \tag("category"("MetaKeyword")) => \tag("category"("keyword")) // Updated (before: keyword.other)
case \tag("category"("MetaSkipped")) => \tag("category"("string"))
case \tag("category"("NonterminalLabel")) => \tag("category"("variable")) // Updated (before: variable.parameter)
case \tag("category"("Result")) => \tag("category"("string")) // Updated (before: text)
case \tag("category"("StdOut")) => \tag("category"("string")) // Updated (before: text)
case \tag("category"("StdErr")) => \tag("category"("string")) // Updated (before: text)

// With additional hot-patching as discussed:
// - https://github.com/SWAT-engineering/rascal-textmate/pull/6
case p: prod(label("integer", sort("Literal")), _, _) => setCategory(p, "constant.numeric")
case p: prod(label("real", sort("Literal")), _, _) => setCategory(p, "constant.numeric")
case p: prod(label("rational", sort("Literal")), _, _) => setCategory(p, "constant.numeric")
case p: prod(label("location", sort("Literal")), _, _) => setCategory(p, "markup.underline.link")
case p: prod(label("regExp", sort("Literal")), _, _) => setCategory(p, "constant.regexp")
case p: prod(lex("StringConstant"), _, _) => setCategory(p, "string.quoted.double")
case p: prod(lex("CaseInsensitiveStringConstant"), _, _) => setCategory(p, "string.quoted.single")
case p: prod(lex("PreStringChars"), _, _) => setCategory(p, "string.quoted.double")
case p: prod(lex("MidStringChars"), _, _) => setCategory(p, "string.quoted.double")
case p: prod(lex("PostStringChars"), _, _) => setCategory(p, "string.quoted.double")
};
}
11 changes: 11 additions & 0 deletions rascal-textmate-core/src/main/rascal/VSCodePico.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@synopsis{
Main function to generate a new TextMate grammar for Pico, to be used in the
special VS Code extension
}

module VSCodePico

import Main;
extend lang::textmate::conversiontests::PicoWithCategories;

int main() = Main::main(rsc, "source.pico", |project://vscode-extension/syntaxes/pico.tmLanguage.json|);
61 changes: 61 additions & 0 deletions rascal-textmate-core/src/main/rascal/VSCodeRascal.rsc
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
@synopsis{
Main function to generate a new TextMate grammar for Rascal, to be used in
the special VS Code extension
}

module VSCodeRascal

import Grammar;
import Main;
extend lang::textmate::conversiontests::Rascal;

int main() = Main::main(getRscGrammar(), "source.rascalmpl", |project://vscode-extension/syntaxes/rascal.tmLanguage.json|);

// Relevant comment regarding grammar precedence in VS Code:
// - https://github.com/microsoft/vscode-docs/issues/2862#issuecomment-599994967

private Grammar getRscGrammar() {
Production setCategory(p: prod(_, _, attributes), str category)
= {\tag("category"(_)), *rest} := attributes
? p[attributes = rest + \tag("category"(category))]
: p[attributes = attributes + \tag("category"(category))];

return visit (rsc) {

// The following mapping is based on:
// - https://github.com/usethesource/rascal/blob/83023f60a6eb9df7a19ccc7a4194b513ac7b7157/src/org/rascalmpl/values/parsetrees/TreeAdapter.java#L44-L59
// - https://github.com/usethesource/rascal-language-servers/blob/752fea3ea09101e5b22ee426b11c5e36db880225/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/SemanticTokenizer.java#L121-L142
// With updates based on:
// - https://github.com/eclipse-lsp4j/lsp4j/blob/f235e91fbe2e45f62e185bbb9f6d21bed48eb2b9/org.eclipse.lsp4j/src/main/java/org/eclipse/lsp4j/Protocol.xtend#L5639-L5695
// - https://github.com/usethesource/rascal-language-servers/blob/88be4a326128da8c81d581c2b918b4927f2185be/rascal-lsp/src/main/java/org/rascalmpl/vscode/lsp/util/SemanticTokenizer.java#L134-L152
case \tag("category"("Normal")) => \tag("category"("source"))
case \tag("category"("Type")) => \tag("category"("type")) // Updated (before: storage.type)
case \tag("category"("Identifier")) => \tag("category"("variable"))
case \tag("category"("Variable")) => \tag("category"("variable"))
case \tag("category"("Constant")) => \tag("category"("string")) // Updated (before: constant)
case \tag("category"("Comment")) => \tag("category"("comment"))
case \tag("category"("Todo")) => \tag("category"("comment"))
case \tag("category"("Quote")) => \tag("category"("string")) // Updated (before: meta.string)
case \tag("category"("MetaAmbiguity")) => \tag("category"("invalid"))
case \tag("category"("MetaVariable")) => \tag("category"("variable"))
case \tag("category"("MetaKeyword")) => \tag("category"("keyword")) // Updated (before: keyword.other)
case \tag("category"("MetaSkipped")) => \tag("category"("string"))
case \tag("category"("NonterminalLabel")) => \tag("category"("variable")) // Updated (before: variable.parameter)
case \tag("category"("Result")) => \tag("category"("string")) // Updated (before: text)
case \tag("category"("StdOut")) => \tag("category"("string")) // Updated (before: text)
case \tag("category"("StdErr")) => \tag("category"("string")) // Updated (before: text)

// With additional hot-patching as discussed:
// - https://github.com/SWAT-engineering/rascal-textmate/pull/6
case p: prod(label("integer", sort("Literal")), _, _) => setCategory(p, "constant.numeric")
case p: prod(label("real", sort("Literal")), _, _) => setCategory(p, "constant.numeric")
case p: prod(label("rational", sort("Literal")), _, _) => setCategory(p, "constant.numeric")
case p: prod(label("location", sort("Literal")), _, _) => setCategory(p, "markup.underline.link")
case p: prod(label("regExp", sort("Literal")), _, _) => setCategory(p, "constant.regexp")
case p: prod(lex("StringConstant"), _, _) => setCategory(p, "string.quoted.double")
case p: prod(lex("CaseInsensitiveStringConstant"), _, _) => setCategory(p, "string.quoted.single")
case p: prod(lex("PreStringChars"), _, _) => setCategory(p, "string.quoted.double")
case p: prod(lex("MidStringChars"), _, _) => setCategory(p, "string.quoted.double")
case p: prod(lex("PostStringChars"), _, _) => setCategory(p, "string.quoted.double")
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,23 @@ syntax Expression
| min: Expression lhs "-" Expression rhs)
;

lexical Id = [a-z][a-z0-9]* !>> [a-z0-9];
lexical Id = ([a-z][a-z0-9]*) !>> [a-z0-9] \ Keyword;
lexical Natural = [0-9]+ !>> [0-9];
lexical String = "\"" ![\"]* "\"";

keyword Keyword
= "begin"
| "end"
| "declare"
| "if"
| "then"
| "else"
| "fi"
| "while"
| "do"
| "od"
;

layout Layout = WhitespaceAndComment* !>> [\ \t\n\r%];

lexical WhitespaceAndComment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
# ^^^^^ comment.block

do
# ^^ variable.other
# ^^ -variable.other
# ^^ keyword.control

123
# ^^^ constant.numeric
Expand All @@ -39,10 +40,6 @@
# ^^^^^^^ variable.other
# ^^^^^^^ storage.type

#begin
## <----- keyword.control
## TODO: `begin` outside `begin`-`end` can never be an identifier in Pico

"foo bar"
# ^^^^^^^^^ string.quoted.double

Expand Down
36 changes: 28 additions & 8 deletions vscode-extension/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rascal-syntax-highlighting",
"displayName": "Rascal Syntax Highlighting",
"name": "rascalmpl-syntax-highlighting",
"displayName": "Rascal Metaprogramming Language (Syntax Highlighting)",
"description": "",
"version": "0.0.1",
"engines": {
Expand All @@ -10,11 +10,31 @@
"Programming Languages"
],
"contributes": {
"grammars": [{
"language": "rascalmpl",
"scopeName": "source.rascalmpl.injection",
"path": "./syntaxes/rascal.tmLanguage.json",
"injectTo": ["source.rascalmpl"]
}]
"languages": [
{
"id": "rascalmpl",
"aliases": ["Rascal MPL"],
"extensions": [".rsc"],
"configuration": "./language-configuration.json"
},
{
"id": "pico",
"aliases": ["Pico"],
"extensions": [".pico"],
"configuration": "./language-configuration.json"
}
],
"grammars": [
{
"language": "rascalmpl",
"scopeName": "source.rascalmpl",
"path": "./syntaxes/rascal.tmLanguage.json"
},
{
"language": "pico",
"scopeName": "source.pico",
"path": "./syntaxes/pico.tmLanguage.json"
}
]
}
}
Loading

0 comments on commit c7ed45e

Please sign in to comment.