feat(zon)!: Zon Parser

This commit is contained in:
FalsePattern 2023-08-08 22:59:16 +02:00 committed by FalsePattern
parent 9a0aa39cfc
commit 3f4bc3d550
Signed by: falsepattern
GPG key ID: FDF7126A9E124447
17 changed files with 367 additions and 0 deletions

View file

@ -18,6 +18,11 @@ Changelog structure reference:
## [Unreleased]
### Added
#### Zon
- Basic parser and PSI tree
## [0.4.0]
### Added

View file

@ -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")

View file

@ -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
View 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

View file

@ -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);
}

View file

@ -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;
}
}

View file

@ -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");
}
}

View 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; }

View file

@ -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));
}
}

View 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+

View file

@ -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";
}
}

View 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);
}
}

View file

@ -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);
}

View file

@ -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);
}
}

View file

@ -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);
}
}

View file

@ -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>

View 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