feat: String escape sequence highlighting

This commit is contained in:
FalsePattern 2024-10-25 19:55:57 +02:00
parent 0d915f921e
commit 9d0f81bd8d
Signed by: falsepattern
GPG key ID: E930CDEC50C50E23
7 changed files with 150 additions and 45 deletions

View file

@ -17,6 +17,11 @@ Changelog structure reference:
## [Unreleased]
### Added
- Zig
- Syntax highlighting for escape sequences in strings
### Fixed
- Zig

View file

@ -2,6 +2,7 @@ import de.undercouch.gradle.tasks.download.Download
import groovy.xml.XmlParser
import org.jetbrains.changelog.Changelog
import org.jetbrains.changelog.markdownToHTML
import org.jetbrains.grammarkit.tasks.GenerateLexerTask
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
import org.jetbrains.intellij.platform.gradle.tasks.PatchPluginXmlTask
import org.jetbrains.intellij.platform.gradle.tasks.PublishPluginTask
@ -204,11 +205,21 @@ project(":zig") {
targetOutputDir = file("${grammarKitGenDir}/lexer/${rootPackagePath}/zig/lexer")
}
register<GenerateLexerTask>("generateStringLexer") {
sourceFile = file("src/main/grammar/ZigString.flex")
targetOutputDir = file("${grammarKitGenDir}/lexer/${rootPackagePath}/zig/stringlexer")
purgeOldFiles = true
}
generateParser {
sourceFile = file("src/main/grammar/Zig.bnf")
pathToParser = "${rootPackagePath}/zig/psi/ZigParser.java"
pathToPsiRoot = "${rootPackagePath}/zig/psi"
}
named("generateGrammars") {
dependsOn("generateStringLexer")
}
}
}

View file

