feat(zon)!: Zon Parser
This commit is contained in:
parent
9a0aa39cfc
commit
3f4bc3d550
17 changed files with 367 additions and 0 deletions
|
@ -18,6 +18,11 @@ Changelog structure reference:
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
#### Zon
|
||||
- Basic parser and PSI tree
|
||||
|
||||
## [0.4.0]
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import org.jetbrains.changelog.Changelog
|
||||
import org.jetbrains.changelog.markdownToHTML
|
||||
import org.jetbrains.grammarkit.tasks.GenerateLexerTask
|
||||
import org.jetbrains.grammarkit.tasks.GenerateParserTask
|
||||
|
||||
fun properties(key: String) = providers.gradleProperty(key)
|
||||
fun environment(key: String) = providers.environmentVariable(key)
|
||||
|
@ -8,6 +10,7 @@ plugins {
|
|||
id("java") // Java support
|
||||
alias(libs.plugins.gradleIntelliJPlugin) // Gradle IntelliJ Plugin
|
||||
alias(libs.plugins.changelog) // Gradle Changelog Plugin
|
||||
alias(libs.plugins.grammarkit)
|
||||
}
|
||||
|
||||
// Keep these in sync with whatever the oldest IDE version we're targeting in gradle.properties needs
|
||||
|
@ -54,6 +57,18 @@ intellij {
|
|||
plugins = properties("platformPlugins").map { it.split(',').map(String::trim).filter(String::isNotEmpty) }
|
||||
}
|
||||
|
||||
// Include the generated files in the source set
|
||||
sourceSets {
|
||||
main {
|
||||
java {
|
||||
srcDirs(
|
||||
"build/generated/sources/grammarkit/java/lexer",
|
||||
"build/generated/sources/grammarkit/java/parser"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
changelog {
|
||||
groups.empty()
|
||||
repositoryUrl = properties("pluginRepositoryUrl")
|
||||
|
@ -64,6 +79,42 @@ tasks {
|
|||
gradleVersion = properties("gradleVersion").get()
|
||||
}
|
||||
|
||||
generateLexer {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
generateParser {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
register<GenerateLexerTask>("generateZonLexer") {
|
||||
group = "build setup"
|
||||
sourceFile = file("src/main/java/com/falsepattern/zigbrains/zon/lexer/Zon.flex")
|
||||
targetDir = "build/generated/sources/grammarkit/java/lexer/com/falsepattern/zigbrains/zon/lexer"
|
||||
targetClass = "ZonFlexLexer"
|
||||
purgeOldFiles = true
|
||||
}
|
||||
|
||||
register<GenerateParserTask>("generateZonParser") {
|
||||
group = "build setup"
|
||||
sourceFile = file("src/main/java/com/falsepattern/zigbrains/zon/parser/Zon.bnf")
|
||||
targetRoot = "build/generated/sources/grammarkit/java/parser"
|
||||
pathToParser = "com/falsepattern/zigbrains/zon/psi/ZonParser.java"
|
||||
pathToPsiRoot = "com/falsepattern/zigbrains/zon/psi"
|
||||
purgeOldFiles = true
|
||||
}
|
||||
|
||||
register<DefaultTask>("generateSources") {
|
||||
description = "Generate source code from parser/lexer definitions"
|
||||
group = "build setup"
|
||||
dependsOn("generateZonLexer")
|
||||
dependsOn("generateZonParser")
|
||||
}
|
||||
|
||||
compileJava {
|
||||
dependsOn("generateSources")
|
||||
}
|
||||
|
||||
patchPluginXml {
|
||||
version = properties("pluginVersion")
|
||||
sinceBuild = properties("pluginSinceBuild")
|
||||
|
|
|
@ -8,6 +8,7 @@ changelog = "2.1.2"
|
|||
gradleIntelliJPlugin = "1.15.0"
|
||||
qodana = "0.1.13"
|
||||
kover = "0.7.2"
|
||||
grammarkit = "2022.3.1"
|
||||
|
||||
[libraries]
|
||||
annotations = { group = "org.jetbrains", name = "annotations", version.ref = "annotations" }
|
||||
|
@ -18,3 +19,4 @@ gradleIntelliJPlugin = { id = "org.jetbrains.intellij", version.ref = "gradleInt
|
|||
kotlin = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
||||
kover = { id = "org.jetbrains.kotlinx.kover", version.ref = "kover" }
|
||||
qodana = { id = "org.jetbrains.qodana", version.ref = "qodana" }
|
||||
grammarkit = { id = "org.jetbrains.grammarkit", version.ref = "grammarkit" }
|
||||
|
|
21
src/art/zig/zon.svg
Normal file
21
src/art/zig/zon.svg
Normal file
|
@ -0,0 +1,21 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 154 140">
|
||||
<g fill="#F7A41D">
|
||||
<g>
|
||||
<polygon points="46,22 28,44 19,30"/>
|
||||
<polygon points="46,22 33,33 28,44 22,44 22,95 31,95 20,100 12,117 0,117 0,22" shape-rendering="crispEdges"/>
|
||||
<polygon points="31,95 12,117 4,106"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="141,22 140,40 122,45"/>
|
||||
<polygon points="153,22 153,117 106,117 120,105 125,95 131,95 131,45 122,45 132,36 141,22" shape-rendering="crispEdges"/>
|
||||
<polygon points="125,95 130,110 106,117"/>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="#1DF7A4">
|
||||
<polygon points="56,22 62,36 37,44"/>
|
||||
<polygon points="56,22 111,22 111,44 37,44 56,32" shape-rendering="crispEdges"/>
|
||||
<polygon points="116,95 97,117 90,104"/>
|
||||
<polygon points="116,95 100,104 97,117 42,117 42,95" shape-rendering="crispEdges"/>
|
||||
<polygon points="150,0 52,117 3,140 101,22"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 858 B |
|
@ -22,4 +22,5 @@ import javax.swing.Icon;
|
|||
|
||||
public class Icons {
|
||||
public static final Icon ZIG = IconLoader.getIcon("/icons/zig.svg", Icons.class);
|
||||
public static final Icon ZON = IconLoader.getIcon("/icons/zon.svg", Icons.class);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.falsepattern.zigbrains.zon;
|
||||
|
||||
import com.falsepattern.zigbrains.common.Icons;
|
||||
import com.intellij.openapi.fileTypes.LanguageFileType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.Icon;
|
||||
|
||||
public class ZonFileType extends LanguageFileType {
|
||||
@SuppressWarnings("unused") //Used by plugin.xml
|
||||
public static final ZonFileType INSTANCE = new ZonFileType();
|
||||
|
||||
private ZonFileType() {
|
||||
super(ZonLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NonNls @NotNull String getName() {
|
||||
return "ZON File";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getDescription() {
|
||||
return "Zig object notation file";
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String getDefaultExtension() {
|
||||
return "zon";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Icon getIcon() {
|
||||
return Icons.ZON;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.falsepattern.zigbrains.zon;
|
||||
|
||||
import com.intellij.lang.Language;
|
||||
|
||||
public class ZonLanguage extends Language {
|
||||
public static final ZonLanguage INSTANCE = new ZonLanguage();
|
||||
private ZonLanguage() {
|
||||
super("Zon");
|
||||
}
|
||||
}
|
45
src/main/java/com/falsepattern/zigbrains/zon/lexer/Zon.flex
Normal file
45
src/main/java/com/falsepattern/zigbrains/zon/lexer/Zon.flex
Normal file
|
@ -0,0 +1,45 @@
|
|||
package com.falsepattern.zigbrains.zon.lexer;
|
||||
|
||||
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.zon.psi.ZonTypes.*;
|
||||
|
||||
%%
|
||||
|
||||
%class ZonFlexLexer
|
||||
%implements FlexLexer
|
||||
%function advance
|
||||
%type IElementType
|
||||
%unicode
|
||||
|
||||
WHITE_SPACE=[\s]+
|
||||
LINE_COMMENT="//" [^\n]* | "////" [^\n]*
|
||||
COMMENT="///".*
|
||||
|
||||
ID=[A-Za-z_][A-Za-z0-9_]* | "@\"" {STRING_CHAR}* \"
|
||||
|
||||
STRING_CHAR=( [^\\\"] | \\[^] )
|
||||
STRING_LITERAL_SINGLE=\"{STRING_CHAR}*\"
|
||||
LINE_STRING=(\\\\ [^\n]* [ \n]*)+
|
||||
|
||||
%%
|
||||
|
||||
<YYINITIAL> {
|
||||
{WHITE_SPACE} { return WHITE_SPACE; }
|
||||
"." { return DOT; }
|
||||
"{" { return LBRACE; }
|
||||
"}" { return RBRACE; }
|
||||
"=" { return EQ; }
|
||||
"," { return COMMA; }
|
||||
{COMMENT} { return COMMENT; }
|
||||
{LINE_COMMENT} { return COMMENT; }
|
||||
|
||||
{ID} { return ID; }
|
||||
{STRING_LITERAL_SINGLE} { return STRING_LITERAL_SINGLE; }
|
||||
{LINE_STRING} { return LINE_STRING; }
|
||||
}
|
||||
|
||||
[^] { return BAD_CHARACTER; }
|
|
@ -0,0 +1,9 @@
|
|||
package com.falsepattern.zigbrains.zon.lexer;
|
||||
|
||||
import com.intellij.lexer.FlexAdapter;
|
||||
|
||||
public class ZonLexerAdapter extends FlexAdapter {
|
||||
public ZonLexerAdapter() {
|
||||
super(new ZonFlexLexer(null));
|
||||
}
|
||||
}
|
35
src/main/java/com/falsepattern/zigbrains/zon/parser/Zon.bnf
Normal file
35
src/main/java/com/falsepattern/zigbrains/zon/parser/Zon.bnf
Normal file
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
parserClass="com.falsepattern.zigbrains.zon.parser.ZonParser"
|
||||
|
||||
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
|
||||
|
||||
psiClassPrefix="Zon"
|
||||
psiImplClassSuffix="Impl"
|
||||
psiPackage="com.falsepattern.zigbrains.zon.psi"
|
||||
psiImplPackage="com.falsepattern.zigbrains.zon.psi.impl"
|
||||
|
||||
elementTypeHolderClass="com.falsepattern.zigbrains.zon.psi.ZonTypes"
|
||||
elementTypeClass="com.falsepattern.zigbrains.zon.psi.ZonElementType"
|
||||
tokenTypeClass="com.falsepattern.zigbrains.zon.psi.ZonTokenType"
|
||||
tokens=[
|
||||
DOT='.'
|
||||
LBRACE='{'
|
||||
RBRACE='}'
|
||||
EQ='='
|
||||
COMMA=','
|
||||
COMMENT='comment'
|
||||
ID='identifier'
|
||||
STRING_LITERAL_SINGLE='string'
|
||||
LINE_STRING='multiline string'
|
||||
]
|
||||
}
|
||||
|
||||
zonFile ::= struct
|
||||
|
||||
struct ::= DOT LBRACE (property (COMMA property)* COMMA?)? RBRACE
|
||||
|
||||
property ::= DOT ID EQ value
|
||||
|
||||
value ::= struct | STRING_LITERAL
|
||||
|
||||
STRING_LITERAL ::= STRING_LITERAL_SINGLE | LINE_STRING+
|
|
@ -0,0 +1,24 @@
|
|||
package com.falsepattern.zigbrains.zon.parser;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.ZonFileType;
|
||||
import com.falsepattern.zigbrains.zon.ZonLanguage;
|
||||
import com.intellij.extapi.psi.PsiFileBase;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ZonFile extends PsiFileBase {
|
||||
public ZonFile(@NotNull FileViewProvider viewProvider) {
|
||||
super(viewProvider, ZonLanguage.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull FileType getFileType() {
|
||||
return ZonFileType.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Zon File";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package com.falsepattern.zigbrains.zon.parser;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.ZonLanguage;
|
||||
import com.falsepattern.zigbrains.zon.lexer.ZonLexerAdapter;
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonTypes;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.ParserDefinition;
|
||||
import com.intellij.lang.PsiParser;
|
||||
import com.intellij.lexer.Lexer;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.FileViewProvider;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.tree.IFileElementType;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ZonParserDefinition implements ParserDefinition {
|
||||
public static final IFileElementType FILE = new IFileElementType(ZonLanguage.INSTANCE);
|
||||
@Override
|
||||
public @NotNull Lexer createLexer(Project project) {
|
||||
return new ZonLexerAdapter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TokenSet getCommentTokens() {
|
||||
return ZonTokenSets.COMMENTS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull TokenSet getStringLiteralElements() {
|
||||
return ZonTokenSets.STRINGS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PsiParser createParser(Project project) {
|
||||
return new ZonParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull IFileElementType getFileNodeType() {
|
||||
return FILE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PsiFile createFile(@NotNull FileViewProvider viewProvider) {
|
||||
return new ZonFile(viewProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull PsiElement createElement(ASTNode node) {
|
||||
return ZonTypes.Factory.createElement(node);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.falsepattern.zigbrains.zon.parser;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.psi.ZonTypes;
|
||||
import com.intellij.psi.tree.TokenSet;
|
||||
|
||||
public interface ZonTokenSets {
|
||||
TokenSet COMMENTS = TokenSet.create(ZonTypes.COMMENT);
|
||||
TokenSet STRINGS = TokenSet.create(ZonTypes.LINE_STRING, ZonTypes.STRING_LITERAL_SINGLE);
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.falsepattern.zigbrains.zon.psi;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.ZonLanguage;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ZonElementType extends IElementType {
|
||||
public ZonElementType(@NonNls @NotNull String debugName) {
|
||||
super(debugName, ZonLanguage.INSTANCE);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.falsepattern.zigbrains.zon.psi;
|
||||
|
||||
import com.falsepattern.zigbrains.zon.ZonLanguage;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ZonTokenType extends IElementType {
|
||||
public ZonTokenType(@NonNls @NotNull String debugName) {
|
||||
super(debugName, ZonLanguage.INSTANCE);
|
||||
}
|
||||
}
|
|
@ -7,6 +7,8 @@
|
|||
<depends>com.intellij.modules.platform</depends>
|
||||
|
||||
<extensions defaultExtensionNs="com.intellij">
|
||||
<!-- region Zig -->
|
||||
|
||||
<!-- region LSP4IntelliJ -->
|
||||
|
||||
<!-- register intellijLanguageClient as a Service OR as a plugin component (see readme)... -->
|
||||
|
@ -75,9 +77,24 @@
|
|||
<notificationGroup displayType="BALLOON"
|
||||
id="ZigBrains.Nag"/>
|
||||
|
||||
<!-- endregion Zig -->
|
||||
|
||||
<!-- region Zon -->
|
||||
<fileType name="Zon File"
|
||||
implementationClass="com.falsepattern.zigbrains.zon.ZonFileType"
|
||||
fieldName="INSTANCE"
|
||||
language="Zon"
|
||||
extensions="zon"/>
|
||||
|
||||
<lang.parserDefinition language="Zon"
|
||||
implementationClass="com.falsepattern.zigbrains.zon.parser.ZonParserDefinition"/>
|
||||
<!-- endregion Zon -->
|
||||
|
||||
</extensions>
|
||||
|
||||
<actions>
|
||||
<!-- region Zig -->
|
||||
|
||||
<!-- region LSP4IntelliJ -->
|
||||
|
||||
<!-- needed for hover -->
|
||||
|
@ -93,6 +110,8 @@
|
|||
</action>
|
||||
|
||||
<!-- endregion LSP4IntelliJ -->
|
||||
|
||||
<!-- endregion Zig -->
|
||||
</actions>
|
||||
|
||||
<applicationListeners>
|
||||
|
|
21
src/main/resources/icons/zon.svg
Normal file
21
src/main/resources/icons/zon.svg
Normal file
|
@ -0,0 +1,21 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 154 140">
|
||||
<g fill="#F7A41D">
|
||||
<g>
|
||||
<polygon points="46,22 28,44 19,30"/>
|
||||
<polygon points="46,22 33,33 28,44 22,44 22,95 31,95 20,100 12,117 0,117 0,22" shape-rendering="crispEdges"/>
|
||||
<polygon points="31,95 12,117 4,106"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon points="141,22 140,40 122,45"/>
|
||||
<polygon points="153,22 153,117 106,117 120,105 125,95 131,95 131,45 122,45 132,36 141,22" shape-rendering="crispEdges"/>
|
||||
<polygon points="125,95 130,110 106,117"/>
|
||||
</g>
|
||||
</g>
|
||||
<g fill="#1DF7A4">
|
||||
<polygon points="56,22 62,36 37,44"/>
|
||||
<polygon points="56,22 111,22 111,44 37,44 56,32" shape-rendering="crispEdges"/>
|
||||
<polygon points="116,95 97,117 90,104"/>
|
||||
<polygon points="116,95 100,104 97,117 42,117 42,95" shape-rendering="crispEdges"/>
|
||||
<polygon points="150,0 52,117 3,140 101,22"/>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 858 B |
Loading…
Add table
Reference in a new issue