@ -90,8 +90,8 @@ char_char= {mb_utf8_literal}
| {char_escape}
| {ascii_char_not_nl_slash_squote}
string_char= {char_escape}
| [^\\\"\n]
string_char= \\ .
| [^\"\n]
all_nl_wrap=[^\n]* [ \n]*
all_nl_nowrap=[^\n]* \n

View file

@ -0,0 +1,60 @@
/*
* Copyright 2023-2024 FalsePattern
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.falsepattern.zigbrains.zig.stringlexer;
import com.intellij.lexer.FlexLexer;
import com.intellij.psi.tree.IElementType;
import static com.intellij.psi.TokenType.WHITE_SPACE;
import static com.intellij.psi.TokenType.BAD_CHARACTER;
import static com.falsepattern.zigbrains.zig.psi.ZigTypes.*;
import static com.intellij.psi.StringEscapesTokenTypes.*;
%%
%public
%class ZigStringLexer
%implements FlexLexer
%function advance
%type IElementType
hex=[0-9a-fA-F]
char_escape_unicode= "\\x" {hex} {hex} | "\\u{" {hex}+ "}"
char_escape_unicode_invalid= "\\x" | "\\u"
char_escape_single_valid= "\\" [nr\\t'\"]
char_escape_single_invalid= "\\" [^nr\\t'\"]
non_escape= [^\\\"\n]
%state STR
%%
<YYINITIAL> {
"\"" { yybegin(STR); return STRING_LITERAL_SINGLE; }
[^] { return STRING_LITERAL_SINGLE; }
}
<STR> {
{char_escape_unicode} { return VALID_STRING_ESCAPE_TOKEN; }
{char_escape_unicode_invalid} { return INVALID_UNICODE_ESCAPE_TOKEN; }
{char_escape_single_valid} { return VALID_STRING_ESCAPE_TOKEN; }
{char_escape_single_invalid} { return INVALID_CHARACTER_ESCAPE_TOKEN; }
[^] { return STRING_LITERAL_SINGLE; }
}

View file

@ -63,6 +63,9 @@ public class ZigColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor("Property//Declaration", ZigSyntaxHighlighter.PROPERTY_DECL),
new AttributesDescriptor("Property//Reference", ZigSyntaxHighlighter.PROPERTY_REF),
new AttributesDescriptor("String", ZigSyntaxHighlighter.STRING),
new AttributesDescriptor("String//Escape", ZigSyntaxHighlighter.STRING_ESC_V),
new AttributesDescriptor("String//Escape//Invalid char", ZigSyntaxHighlighter.STRING_ESC_I_C),
new AttributesDescriptor("String//Escape//Invalid unicode", ZigSyntaxHighlighter.STRING_ESC_I_U),
new AttributesDescriptor("Struct//Declaration", ZigSyntaxHighlighter.STRUCT_DECL),
new AttributesDescriptor("Struct//Reference", ZigSyntaxHighlighter.STRUCT_REF),
new AttributesDescriptor("Type//Declaration", ZigSyntaxHighlighter.TYPE_DECL),

View file

@ -16,6 +16,7 @@
package com.falsepattern.zigbrains.zig.highlighter;
import com.falsepattern.zigbrains.zig.lexer.ZigHighlightingLexer;
import com.falsepattern.zigbrains.zig.lexer.ZigLexerAdapter;
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.intellij.lexer.Lexer;
@ -23,6 +24,7 @@ import com.intellij.openapi.editor.DefaultLanguageHighlighterColors;
import com.intellij.openapi.editor.HighlighterColors;
import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase;
import com.intellij.psi.StringEscapesTokenTypes;
import com.intellij.psi.TokenType;
import com.intellij.psi.tree.IElementType;
import com.redhat.devtools.lsp4ij.features.semanticTokens.SemanticTokensHighlightingColors;
@ -65,6 +67,9 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
OPERATOR = createKey("OPERATOR" , SemanticTokensHighlightingColors.OPERATOR ),
PARAMETER = createKey("PARAMETER" , SemanticTokensHighlightingColors.PARAMETER ),
STRING = createKey("STRING" , SemanticTokensHighlightingColors.STRING ),
STRING_ESC_V = createKey("STRING_ESC_V" , DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE ),
STRING_ESC_I_C = createKey("STRING_ESC_I_C" , DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE ),
STRING_ESC_I_U = createKey("STRING_ESC_I_U" , DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE ),
STRUCT_DECL = createKey("STRUCT_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ),
STRUCT_REF = createKey("STRUCT" , SemanticTokensHighlightingColors.CLASS ),
TYPE_DECL = createKey("TYPE_DECL" , SemanticTokensHighlightingColors.CLASS_DECLARATION ),
@ -102,6 +107,9 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
}
addMapping(BUILTIN, ZigTypes.BUILTINIDENTIFIER);
addMapping(STRING, ZigTypes.STRING_LITERAL_SINGLE, ZigTypes.STRING_LITERAL_MULTI);
addMapping(STRING_ESC_V, StringEscapesTokenTypes.VALID_STRING_ESCAPE_TOKEN);
addMapping(STRING_ESC_I_C, StringEscapesTokenTypes.INVALID_CHARACTER_ESCAPE_TOKEN);
addMapping(STRING_ESC_I_U, StringEscapesTokenTypes.INVALID_UNICODE_ESCAPE_TOKEN);
addMapping(BAD_CHAR, TokenType.BAD_CHARACTER);
addMapping(NUMBER, ZigTypes.INTEGER, ZigTypes.FLOAT);
addMapping(CHAR, ZigTypes.CHAR_LITERAL);
@ -120,7 +128,7 @@ public class ZigSyntaxHighlighter extends SyntaxHighlighterBase {
@Override
public @NotNull Lexer getHighlightingLexer() {
return new ZigLexerAdapter();
return new ZigHighlightingLexer();
}
@Override

View file

@ -0,0 +1,18 @@
package com.falsepattern.zigbrains.zig.lexer;
import com.falsepattern.zigbrains.zig.psi.ZigTypes;
import com.intellij.lexer.FlexAdapter;
import com.intellij.lexer.LayeredLexer;
import com.intellij.lexer.MergingLexerAdapter;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.tree.TokenSet;
import lombok.val;
public class ZigHighlightingLexer extends LayeredLexer {
public ZigHighlightingLexer() {
super(new ZigLexerAdapter());
val stringLexer = new MergingLexerAdapter(new FlexAdapter(new com.falsepattern.zigbrains.zig.stringlexer.ZigStringLexer(null)), TokenSet.create(
ZigTypes.STRING_LITERAL_SINGLE));
registerSelfStoppingLayer(stringLexer, new IElementType[]{ZigTypes.STRING_LITERAL_SINGLE}, IElementType.EMPTY_ARRAY);
}
}