initial Zig PSI port, full ZON port
This commit is contained in:
parent
d9b4be45ee
commit
71c09d3ae2
45 changed files with 1910 additions and 20 deletions
|
@ -4,10 +4,11 @@ import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
java
|
kotlin("jvm") version "1.9.24" apply false
|
||||||
kotlin("jvm") version "1.9.24"
|
|
||||||
id("org.jetbrains.intellij.platform") version "2.1.0"
|
id("org.jetbrains.intellij.platform") version "2.1.0"
|
||||||
id("org.jetbrains.changelog") version "2.2.1"
|
id("org.jetbrains.changelog") version "2.2.1"
|
||||||
|
id("org.jetbrains.grammarkit") version "2022.3.2.2" apply false
|
||||||
|
idea
|
||||||
}
|
}
|
||||||
|
|
||||||
val javaVersion = providers.gradleProperty("javaVersion").get().toInt()
|
val javaVersion = providers.gradleProperty("javaVersion").get().toInt()
|
||||||
|
@ -19,6 +20,11 @@ subprojects {
|
||||||
apply(plugin = "java")
|
apply(plugin = "java")
|
||||||
apply(plugin = "org.jetbrains.kotlin.jvm")
|
apply(plugin = "org.jetbrains.kotlin.jvm")
|
||||||
apply(plugin = "org.jetbrains.intellij.platform.module")
|
apply(plugin = "org.jetbrains.intellij.platform.module")
|
||||||
|
apply(plugin = "idea")
|
||||||
|
|
||||||
|
extensions.configure<KotlinJvmProjectExtension>("kotlin") {
|
||||||
|
jvmToolchain(javaVersion)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
@ -31,13 +37,17 @@ tasks {
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
kotlin {
|
idea {
|
||||||
jvmToolchain(javaVersion)
|
module {
|
||||||
|
isDownloadJavadoc = false
|
||||||
|
isDownloadSources = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(javaVersion)
|
languageVersion = JavaLanguageVersion.of(javaVersion)
|
||||||
|
@Suppress("UnstableApiUsage")
|
||||||
vendor = JvmVendorSpec.JETBRAINS
|
vendor = JvmVendorSpec.JETBRAINS
|
||||||
}
|
}
|
||||||
sourceCompatibility = JavaVersion.toVersion(javaVersion)
|
sourceCompatibility = JavaVersion.toVersion(javaVersion)
|
||||||
|
@ -66,7 +76,8 @@ dependencies {
|
||||||
zipSigner()
|
zipSigner()
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation(project(":core"))
|
implementation(project(":zig"))
|
||||||
|
implementation(project(":zon"))
|
||||||
}
|
}
|
||||||
|
|
||||||
intellijPlatform {
|
intellijPlatform {
|
||||||
|
@ -121,6 +132,7 @@ intellijPlatform {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
buildSearchableOptions = false
|
buildSearchableOptions = false
|
||||||
|
instrumentCode = false
|
||||||
}
|
}
|
||||||
|
|
||||||
changelog {
|
changelog {
|
||||||
|
@ -132,4 +144,10 @@ tasks {
|
||||||
publishPlugin {
|
publishPlugin {
|
||||||
dependsOn(patchChangelog)
|
dependsOn(patchChangelog)
|
||||||
}
|
}
|
||||||
|
compileJava {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
|
classes {
|
||||||
|
enabled = false
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
intellijPlatform {
|
|
||||||
create(IntelliJPlatformType.IntellijIdeaCommunity, providers.gradleProperty("ideaCommunityVersion"))
|
|
||||||
}
|
|
||||||
}
|
|
73
modules/zig/build.gradle.kts
Normal file
73
modules/zig/build.gradle.kts
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
import org.jetbrains.grammarkit.tasks.GenerateLexerTask
|
||||||
|
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("org.jetbrains.grammarkit")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
intellijPlatform {
|
||||||
|
create(IntelliJPlatformType.IntellijIdeaCommunity, providers.gradleProperty("ideaCommunityVersion"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val grammarGenRoot = "generated/sources/grammarkit/zig"
|
||||||
|
val rootPackagePath = "com/falsepattern/zigbrains/zig"
|
||||||
|
|
||||||
|
val parserDir = layout.buildDirectory.dir("$grammarGenRoot/parser")
|
||||||
|
val lexerDir = layout.buildDirectory.dir("$grammarGenRoot/lexer")
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
java {
|
||||||
|
srcDir(parserDir)
|
||||||
|
srcDir(lexerDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
idea {
|
||||||
|
module {
|
||||||
|
sourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile))
|
||||||
|
generatedSourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
generateLexer {
|
||||||
|
purgeOldFiles = true
|
||||||
|
sourceFile = file("src/main/grammar/Zig.flex")
|
||||||
|
targetOutputDir = layout.buildDirectory.dir("$grammarGenRoot/lexer/$rootPackagePath/lexer")
|
||||||
|
}
|
||||||
|
|
||||||
|
register<GenerateLexerTask>("generateStringLexer") {
|
||||||
|
purgeOldFiles = true
|
||||||
|
sourceFile = file("src/main/grammar/ZigString.flex")
|
||||||
|
targetOutputDir = layout.buildDirectory.dir("$grammarGenRoot/stringlexer/$rootPackagePath/stringlexer")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
generateParser {
|
||||||
|
purgeOldFiles = true
|
||||||
|
sourceFile = file("src/main/grammar/Zig.bnf")
|
||||||
|
targetRootOutputDir = layout.buildDirectory.dir("$grammarGenRoot/parser")
|
||||||
|
pathToParser = "$rootPackagePath/psi/ZigParser.java"
|
||||||
|
pathToPsiRoot = "$rootPackagePath/psi"
|
||||||
|
}
|
||||||
|
|
||||||
|
register<DefaultTask>("generateGrammars") {
|
||||||
|
group = "grammarkit"
|
||||||
|
dependsOn("generateLexer")
|
||||||
|
dependsOn("generateStringLexer")
|
||||||
|
dependsOn("generateParser")
|
||||||
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
dependsOn("generateGrammars")
|
||||||
|
}
|
||||||
|
|
||||||
|
compileKotlin {
|
||||||
|
dependsOn("generateGrammars")
|
||||||
|
}
|
||||||
|
}
|
568
modules/zig/src/main/grammar/Zig.bnf
Normal file
568
modules/zig/src/main/grammar/Zig.bnf
Normal file
|
@ -0,0 +1,568 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
parserClass="com.falsepattern.zigbrains.zig.parser.ZigParser"
|
||||||
|
|
||||||
|
extends="com.intellij.extapi.psi.ASTWrapperPsiElement"
|
||||||
|
extends(".*Expr")=Expr
|
||||||
|
|
||||||
|
psiClassPrefix="Zig"
|
||||||
|
psiImplClassSuffix="Impl"
|
||||||
|
psiPackage="com.falsepattern.zigbrains.zig.psi"
|
||||||
|
psiImplPackage="com.falsepattern.zigbrains.zig.psi.impl"
|
||||||
|
|
||||||
|
elementTypeHolderClass="com.falsepattern.zigbrains.zig.psi.ZigTypes"
|
||||||
|
elementTypeClass="com.falsepattern.zigbrains.zig.parser.ZigElementType"
|
||||||
|
|
||||||
|
tokenTypeClass="com.falsepattern.zigbrains.zig.parser.ZigTokenType"
|
||||||
|
generateTokenAccessors = true
|
||||||
|
tokens=[
|
||||||
|
|
||||||
|
//Symbols
|
||||||
|
AMPERSAND='&'
|
||||||
|
AMPERSANDEQUAL='&='
|
||||||
|
ASTERISK='*'
|
||||||
|
ASTERISK2='**'
|
||||||
|
ASTERISKEQUAL='*='
|
||||||
|
ASTERISKPERCENT='*%'
|
||||||
|
ASTERISKPERCENTEQUAL='*%='
|
||||||
|
ASTERISKPIPE='*|'
|
||||||
|
ASTERISKPIPEEQUAL='*|='
|
||||||
|
CARET='^'
|
||||||
|
CARETEQUAL='^='
|
||||||
|
COLON=':'
|
||||||
|
COMMA=','
|
||||||
|
DOT='.'
|
||||||
|
DOT2='..'
|
||||||
|
DOT3='...'
|
||||||
|
DOTASTERISK='.*'
|
||||||
|
DOTQUESTIONMARK='.?'
|
||||||
|
EQUAL='='
|
||||||
|
EQUALEQUAL='=='
|
||||||
|
EQUALRARROW='=>'
|
||||||
|
EXCLAMATIONMARK='!'
|
||||||
|
EXCLAMATIONMARKEQUAL='!='
|
||||||
|
LARROW='<'
|
||||||
|
LARROW2='<<'
|
||||||
|
LARROW2EQUAL='<<='
|
||||||
|
LARROW2PIPE='<<|'
|
||||||
|
LARROW2PIPEEQUAL='<<|='
|
||||||
|
LARROWEQUAL='<='
|
||||||
|
LBRACE='{'
|
||||||
|
LBRACKET='['
|
||||||
|
LPAREN='('
|
||||||
|
MINUS='-'
|
||||||
|
MINUSEQUAL='-='
|
||||||
|
MINUSPERCENT='-%'
|
||||||
|
MINUSPERCENTEQUAL='-%='
|
||||||
|
MINUSPIPE='-|'
|
||||||
|
MINUSPIPEEQUAL='-|='
|
||||||
|
MINUSRARROW='->'
|
||||||
|
PERCENT='%'
|
||||||
|
PERCENTEQUAL='%='
|
||||||
|
PIPE='|'
|
||||||
|
PIPE2='||'
|
||||||
|
PIPEEQUAL='|='
|
||||||
|
PLUS='+'
|
||||||
|
PLUS2='++'
|
||||||
|
PLUSEQUAL='+='
|
||||||
|
PLUSPERCENT='+%'
|
||||||
|
PLUSPERCENTEQUAL='+%='
|
||||||
|
PLUSPIPE='+|'
|
||||||
|
PLUSPIPEEQUAL='+|='
|
||||||
|
QUESTIONMARK='?'
|
||||||
|
RARROW='>'
|
||||||
|
RARROW2='>>'
|
||||||
|
RARROW2EQUAL='>>='
|
||||||
|
RARROWEQUAL='>='
|
||||||
|
RBRACE='}'
|
||||||
|
RBRACKET=']'
|
||||||
|
RPAREN=')'
|
||||||
|
SEMICOLON=';'
|
||||||
|
SLASH='/'
|
||||||
|
SLASHEQUAL='/='
|
||||||
|
TILDE='~'
|
||||||
|
|
||||||
|
//Keywords
|
||||||
|
KEYWORD_ADDRSPACE='addrspace'
|
||||||
|
KEYWORD_ALIGN='align'
|
||||||
|
KEYWORD_ALLOWZERO='allowzero'
|
||||||
|
KEYWORD_AND='and'
|
||||||
|
KEYWORD_ANYFRAME='anyframe'
|
||||||
|
KEYWORD_ANYTYPE='anytype'
|
||||||
|
KEYWORD_ASM='asm'
|
||||||
|
KEYWORD_ASYNC='async'
|
||||||
|
KEYWORD_AWAIT='await'
|
||||||
|
KEYWORD_BREAK='break'
|
||||||
|
KEYWORD_CALLCONV='callconv'
|
||||||
|
KEYWORD_CATCH='catch'
|
||||||
|
KEYWORD_COMPTIME='comptime'
|
||||||
|
KEYWORD_CONST='const'
|
||||||
|
KEYWORD_CONTINUE='continue'
|
||||||
|
KEYWORD_DEFER='defer'
|
||||||
|
KEYWORD_ELSE='else'
|
||||||
|
KEYWORD_ENUM='enum'
|
||||||
|
KEYWORD_ERRDEFER='errdefer'
|
||||||
|
KEYWORD_ERROR='error'
|
||||||
|
KEYWORD_EXPORT='export'
|
||||||
|
KEYWORD_EXTERN='extern'
|
||||||
|
KEYWORD_FN='fn'
|
||||||
|
KEYWORD_FOR='for'
|
||||||
|
KEYWORD_IF='if'
|
||||||
|
KEYWORD_INLINE='inline'
|
||||||
|
KEYWORD_NOALIAS='noalias'
|
||||||
|
KEYWORD_NOSUSPEND='nosuspend'
|
||||||
|
KEYWORD_NOINLINE='noinline'
|
||||||
|
KEYWORD_OPAQUE='opaque'
|
||||||
|
KEYWORD_OR='or'
|
||||||
|
KEYWORD_ORELSE='orelse'
|
||||||
|
KEYWORD_PACKED='packed'
|
||||||
|
KEYWORD_PUB='pub'
|
||||||
|
KEYWORD_RESUME='resume'
|
||||||
|
KEYWORD_RETURN='return'
|
||||||
|
KEYWORD_LINKSECTION='linksection'
|
||||||
|
KEYWORD_STRUCT='struct'
|
||||||
|
KEYWORD_SUSPEND='suspend'
|
||||||
|
KEYWORD_SWITCH='switch'
|
||||||
|
KEYWORD_TEST='test'
|
||||||
|
KEYWORD_THREADLOCAL='threadlocal'
|
||||||
|
KEYWORD_TRY='try'
|
||||||
|
KEYWORD_UNION='union'
|
||||||
|
KEYWORD_UNREACHABLE='unreachable'
|
||||||
|
KEYWORD_USINGNAMESPACE='usingnamespace'
|
||||||
|
KEYWORD_VAR='var'
|
||||||
|
KEYWORD_VOLATILE='volatile'
|
||||||
|
KEYWORD_WHILE='while'
|
||||||
|
|
||||||
|
CONTAINER_DOC_COMMENT='container doc comment'
|
||||||
|
DOC_COMMENT='doc comment'
|
||||||
|
LINE_COMMENT='comment'
|
||||||
|
|
||||||
|
CHAR_LITERAL='character literal'
|
||||||
|
|
||||||
|
FLOAT='float'
|
||||||
|
INTEGER='integer'
|
||||||
|
|
||||||
|
STRING_LITERAL_SINGLE='quoted string literal'
|
||||||
|
STRING_LITERAL_MULTI='multiline string literal'
|
||||||
|
|
||||||
|
IDENTIFIER='identifier'
|
||||||
|
BUILTINIDENTIFIER='builtin identifier'
|
||||||
|
]
|
||||||
|
|
||||||
|
//Mixins
|
||||||
|
// mixin("StringLiteral")="com.falsepattern.zigbrains.zig.psi.impl.mixins.ZigStringLiteralMixinImpl"
|
||||||
|
// implements("StringLiteral")="com.falsepattern.zigbrains.zig.psi.mixins.ZigStringLiteralMixin"
|
||||||
|
}
|
||||||
|
|
||||||
|
Root ::= CONTAINER_DOC_COMMENT? ContainerMembers?
|
||||||
|
|
||||||
|
// *** Top level ***
|
||||||
|
ContainerMembers ::= ContainerDeclarations? (ContainerField COMMA)* (ContainerField | ContainerDeclarations)?
|
||||||
|
|
||||||
|
ContainerDeclarations ::= (TestDecl | ComptimeDecl | DOC_COMMENT? KEYWORD_PUB? Decl)+
|
||||||
|
|
||||||
|
TestDecl ::= DOC_COMMENT? KEYWORD_TEST (STRING_LITERAL_SINGLE | IDENTIFIER)? Block {pin=2}
|
||||||
|
|
||||||
|
ComptimeDecl ::= KEYWORD_COMPTIME Block
|
||||||
|
|
||||||
|
Decl
|
||||||
|
::= (KEYWORD_EXPORT | KEYWORD_EXTERN STRING_LITERAL_SINGLE? | KEYWORD_INLINE | KEYWORD_NOINLINE)? FnProto (SEMICOLON | Block)
|
||||||
|
| (KEYWORD_EXPORT | KEYWORD_EXTERN STRING_LITERAL_SINGLE?)? KEYWORD_THREADLOCAL? GlobalVarDecl
|
||||||
|
| KEYWORD_USINGNAMESPACE Expr SEMICOLON
|
||||||
|
|
||||||
|
FnProto ::= KEYWORD_FN IDENTIFIER? LPAREN ParamDeclList RPAREN ByteAlign? AddrSpace? LinkSection? CallConv? EXCLAMATIONMARK? TypeExpr {pin=1}
|
||||||
|
|
||||||
|
VarDeclProto ::= (KEYWORD_CONST | KEYWORD_VAR) IDENTIFIER (COLON TypeExpr)? ByteAlign? AddrSpace? LinkSection? {pin=1}
|
||||||
|
|
||||||
|
GlobalVarDecl ::= VarDeclProto (EQUAL Expr)? SEMICOLON {pin=1}
|
||||||
|
|
||||||
|
ContainerField ::= DOC_COMMENT? KEYWORD_COMPTIME? !KEYWORD_FN (IDENTIFIER COLON)? TypeExpr ByteAlign? (EQUAL Expr)? {pin=5}
|
||||||
|
|
||||||
|
// *** Block Level ***
|
||||||
|
Statement
|
||||||
|
::= KEYWORD_COMPTIME ComptimeStatement
|
||||||
|
| KEYWORD_NOSUSPEND BlockExprStatement
|
||||||
|
| KEYWORD_DEFER BlockExprStatement
|
||||||
|
| KEYWORD_ERRDEFER Payload? BlockExprStatement
|
||||||
|
| IfStatement
|
||||||
|
| LabeledStatement
|
||||||
|
| VarDeclExprStatement
|
||||||
|
|
||||||
|
ComptimeStatement
|
||||||
|
::= BlockExpr
|
||||||
|
| VarDeclExprStatement
|
||||||
|
|
||||||
|
IfStatement
|
||||||
|
::= IfPrefix ZB_IfStatement_Body {pin(".*")=1}
|
||||||
|
|
||||||
|
private ZB_IfStatement_Body
|
||||||
|
::= BlockExpr ( KEYWORD_ELSE Payload? Statement )?
|
||||||
|
| AssignExpr ( SEMICOLON | KEYWORD_ELSE Payload? Statement )
|
||||||
|
|
||||||
|
LabeledStatement ::= BlockLabel? (Block | LoopStatement | SwitchExpr)
|
||||||
|
|
||||||
|
LoopStatement ::= KEYWORD_INLINE? (ForStatement | WhileStatement)
|
||||||
|
|
||||||
|
ForStatement
|
||||||
|
::= ForPrefix ZB_ForStatement_Body {pin(".*")=1}
|
||||||
|
|
||||||
|
private ZB_ForStatement_Body
|
||||||
|
::= BlockExpr ( KEYWORD_ELSE Statement )?
|
||||||
|
| AssignExpr ( SEMICOLON | KEYWORD_ELSE Statement )
|
||||||
|
|
||||||
|
WhileStatement
|
||||||
|
::= WhilePrefix ZB_WhileStatement_Body {pin(".*") =1}
|
||||||
|
|
||||||
|
private ZB_WhileStatement_Body
|
||||||
|
::= BlockExpr ( KEYWORD_ELSE Payload? Statement )?
|
||||||
|
| AssignExpr ( SEMICOLON | KEYWORD_ELSE Payload? Statement)
|
||||||
|
|
||||||
|
BlockExprStatement
|
||||||
|
::= BlockExpr
|
||||||
|
| ZB_BlockExprStatement_AssignExpr
|
||||||
|
|
||||||
|
private ZB_BlockExprStatement_AssignExpr ::= AssignExpr SEMICOLON {pin=1}
|
||||||
|
|
||||||
|
BlockExpr ::= BlockLabel? Block
|
||||||
|
|
||||||
|
//An expression, assignment, or any destructure, as a statement.
|
||||||
|
VarDeclExprStatement
|
||||||
|
::= VarDeclProto (COMMA (VarDeclProto | Expr))* EQUAL Expr SEMICOLON
|
||||||
|
| Expr (AssignOp Expr | (COMMA (VarDeclProto | Expr))+ EQUAL Expr)? SEMICOLON {pin(".*")=1}
|
||||||
|
|
||||||
|
// *** Expression Level ***
|
||||||
|
|
||||||
|
// An assignment or a destructure whose LHS are all lvalue expressions.
|
||||||
|
AssignExpr ::= Expr (AssignOp Expr | (COMMA Expr)+ EQUAL Expr)?
|
||||||
|
|
||||||
|
SingleAssignExpr ::= Expr (AssignOp Expr)?
|
||||||
|
|
||||||
|
Expr ::= BoolOrExpr
|
||||||
|
|
||||||
|
BoolOrExpr ::= BoolAndExpr (KEYWORD_OR BoolAndExpr)*
|
||||||
|
|
||||||
|
BoolAndExpr ::= CompareExpr (KEYWORD_AND CompareExpr)*
|
||||||
|
|
||||||
|
CompareExpr ::= BitwiseExpr (CompareOp BitwiseExpr)?
|
||||||
|
|
||||||
|
BitwiseExpr ::= BitShiftExpr (BitwiseOp BitShiftExpr)*
|
||||||
|
|
||||||
|
BitShiftExpr ::= AdditionExpr (BitShiftOp AdditionExpr)*
|
||||||
|
|
||||||
|
AdditionExpr ::= MultiplyExpr (AdditionOp MultiplyExpr)*
|
||||||
|
|
||||||
|
MultiplyExpr ::= PrefixExpr (MultiplyOp PrefixExpr)*
|
||||||
|
|
||||||
|
PrefixExpr ::= PrefixOp* PrimaryExpr
|
||||||
|
|
||||||
|
PrimaryExpr
|
||||||
|
::= AsmExpr
|
||||||
|
| IfExpr
|
||||||
|
| KEYWORD_BREAK BreakLabel? Expr?
|
||||||
|
| KEYWORD_COMPTIME Expr
|
||||||
|
| KEYWORD_NOSUSPEND Expr
|
||||||
|
| KEYWORD_CONTINUE BreakLabel? Expr?
|
||||||
|
| KEYWORD_RESUME Expr
|
||||||
|
| KEYWORD_RETURN Expr?
|
||||||
|
| BlockLabel? LoopExpr
|
||||||
|
| Block
|
||||||
|
| CurlySuffixExpr
|
||||||
|
|
||||||
|
IfExpr ::= IfPrefix Expr (KEYWORD_ELSE Payload? Expr)?
|
||||||
|
|
||||||
|
Block ::= LBRACE ZB_Block_Statement RBRACE {pin=1}
|
||||||
|
|
||||||
|
private ZB_Block_Statement ::= Statement* {recoverWhile="ZB_Block_Statement_recover"}
|
||||||
|
|
||||||
|
private ZB_Block_Statement_recover ::= !(RBRACE)
|
||||||
|
|
||||||
|
LoopExpr ::= KEYWORD_INLINE? (ForExpr | WhileExpr)
|
||||||
|
|
||||||
|
ForExpr ::= ForPrefix Expr (KEYWORD_ELSE Expr)?
|
||||||
|
|
||||||
|
WhileExpr ::= WhilePrefix Expr (KEYWORD_ELSE Payload? Expr)?
|
||||||
|
|
||||||
|
CurlySuffixExpr ::= TypeExpr InitList?
|
||||||
|
|
||||||
|
InitList
|
||||||
|
::= LBRACE ZB_InitList_Body RBRACE {pin=1}
|
||||||
|
|
||||||
|
private ZB_InitList_Body
|
||||||
|
::= FieldInit (COMMA ZB_InitList_FieldInit)* COMMA?
|
||||||
|
| Expr (COMMA ZB_InitList_Expr)* COMMA?
|
||||||
|
| ()
|
||||||
|
|
||||||
|
private ZB_InitList_FieldInit ::= FieldInit {recoverWhile="ZB_InitList_Recover"}
|
||||||
|
private ZB_InitList_Expr ::= Expr {recoverWhile="ZB_InitList_Recover"}
|
||||||
|
|
||||||
|
private ZB_InitList_Recover ::= !(COMMA | RBRACE)
|
||||||
|
|
||||||
|
TypeExpr ::= PrefixTypeOp* ErrorUnionExpr
|
||||||
|
|
||||||
|
ErrorUnionExpr ::= SuffixExpr (EXCLAMATIONMARK TypeExpr)?
|
||||||
|
|
||||||
|
SuffixExpr
|
||||||
|
::= KEYWORD_ASYNC PrimaryTypeExpr SuffixOp* FnCallArguments
|
||||||
|
| PrimaryTypeExpr (SuffixOp | FnCallArguments)*
|
||||||
|
|
||||||
|
PrimaryTypeExpr
|
||||||
|
::= BUILTINIDENTIFIER FnCallArguments
|
||||||
|
| CHAR_LITERAL
|
||||||
|
| ContainerDecl
|
||||||
|
| DOT IDENTIFIER
|
||||||
|
| DOT InitList
|
||||||
|
| ErrorSetDecl
|
||||||
|
| FLOAT
|
||||||
|
| FnProto
|
||||||
|
| GroupedExpr
|
||||||
|
| LabeledTypeExpr
|
||||||
|
| IDENTIFIER
|
||||||
|
| IfTypeExpr
|
||||||
|
| INTEGER
|
||||||
|
| KEYWORD_COMPTIME TypeExpr
|
||||||
|
| KEYWORD_ERROR DOT IDENTIFIER
|
||||||
|
| KEYWORD_ANYFRAME
|
||||||
|
| KEYWORD_UNREACHABLE
|
||||||
|
| StringLiteral
|
||||||
|
|
||||||
|
ContainerDecl ::= (KEYWORD_EXTERN | KEYWORD_PACKED)? ContainerDeclAuto
|
||||||
|
|
||||||
|
ErrorSetDecl ::= KEYWORD_ERROR LBRACE IdentifierList RBRACE
|
||||||
|
|
||||||
|
GroupedExpr ::= LPAREN Expr RPAREN
|
||||||
|
|
||||||
|
IfTypeExpr ::= IfPrefix TypeExpr (KEYWORD_ELSE Payload? TypeExpr)?
|
||||||
|
|
||||||
|
LabeledTypeExpr
|
||||||
|
::= BlockLabel Block
|
||||||
|
| BlockLabel? LoopTypeExpr
|
||||||
|
| BlockLabel? SwitchExpr
|
||||||
|
|
||||||
|
LoopTypeExpr ::= KEYWORD_INLINE? (ForTypeExpr | WhileTypeExpr)
|
||||||
|
|
||||||
|
ForTypeExpr ::= ForPrefix TypeExpr (KEYWORD_ELSE TypeExpr)?
|
||||||
|
|
||||||
|
WhileTypeExpr ::= WhilePrefix TypeExpr (KEYWORD_ELSE Payload? TypeExpr)?
|
||||||
|
|
||||||
|
SwitchExpr ::= KEYWORD_SWITCH LPAREN Expr RPAREN LBRACE SwitchProngList RBRACE {pin=1}
|
||||||
|
|
||||||
|
// *** Assembly ***
|
||||||
|
AsmExpr ::= KEYWORD_ASM KEYWORD_VOLATILE? LPAREN Expr AsmOutput? RPAREN
|
||||||
|
|
||||||
|
AsmOutput ::= COLON AsmOutputList AsmInput?
|
||||||
|
|
||||||
|
AsmOutputItem ::= LBRACKET IDENTIFIER RBRACKET StringLiteral LPAREN (MINUSRARROW TypeExpr | IDENTIFIER) RPAREN
|
||||||
|
|
||||||
|
AsmInput ::= COLON AsmInputList AsmClobbers?
|
||||||
|
|
||||||
|
AsmInputItem ::= LBRACKET IDENTIFIER RBRACKET StringLiteral LPAREN Expr RPAREN
|
||||||
|
|
||||||
|
AsmClobbers ::= COLON StringList
|
||||||
|
|
||||||
|
// *** Helper grammar ***
|
||||||
|
BreakLabel ::= COLON IDENTIFIER
|
||||||
|
|
||||||
|
BlockLabel ::= IDENTIFIER COLON
|
||||||
|
|
||||||
|
FieldInit ::= DOT IDENTIFIER EQUAL Expr
|
||||||
|
|
||||||
|
WhileContinueExpr ::= COLON LPAREN AssignExpr RPAREN
|
||||||
|
|
||||||
|
LinkSection ::= KEYWORD_LINKSECTION LPAREN Expr RPAREN
|
||||||
|
|
||||||
|
AddrSpace ::= KEYWORD_ADDRSPACE LPAREN Expr RPAREN
|
||||||
|
|
||||||
|
// Fn specific
|
||||||
|
CallConv ::= KEYWORD_CALLCONV LPAREN Expr RPAREN
|
||||||
|
|
||||||
|
ParamDecl
|
||||||
|
::= DOC_COMMENT? (KEYWORD_NOALIAS | KEYWORD_COMPTIME)? (IDENTIFIER COLON)? ParamType
|
||||||
|
| DOT3
|
||||||
|
|
||||||
|
ParamType
|
||||||
|
::= KEYWORD_ANYTYPE
|
||||||
|
| TypeExpr
|
||||||
|
|
||||||
|
// Control flow prefixes
|
||||||
|
IfPrefix ::= KEYWORD_IF ZB_IfPrefix_Operand PtrPayload? {pin=1}
|
||||||
|
|
||||||
|
private ZB_IfPrefix_Operand ::= LPAREN Expr RPAREN {pin=1}
|
||||||
|
|
||||||
|
WhilePrefix ::= KEYWORD_WHILE ZB_WhilePrefix_Operand PtrPayload? WhileContinueExpr? {pin=1}
|
||||||
|
|
||||||
|
private ZB_WhilePrefix_Operand ::= LPAREN Expr RPAREN {pin=1}
|
||||||
|
|
||||||
|
ForRange ::= Expr DOT2 Expr?
|
||||||
|
ForOperand ::= ForRange | Expr {recoverWhile="ZB_ForOperand_Recover"}
|
||||||
|
|
||||||
|
private ZB_ForOperand_Recover ::= !(COMMA | RPAREN)
|
||||||
|
|
||||||
|
ForPrefix ::= KEYWORD_FOR ZB_ForPrefix_Operands PtrIndexPayload {pin=1}
|
||||||
|
|
||||||
|
private ZB_ForPrefix_Operands ::= LPAREN (ForOperand COMMA)* ForOperand RPAREN {pin=1}
|
||||||
|
|
||||||
|
// Payloads
|
||||||
|
Payload ::= PIPE IDENTIFIER PIPE
|
||||||
|
|
||||||
|
PtrPayload ::= PIPE ASTERISK? IDENTIFIER PIPE
|
||||||
|
|
||||||
|
PtrIndexPayload ::= PIPE (ASTERISK? IDENTIFIER COMMA)* (ASTERISK? IDENTIFIER) PIPE
|
||||||
|
|
||||||
|
// Switch specific
|
||||||
|
SwitchProng ::= KEYWORD_INLINE? SwitchCase EQUALRARROW PtrIndexPayload? SingleAssignExpr {pin=3}
|
||||||
|
|
||||||
|
SwitchCase
|
||||||
|
::= SwitchItem (COMMA SwitchItem)* COMMA?
|
||||||
|
| KEYWORD_ELSE
|
||||||
|
|
||||||
|
SwitchItem ::= Expr (DOT3 Expr)?
|
||||||
|
|
||||||
|
// Operators
|
||||||
|
AssignOp
|
||||||
|
::= ASTERISKEQUAL
|
||||||
|
| ASTERISKPIPEEQUAL
|
||||||
|
| SLASHEQUAL
|
||||||
|
| PERCENTEQUAL
|
||||||
|
| PLUSEQUAL
|
||||||
|
| PLUSPIPEEQUAL
|
||||||
|
| MINUSEQUAL
|
||||||
|
| MINUSPIPEEQUAL
|
||||||
|
| LARROW2EQUAL
|
||||||
|
| LARROW2PIPEEQUAL
|
||||||
|
| RARROW2EQUAL
|
||||||
|
| AMPERSANDEQUAL
|
||||||
|
| CARETEQUAL
|
||||||
|
| PIPEEQUAL
|
||||||
|
| ASTERISKPERCENTEQUAL
|
||||||
|
| PLUSPERCENTEQUAL
|
||||||
|
| MINUSPERCENTEQUAL
|
||||||
|
| EQUAL
|
||||||
|
|
||||||
|
CompareOp
|
||||||
|
::= EQUALEQUAL
|
||||||
|
| EXCLAMATIONMARKEQUAL
|
||||||
|
| LARROW
|
||||||
|
| RARROW
|
||||||
|
| LARROWEQUAL
|
||||||
|
| RARROWEQUAL
|
||||||
|
|
||||||
|
BitwiseOp
|
||||||
|
::= AMPERSAND
|
||||||
|
| CARET
|
||||||
|
| PIPE
|
||||||
|
| KEYWORD_ORELSE
|
||||||
|
| KEYWORD_CATCH Payload?
|
||||||
|
|
||||||
|
BitShiftOp
|
||||||
|
::= LARROW2
|
||||||
|
| RARROW2
|
||||||
|
| LARROW2PIPE
|
||||||
|
|
||||||
|
AdditionOp
|
||||||
|
::= PLUS
|
||||||
|
| MINUS
|
||||||
|
| PLUS2
|
||||||
|
| PLUSPERCENT
|
||||||
|
| MINUSPERCENT
|
||||||
|
| PLUSPIPE
|
||||||
|
| MINUSPIPE
|
||||||
|
|
||||||
|
MultiplyOp
|
||||||
|
::= PIPE2
|
||||||
|
| ASTERISK
|
||||||
|
| SLASH
|
||||||
|
| PERCENT
|
||||||
|
| ASTERISK2
|
||||||
|
| ASTERISKPERCENT
|
||||||
|
| ASTERISKPIPE
|
||||||
|
|
||||||
|
PrefixOp
|
||||||
|
::= EXCLAMATIONMARK
|
||||||
|
| MINUS
|
||||||
|
| TILDE
|
||||||
|
| MINUSPERCENT
|
||||||
|
| AMPERSAND
|
||||||
|
| KEYWORD_TRY
|
||||||
|
| KEYWORD_AWAIT
|
||||||
|
|
||||||
|
PrefixTypeOp
|
||||||
|
::= QUESTIONMARK
|
||||||
|
| KEYWORD_ANYFRAME MINUSRARROW
|
||||||
|
| SliceTypeStart (ByteAlign | AddrSpace | KEYWORD_CONST | KEYWORD_VOLATILE | KEYWORD_ALLOWZERO)*
|
||||||
|
| PtrTypeStart (AddrSpace | KEYWORD_ALIGN LPAREN Expr (COLON Expr COLON Expr)? RPAREN | KEYWORD_CONST | KEYWORD_VOLATILE | KEYWORD_ALLOWZERO)*
|
||||||
|
| ArrayTypeStart
|
||||||
|
|
||||||
|
SuffixOp
|
||||||
|
::= LBRACKET Expr (DOT2 (Expr? (COLON Expr)?)?)? RBRACKET
|
||||||
|
| DOT IDENTIFIER
|
||||||
|
| DOTASTERISK
|
||||||
|
| DOTQUESTIONMARK
|
||||||
|
|
||||||
|
FnCallArguments ::= LPAREN ExprList RPAREN {pin=1}
|
||||||
|
|
||||||
|
// Ptr specific
|
||||||
|
SliceTypeStart ::= LBRACKET (COLON Expr)? RBRACKET
|
||||||
|
|
||||||
|
PtrTypeStart
|
||||||
|
::= ASTERISK
|
||||||
|
| ASTERISK2
|
||||||
|
| LBRACKET ASTERISK ("c" | COLON Expr)? RBRACKET
|
||||||
|
|
||||||
|
ArrayTypeStart ::= LBRACKET Expr (COLON Expr)? RBRACKET
|
||||||
|
|
||||||
|
// ContainerDecl specific
|
||||||
|
ContainerDeclAuto ::= ContainerDeclType LBRACE CONTAINER_DOC_COMMENT? ZB_ContainerDeclAuto_ContainerMembers RBRACE {pin=2}
|
||||||
|
|
||||||
|
private ZB_ContainerDeclAuto_ContainerMembers ::= ContainerMembers {recoverWhile="ZB_ContainerDeclAuto_ContainerMembers_recover"}
|
||||||
|
private ZB_ContainerDeclAuto_ContainerMembers_recover ::= !(RBRACE)
|
||||||
|
|
||||||
|
ContainerDeclType
|
||||||
|
::= KEYWORD_STRUCT (LPAREN ZB_ContainerDeclType_Expr RPAREN)?
|
||||||
|
| KEYWORD_OPAQUE
|
||||||
|
| KEYWORD_ENUM (LPAREN ZB_ContainerDeclType_Expr RPAREN)?
|
||||||
|
| KEYWORD_UNION (LPAREN (KEYWORD_ENUM (LPAREN ZB_ContainerDeclType_Expr RPAREN)? | ZB_ContainerDeclType_Expr) RPAREN)? {pin(".*")=1}
|
||||||
|
|
||||||
|
private ZB_ContainerDeclType_Expr ::= Expr {recoverWhile="ZB_ContainerDeclType_Expr_recover"}
|
||||||
|
private ZB_ContainerDeclType_Expr_recover ::= !(RPAREN)
|
||||||
|
|
||||||
|
// Alignment
|
||||||
|
ByteAlign ::= KEYWORD_ALIGN LPAREN Expr RPAREN
|
||||||
|
|
||||||
|
// Lists
|
||||||
|
IdentifierList ::= (DOC_COMMENT? IDENTIFIER COMMA)* (DOC_COMMENT? IDENTIFIER)?
|
||||||
|
|
||||||
|
SwitchProngList ::= (ZB_SwitchProngList_SwitchProng COMMA)* ZB_SwitchProngList_SwitchProng?
|
||||||
|
|
||||||
|
private ZB_SwitchProngList_SwitchProng ::= SwitchProng {recoverWhile="ZB_SwitchProngList_Recover"}
|
||||||
|
|
||||||
|
private ZB_SwitchProngList_Recover ::= !(COMMA | RBRACE)
|
||||||
|
|
||||||
|
AsmOutputList ::= (AsmOutputItem COMMA)* AsmOutputItem?
|
||||||
|
|
||||||
|
AsmInputList ::= (AsmInputItem COMMA)* AsmInputItem?
|
||||||
|
|
||||||
|
StringList ::= (StringLiteral COMMA)* StringLiteral?
|
||||||
|
|
||||||
|
ParamDeclList ::= (ParamDecl COMMA)* ParamDecl?
|
||||||
|
|
||||||
|
ExprList ::= (ZB_ExprList_Expr COMMA)* ZB_ExprList_Expr?
|
||||||
|
|
||||||
|
private ZB_ExprList_Expr ::= Expr {recoverWhile="ZB_ExprList_recover"}
|
||||||
|
private ZB_ExprList_recover ::= !(RPAREN | COMMA)
|
||||||
|
|
||||||
|
StringLiteral ::= STRING_LITERAL_SINGLE | STRING_LITERAL_MULTI
|
282
modules/zig/src/main/grammar/Zig.flex
Normal file
282
modules/zig/src/main/grammar/Zig.flex
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
* 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.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.zig.psi.ZigTypes.*;
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
%class ZigFlexLexer
|
||||||
|
%implements FlexLexer
|
||||||
|
%function advance
|
||||||
|
%type IElementType
|
||||||
|
|
||||||
|
CRLF=\R
|
||||||
|
WHITE_SPACE=[\s]+
|
||||||
|
|
||||||
|
bin=[01]
|
||||||
|
bin_="_"? {bin}
|
||||||
|
oct=[0-7]
|
||||||
|
oct_="_"? {oct}
|
||||||
|
hex=[0-9a-fA-F]
|
||||||
|
hex_="_"? {hex}
|
||||||
|
dec=[0-9]
|
||||||
|
dec_="_"? {dec}
|
||||||
|
|
||||||
|
bin_int={bin} {bin_}*
|
||||||
|
oct_int={oct} {oct_}*
|
||||||
|
dec_int={dec} {dec_}*
|
||||||
|
hex_int={hex} {hex_}*
|
||||||
|
|
||||||
|
ox80_oxBF=[\200-\277]
|
||||||
|
oxF4=\364
|
||||||
|
ox80_ox8F=[\200-\217]
|
||||||
|
oxF1_oxF3=[\361-\363]
|
||||||
|
oxF0=\360
|
||||||
|
ox90_0xBF=[\220-\277]
|
||||||
|
oxEE_oxEF=[\356-\357]
|
||||||
|
oxED=\355
|
||||||
|
ox80_ox9F=[\200-\237]
|
||||||
|
oxE1_oxEC=[\341-\354]
|
||||||
|
oxE0=\340
|
||||||
|
oxA0_oxBF=[\240-\277]
|
||||||
|
oxC2_oxDF=[\302-\337]
|
||||||
|
|
||||||
|
// From https://lemire.me/blog/2018/05/09/how-quickly-can-you-check-that-a-string-is-valid-unicode-utf-8/
|
||||||
|
// First Byte Second Byte Third Byte Fourth Byte
|
||||||
|
// [0x00,0x7F]
|
||||||
|
// [0xC2,0xDF] [0x80,0xBF]
|
||||||
|
// 0xE0 [0xA0,0xBF] [0x80,0xBF]
|
||||||
|
// [0xE1,0xEC] [0x80,0xBF] [0x80,0xBF]
|
||||||
|
// 0xED [0x80,0x9F] [0x80,0xBF]
|
||||||
|
// [0xEE,0xEF] [0x80,0xBF] [0x80,0xBF]
|
||||||
|
// 0xF0 [0x90,0xBF] [0x80,0xBF] [0x80,0xBF]
|
||||||
|
// [0xF1,0xF3] [0x80,0xBF] [0x80,0xBF] [0x80,0xBF]
|
||||||
|
// 0xF4 [0x80,0x8F] [0x80,0xBF] [0x80,0xBF]
|
||||||
|
|
||||||
|
mb_utf8_literal= {oxF4} {ox80_ox8F} {ox80_oxBF} {ox80_oxBF}
|
||||||
|
| {oxF1_oxF3} {ox80_oxBF} {ox80_oxBF} {ox80_oxBF}
|
||||||
|
| {oxF0} {ox90_0xBF} {ox80_oxBF} {ox80_oxBF}
|
||||||
|
| {oxEE_oxEF} {ox80_oxBF} {ox80_oxBF}
|
||||||
|
| {oxED} {ox80_ox9F} {ox80_oxBF}
|
||||||
|
| {oxE1_oxEC} {ox80_oxBF} {ox80_oxBF}
|
||||||
|
| {oxE0} {oxA0_oxBF} {ox80_oxBF}
|
||||||
|
| {oxC2_oxDF} {ox80_oxBF}
|
||||||
|
|
||||||
|
ascii_char_not_nl_slash_squote=[\000-\011\013-\046\050-\133\135-\177]
|
||||||
|
|
||||||
|
char_escape= "\\x" {hex} {hex}
|
||||||
|
| "\\u{" {hex}+ "}"
|
||||||
|
| "\\" [nr\\t'\"]
|
||||||
|
char_char= {mb_utf8_literal}
|
||||||
|
| {char_escape}
|
||||||
|
| {ascii_char_not_nl_slash_squote}
|
||||||
|
|
||||||
|
string_char= \\ .
|
||||||
|
| [^\"\n]
|
||||||
|
|
||||||
|
all_nl_wrap=[^\n]* [ \n]*
|
||||||
|
all_nl_nowrap=[^\n]* \n
|
||||||
|
|
||||||
|
|
||||||
|
FLOAT= "0x" {hex_int} "." {hex_int} ([pP] [-+]? {dec_int})?
|
||||||
|
| {dec_int} "." {dec_int} ([eE] [-+]? {dec_int})?
|
||||||
|
| "0x" {hex_int} [pP] [-+]? {dec_int}
|
||||||
|
| {dec_int} [eE] [-+]? {dec_int}
|
||||||
|
|
||||||
|
INTEGER= "0b" {bin_int}
|
||||||
|
| "0o" {oct_int}
|
||||||
|
| "0x" {hex_int}
|
||||||
|
| {dec_int}
|
||||||
|
|
||||||
|
IDENTIFIER_PLAIN=[A-Za-z_][A-Za-z0-9_]*
|
||||||
|
BUILTINIDENTIFIER="@"[A-Za-z_][A-Za-z0-9_]*
|
||||||
|
|
||||||
|
%state STR_LIT
|
||||||
|
%state STR_MULT_LINE
|
||||||
|
%state CHAR_LIT
|
||||||
|
|
||||||
|
%state ID_QUOT
|
||||||
|
%state UNT_QUOT
|
||||||
|
|
||||||
|
%state CDOC_CMT
|
||||||
|
%state DOC_CMT
|
||||||
|
%state LINE_CMT
|
||||||
|
%%
|
||||||
|
|
||||||
|
//Comments
|
||||||
|
|
||||||
|
<YYINITIAL> "//!" { yybegin(CDOC_CMT); }
|
||||||
|
<CDOC_CMT> {all_nl_wrap} "//!" { }
|
||||||
|
<CDOC_CMT> {all_nl_nowrap} { yybegin(YYINITIAL); return CONTAINER_DOC_COMMENT; }
|
||||||
|
|
||||||
|
<YYINITIAL> "///" { yybegin(DOC_CMT); }
|
||||||
|
<DOC_CMT> {all_nl_wrap} "///" { }
|
||||||
|
<DOC_CMT> {all_nl_nowrap} { yybegin(YYINITIAL); return DOC_COMMENT; }
|
||||||
|
|
||||||
|
<YYINITIAL> "//" { yybegin(LINE_CMT); }
|
||||||
|
<LINE_CMT> {all_nl_wrap} "//" { }
|
||||||
|
<LINE_CMT> {all_nl_nowrap} { yybegin(YYINITIAL); return LINE_COMMENT; }
|
||||||
|
|
||||||
|
//Symbols
|
||||||
|
<YYINITIAL> "&" { return AMPERSAND; }
|
||||||
|
<YYINITIAL> "&=" { return AMPERSANDEQUAL; }
|
||||||
|
<YYINITIAL> "*" { return ASTERISK; }
|
||||||
|
<YYINITIAL> "**" { return ASTERISK2; }
|
||||||
|
<YYINITIAL> "*=" { return ASTERISKEQUAL; }
|
||||||
|
<YYINITIAL> "*%" { return ASTERISKPERCENT; }
|
||||||
|
<YYINITIAL> "*%=" { return ASTERISKPERCENTEQUAL; }
|
||||||
|
<YYINITIAL> "*|" { return ASTERISKPIPE; }
|
||||||
|
<YYINITIAL> "*|=" { return ASTERISKPIPEEQUAL; }
|
||||||
|
<YYINITIAL> "^" { return CARET; }
|
||||||
|
<YYINITIAL> "^=" { return CARETEQUAL; }
|
||||||
|
<YYINITIAL> ":" { return COLON; }
|
||||||
|
<YYINITIAL> "," { return COMMA; }
|
||||||
|
<YYINITIAL> "." { return DOT; }
|
||||||
|
<YYINITIAL> ".." { return DOT2; }
|
||||||
|
<YYINITIAL> "..." { return DOT3; }
|
||||||
|
<YYINITIAL> ".*" { return DOTASTERISK; }
|
||||||
|
<YYINITIAL> ".?" { return DOTQUESTIONMARK; }
|
||||||
|
<YYINITIAL> "=" { return EQUAL; }
|
||||||
|
<YYINITIAL> "==" { return EQUALEQUAL; }
|
||||||
|
<YYINITIAL> "=>" { return EQUALRARROW; }
|
||||||
|
<YYINITIAL> "!" { return EXCLAMATIONMARK; }
|
||||||
|
<YYINITIAL> "!=" { return EXCLAMATIONMARKEQUAL; }
|
||||||
|
<YYINITIAL> "<" { return LARROW; }
|
||||||
|
<YYINITIAL> "<<" { return LARROW2; }
|
||||||
|
<YYINITIAL> "<<=" { return LARROW2EQUAL; }
|
||||||
|
<YYINITIAL> "<<|" { return LARROW2PIPE; }
|
||||||
|
<YYINITIAL> "<<|=" { return LARROW2PIPEEQUAL; }
|
||||||
|
<YYINITIAL> "<=" { return LARROWEQUAL; }
|
||||||
|
<YYINITIAL> "{" { return LBRACE; }
|
||||||
|
<YYINITIAL> "[" { return LBRACKET; }
|
||||||
|
<YYINITIAL> "(" { return LPAREN; }
|
||||||
|
<YYINITIAL> "-" { return MINUS; }
|
||||||
|
<YYINITIAL> "-=" { return MINUSEQUAL; }
|
||||||
|
<YYINITIAL> "-%" { return MINUSPERCENT; }
|
||||||
|
<YYINITIAL> "-%=" { return MINUSPERCENTEQUAL; }
|
||||||
|
<YYINITIAL> "-|" { return MINUSPIPE; }
|
||||||
|
<YYINITIAL> "-|=" { return MINUSPIPEEQUAL; }
|
||||||
|
<YYINITIAL> "->" { return MINUSRARROW; }
|
||||||
|
<YYINITIAL> "%" { return PERCENT; }
|
||||||
|
<YYINITIAL> "%=" { return PERCENTEQUAL; }
|
||||||
|
<YYINITIAL> "|" { return PIPE; }
|
||||||
|
<YYINITIAL> "||" { return PIPE2; }
|
||||||
|
<YYINITIAL> "|=" { return PIPEEQUAL; }
|
||||||
|
<YYINITIAL> "+" { return PLUS; }
|
||||||
|
<YYINITIAL> "++" { return PLUS2; }
|
||||||
|
<YYINITIAL> "+=" { return PLUSEQUAL; }
|
||||||
|
<YYINITIAL> "+%" { return PLUSPERCENT; }
|
||||||
|
<YYINITIAL> "+%=" { return PLUSPERCENTEQUAL; }
|
||||||
|
<YYINITIAL> "+|" { return PLUSPIPE; }
|
||||||
|
<YYINITIAL> "+|=" { return PLUSPIPEEQUAL; }
|
||||||
|
//This one is directly in the tokenizer, because it conflicts with identifiers without context
|
||||||
|
//<YYINITIAL> "c" { return LETTERC; }
|
||||||
|
<YYINITIAL> "?" { return QUESTIONMARK; }
|
||||||
|
<YYINITIAL> ">" { return RARROW; }
|
||||||
|
<YYINITIAL> ">>" { return RARROW2; }
|
||||||
|
<YYINITIAL> ">>=" { return RARROW2EQUAL; }
|
||||||
|
<YYINITIAL> ">=" { return RARROWEQUAL; }
|
||||||
|
<YYINITIAL> "}" { return RBRACE; }
|
||||||
|
<YYINITIAL> "]" { return RBRACKET; }
|
||||||
|
<YYINITIAL> ")" { return RPAREN; }
|
||||||
|
<YYINITIAL> ";" { return SEMICOLON; }
|
||||||
|
<YYINITIAL> "/" { return SLASH; }
|
||||||
|
<YYINITIAL> "/=" { return SLASHEQUAL; }
|
||||||
|
<YYINITIAL> "~" { return TILDE; }
|
||||||
|
|
||||||
|
// keywords
|
||||||
|
<YYINITIAL> "addrspace" { return KEYWORD_ADDRSPACE; }
|
||||||
|
<YYINITIAL> "align" { return KEYWORD_ALIGN; }
|
||||||
|
<YYINITIAL> "allowzero" { return KEYWORD_ALLOWZERO; }
|
||||||
|
<YYINITIAL> "and" { return KEYWORD_AND; }
|
||||||
|
<YYINITIAL> "anyframe" { return KEYWORD_ANYFRAME; }
|
||||||
|
<YYINITIAL> "anytype" { return KEYWORD_ANYTYPE; }
|
||||||
|
<YYINITIAL> "asm" { return KEYWORD_ASM; }
|
||||||
|
<YYINITIAL> "async" { return KEYWORD_ASYNC; }
|
||||||
|
<YYINITIAL> "await" { return KEYWORD_AWAIT; }
|
||||||
|
<YYINITIAL> "break" { return KEYWORD_BREAK; }
|
||||||
|
<YYINITIAL> "callconv" { return KEYWORD_CALLCONV; }
|
||||||
|
<YYINITIAL> "catch" { return KEYWORD_CATCH; }
|
||||||
|
<YYINITIAL> "comptime" { return KEYWORD_COMPTIME; }
|
||||||
|
<YYINITIAL> "const" { return KEYWORD_CONST; }
|
||||||
|
<YYINITIAL> "continue" { return KEYWORD_CONTINUE; }
|
||||||
|
<YYINITIAL> "defer" { return KEYWORD_DEFER; }
|
||||||
|
<YYINITIAL> "else" { return KEYWORD_ELSE; }
|
||||||
|
<YYINITIAL> "enum" { return KEYWORD_ENUM; }
|
||||||
|
<YYINITIAL> "errdefer" { return KEYWORD_ERRDEFER; }
|
||||||
|
<YYINITIAL> "error" { return KEYWORD_ERROR; }
|
||||||
|
<YYINITIAL> "export" { return KEYWORD_EXPORT; }
|
||||||
|
<YYINITIAL> "extern" { return KEYWORD_EXTERN; }
|
||||||
|
<YYINITIAL> "fn" { return KEYWORD_FN; }
|
||||||
|
<YYINITIAL> "for" { return KEYWORD_FOR; }
|
||||||
|
<YYINITIAL> "if" { return KEYWORD_IF; }
|
||||||
|
<YYINITIAL> "inline" { return KEYWORD_INLINE; }
|
||||||
|
<YYINITIAL> "noalias" { return KEYWORD_NOALIAS; }
|
||||||
|
<YYINITIAL> "nosuspend" { return KEYWORD_NOSUSPEND; }
|
||||||
|
<YYINITIAL> "noinline" { return KEYWORD_NOINLINE; }
|
||||||
|
<YYINITIAL> "opaque" { return KEYWORD_OPAQUE; }
|
||||||
|
<YYINITIAL> "or" { return KEYWORD_OR; }
|
||||||
|
<YYINITIAL> "orelse" { return KEYWORD_ORELSE; }
|
||||||
|
<YYINITIAL> "packed" { return KEYWORD_PACKED; }
|
||||||
|
<YYINITIAL> "pub" { return KEYWORD_PUB; }
|
||||||
|
<YYINITIAL> "resume" { return KEYWORD_RESUME; }
|
||||||
|
<YYINITIAL> "return" { return KEYWORD_RETURN; }
|
||||||
|
<YYINITIAL> "linksection" { return KEYWORD_LINKSECTION; }
|
||||||
|
<YYINITIAL> "struct" { return KEYWORD_STRUCT; }
|
||||||
|
<YYINITIAL> "suspend" { return KEYWORD_SUSPEND; }
|
||||||
|
<YYINITIAL> "switch" { return KEYWORD_SWITCH; }
|
||||||
|
<YYINITIAL> "test" { return KEYWORD_TEST; }
|
||||||
|
<YYINITIAL> "threadlocal" { return KEYWORD_THREADLOCAL; }
|
||||||
|
<YYINITIAL> "try" { return KEYWORD_TRY; }
|
||||||
|
<YYINITIAL> "union" { return KEYWORD_UNION; }
|
||||||
|
<YYINITIAL> "unreachable" { return KEYWORD_UNREACHABLE; }
|
||||||
|
<YYINITIAL> "usingnamespace" { return KEYWORD_USINGNAMESPACE; }
|
||||||
|
<YYINITIAL> "var" { return KEYWORD_VAR; }
|
||||||
|
<YYINITIAL> "volatile" { return KEYWORD_VOLATILE; }
|
||||||
|
<YYINITIAL> "while" { return KEYWORD_WHILE; }
|
||||||
|
|
||||||
|
<YYINITIAL> "'" { yybegin(CHAR_LIT); }
|
||||||
|
<CHAR_LIT> {char_char}"'" { yybegin(YYINITIAL); return CHAR_LITERAL; }
|
||||||
|
<CHAR_LIT> [^] { yypushback(1); yybegin(UNT_QUOT); }
|
||||||
|
|
||||||
|
<YYINITIAL> {FLOAT} { return FLOAT; }
|
||||||
|
<YYINITIAL> {INTEGER} { return INTEGER; }
|
||||||
|
|
||||||
|
<YYINITIAL> "\"" { yybegin(STR_LIT); }
|
||||||
|
<STR_LIT> {string_char}*"\"" { yybegin(YYINITIAL); return STRING_LITERAL_SINGLE; }
|
||||||
|
<STR_LIT> [^] { yypushback(1); yybegin(UNT_QUOT); }
|
||||||
|
<YYINITIAL> "\\\\" { yybegin(STR_MULT_LINE); }
|
||||||
|
<STR_MULT_LINE> {all_nl_wrap} "\\\\" { }
|
||||||
|
<STR_MULT_LINE> {all_nl_nowrap} { yybegin(YYINITIAL); return STRING_LITERAL_MULTI; }
|
||||||
|
|
||||||
|
<YYINITIAL> {IDENTIFIER_PLAIN} { return IDENTIFIER; }
|
||||||
|
<YYINITIAL> "@\"" { yybegin(ID_QUOT); }
|
||||||
|
<ID_QUOT> {string_char}*"\"" { yybegin(YYINITIAL); return IDENTIFIER; }
|
||||||
|
<ID_QUOT> [^] { yypushback(1); yybegin(UNT_QUOT); }
|
||||||
|
|
||||||
|
<YYINITIAL> {BUILTINIDENTIFIER} { return BUILTINIDENTIFIER; }
|
||||||
|
|
||||||
|
<UNT_QUOT> [^\n]*{CRLF} { yybegin(YYINITIAL); return BAD_CHARACTER; }
|
||||||
|
|
||||||
|
<YYINITIAL> {WHITE_SPACE} { return WHITE_SPACE; }
|
||||||
|
|
||||||
|
[^] { return BAD_CHARACTER; }
|
62
modules/zig/src/main/grammar/ZigString.flex
Normal file
62
modules/zig/src/main/grammar/ZigString.flex
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
%{
|
||||||
|
public ZigStringLexer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
|
||||||
|
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'\"]
|
||||||
|
|
||||||
|
%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; }
|
||||||
|
}
|
|
@ -1,7 +1,6 @@
|
||||||
package com.falsepattern.zigbrains.zig
|
package com.falsepattern.zigbrains.zig
|
||||||
|
|
||||||
import com.intellij.openapi.fileTypes.LanguageFileType
|
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||||
import javax.swing.Icon
|
|
||||||
|
|
||||||
object ZigFileType : LanguageFileType(ZigLanguage) {
|
object ZigFileType : LanguageFileType(ZigLanguage) {
|
||||||
override fun getName() = "Zig File"
|
override fun getName() = "Zig File"
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.lexer
|
||||||
|
|
||||||
|
import com.intellij.lexer.FlexAdapter
|
||||||
|
|
||||||
|
class ZigLexerAdapter: FlexAdapter(ZigFlexLexer(null))
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.parser
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.ZigLanguage
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZigElementType(debugName: String): IElementType(debugName, ZigLanguage)
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.parser
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.ZigLanguage
|
||||||
|
import com.falsepattern.zigbrains.zig.lexer.ZigLexerAdapter
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.lang.ParserDefinition
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.FileViewProvider
|
||||||
|
import com.intellij.psi.tree.IFileElementType
|
||||||
|
|
||||||
|
class ZigParserDefinition : ParserDefinition {
|
||||||
|
override fun createLexer(project: Project?) = ZigLexerAdapter()
|
||||||
|
|
||||||
|
override fun createParser(project: Project?) = ZigParser()
|
||||||
|
|
||||||
|
override fun getFileNodeType() = FILE
|
||||||
|
|
||||||
|
override fun getCommentTokens() = ZigTokenSets.COMMENTS
|
||||||
|
|
||||||
|
override fun getStringLiteralElements() = ZigTokenSets.STRINGS
|
||||||
|
|
||||||
|
override fun createElement(node: ASTNode?) = ZigTypes.Factory.createElement(node)!!
|
||||||
|
|
||||||
|
override fun createFile(viewProvider: FileViewProvider) = ZigFile(viewProvider)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val FILE = IFileElementType(ZigLanguage)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.parser
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigTypes
|
||||||
|
import com.intellij.psi.tree.TokenSet
|
||||||
|
|
||||||
|
object ZigTokenSets {
|
||||||
|
val COMMENTS = TokenSet.create(ZigTypes.LINE_COMMENT, ZigTypes.DOC_COMMENT, ZigTypes.CONTAINER_DOC_COMMENT)
|
||||||
|
val STRINGS = TokenSet.create(ZigTypes.STRING_LITERAL_SINGLE, ZigTypes.STRING_LITERAL_MULTI)
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.parser
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.ZigLanguage
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZigTokenType(debugName: String): IElementType(debugName, ZigLanguage)
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.falsepattern.zigbrains.zig.psi
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zig.ZigFileType
|
||||||
|
import com.falsepattern.zigbrains.zig.ZigLanguage
|
||||||
|
import com.intellij.extapi.psi.PsiFileBase
|
||||||
|
import com.intellij.psi.FileViewProvider
|
||||||
|
|
||||||
|
class ZigFile(viewProvider: FileViewProvider): PsiFileBase(viewProvider, ZigLanguage) {
|
||||||
|
override fun getFileType() = ZigFileType
|
||||||
|
|
||||||
|
override fun toString() = ZigFileType.name
|
||||||
|
}
|
Before Width: | Height: | Size: 850 B After Width: | Height: | Size: 850 B |
64
modules/zon/build.gradle.kts
Normal file
64
modules/zon/build.gradle.kts
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
import org.jetbrains.intellij.platform.gradle.IntelliJPlatformType
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm")
|
||||||
|
id("org.jetbrains.grammarkit")
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
intellijPlatform {
|
||||||
|
create(IntelliJPlatformType.IntellijIdeaCommunity, providers.gradleProperty("ideaCommunityVersion"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val grammarGenRoot = "generated/sources/grammarkit/zon"
|
||||||
|
val rootPackagePath = "com/falsepattern/zigbrains/zon"
|
||||||
|
|
||||||
|
val parserDir = layout.buildDirectory.dir("$grammarGenRoot/parser")
|
||||||
|
val lexerDir = layout.buildDirectory.dir("$grammarGenRoot/lexer")
|
||||||
|
|
||||||
|
sourceSets {
|
||||||
|
main {
|
||||||
|
java {
|
||||||
|
srcDir(parserDir)
|
||||||
|
srcDir(lexerDir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
idea {
|
||||||
|
module {
|
||||||
|
sourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile))
|
||||||
|
generatedSourceDirs.addAll(listOf(parserDir.get().asFile, lexerDir.get().asFile))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks {
|
||||||
|
generateLexer {
|
||||||
|
purgeOldFiles = true
|
||||||
|
sourceFile = file("src/main/grammar/Zon.flex")
|
||||||
|
targetOutputDir = layout.buildDirectory.dir("$grammarGenRoot/lexer/$rootPackagePath/lexer")
|
||||||
|
}
|
||||||
|
|
||||||
|
generateParser {
|
||||||
|
purgeOldFiles = true
|
||||||
|
sourceFile = file("src/main/grammar/Zon.bnf")
|
||||||
|
targetRootOutputDir = layout.buildDirectory.dir("$grammarGenRoot/parser")
|
||||||
|
pathToParser = "$rootPackagePath/psi/ZonParser.java"
|
||||||
|
pathToPsiRoot = "$rootPackagePath/psi"
|
||||||
|
}
|
||||||
|
|
||||||
|
register<DefaultTask>("generateGrammars") {
|
||||||
|
group = "grammarkit"
|
||||||
|
dependsOn("generateLexer")
|
||||||
|
dependsOn("generateParser")
|
||||||
|
}
|
||||||
|
|
||||||
|
compileJava {
|
||||||
|
dependsOn("generateGrammars")
|
||||||
|
}
|
||||||
|
|
||||||
|
compileKotlin {
|
||||||
|
dependsOn("generateGrammars")
|
||||||
|
}
|
||||||
|
}
|
73
modules/zon/src/main/grammar/Zon.bnf
Normal file
73
modules/zon/src/main/grammar/Zon.bnf
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
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.parser.ZonElementType"
|
||||||
|
tokenTypeClass="com.falsepattern.zigbrains.zon.parser.ZonTokenType"
|
||||||
|
tokens=[
|
||||||
|
DOT='.'
|
||||||
|
LBRACE='{'
|
||||||
|
RBRACE='}'
|
||||||
|
EQ='='
|
||||||
|
COMMA=','
|
||||||
|
COMMENT='comment'
|
||||||
|
ID='identifier'
|
||||||
|
STRING_LITERAL_SINGLE='string'
|
||||||
|
LINE_STRING='multiline string'
|
||||||
|
BAD_STRING='unterminated string'
|
||||||
|
BOOL_TRUE='true'
|
||||||
|
BOOL_FALSE='false'
|
||||||
|
]
|
||||||
|
|
||||||
|
//Mixins
|
||||||
|
mixin("entry")="com.falsepattern.zigbrains.zon.psi.impl.mixins.ZonEntryMixinImpl"
|
||||||
|
implements("entry")="com.falsepattern.zigbrains.zon.psi.mixins.ZonEntryMixin"
|
||||||
|
|
||||||
|
mixin("identifier")="com.falsepattern.zigbrains.zon.psi.impl.mixins.ZonIdentifierMixinImpl"
|
||||||
|
implements("identifier")="com.falsepattern.zigbrains.zon.psi.mixins.ZonIdentifierMixin"
|
||||||
|
}
|
||||||
|
|
||||||
|
zonFile ::= entry
|
||||||
|
|
||||||
|
entry ::= DOT LBRACE (list | struct | ()) RBRACE
|
||||||
|
|
||||||
|
struct ::= (property | property_placeholder) (COMMA (property_placeholder? property property_placeholder? | property_placeholder))* COMMA?
|
||||||
|
|
||||||
|
list ::= value (COMMA value)* COMMA?
|
||||||
|
|
||||||
|
property ::= DOT identifier EQ value
|
||||||
|
|
||||||
|
identifier ::= ID
|
||||||
|
|
||||||
|
property_placeholder ::= DOT? INTELLIJ_COMPLETION_DUMMY
|
||||||
|
|
||||||
|
private value ::= entry | boolean | STRING_LITERAL | value_placeholder
|
||||||
|
|
||||||
|
value_placeholder ::= INTELLIJ_COMPLETION_DUMMY
|
||||||
|
|
||||||
|
boolean ::= BOOL_TRUE | BOOL_FALSE
|
||||||
|
|
||||||
|
STRING_LITERAL ::= STRING_LITERAL_SINGLE | LINE_STRING+
|
83
modules/zon/src/main/grammar/Zon.flex
Normal file
83
modules/zon/src/main/grammar/Zon.flex
Normal file
|
@ -0,0 +1,83 @@
|
||||||
|
/*
|
||||||
|
* 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.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
|
||||||
|
|
||||||
|
CRLF=\R
|
||||||
|
WHITE_SPACE=[\s]+
|
||||||
|
LINE_COMMENT="//" [^\n]* | "////" [^\n]*
|
||||||
|
COMMENT="///".*
|
||||||
|
|
||||||
|
ID=[A-Za-z_][A-Za-z0-9_]*
|
||||||
|
|
||||||
|
hex=[0-9a-fA-F]
|
||||||
|
char_escape
|
||||||
|
= "\\x" {hex} {hex}
|
||||||
|
| "\\u{" {hex}+ "}"
|
||||||
|
| "\\" [nr\\t'\"]
|
||||||
|
|
||||||
|
string_char
|
||||||
|
= {char_escape}
|
||||||
|
| [^\\\"\n]
|
||||||
|
|
||||||
|
LINE_STRING=("\\\\" [^\n]* [ \n]*)+
|
||||||
|
|
||||||
|
%state STRING_LITERAL
|
||||||
|
%state ID_STRING
|
||||||
|
%state UNCLOSED_STRING
|
||||||
|
%%
|
||||||
|
|
||||||
|
|
||||||
|
<YYINITIAL> {WHITE_SPACE} { return WHITE_SPACE; }
|
||||||
|
<YYINITIAL> "." { return DOT; }
|
||||||
|
<YYINITIAL> "IntellijIdeaRulezzz" { return INTELLIJ_COMPLETION_DUMMY; }
|
||||||
|
<YYINITIAL> "{" { return LBRACE; }
|
||||||
|
<YYINITIAL> "}" { return RBRACE; }
|
||||||
|
<YYINITIAL> "=" { return EQ; }
|
||||||
|
<YYINITIAL> "," { return COMMA; }
|
||||||
|
<YYINITIAL> "true" { return BOOL_TRUE; }
|
||||||
|
<YYINITIAL> "false" { return BOOL_FALSE; }
|
||||||
|
<YYINITIAL> {COMMENT} { return COMMENT; }
|
||||||
|
<YYINITIAL> {LINE_COMMENT} { return COMMENT; }
|
||||||
|
|
||||||
|
<YYINITIAL> {ID} { return ID; }
|
||||||
|
<YYINITIAL> "@\"" { yybegin(ID_STRING); }
|
||||||
|
<ID_STRING> {string_char}*"\"" { yybegin(YYINITIAL); return ID; }
|
||||||
|
<ID_STRING> [^] { yypushback(1); yybegin(UNCLOSED_STRING); }
|
||||||
|
|
||||||
|
<YYINITIAL> "\"" { yybegin(STRING_LITERAL); }
|
||||||
|
<STRING_LITERAL> {string_char}*"\"" { yybegin(YYINITIAL); return STRING_LITERAL_SINGLE; }
|
||||||
|
<STRING_LITERAL> [^] { yypushback(1); yybegin(UNCLOSED_STRING); }
|
||||||
|
|
||||||
|
<UNCLOSED_STRING>[^\n]*{CRLF} { yybegin(YYINITIAL); return BAD_STRING; }
|
||||||
|
|
||||||
|
<YYINITIAL> {LINE_STRING} { return LINE_STRING; }
|
||||||
|
|
||||||
|
[^] { return BAD_CHARACTER; }
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.falsepattern.zigbrains.zon
|
||||||
|
|
||||||
|
import com.intellij.openapi.util.IconLoader
|
||||||
|
|
||||||
|
object Icons {
|
||||||
|
val ZON = IconLoader.getIcon("/icons/zon.svg", Icons::class.java)
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.falsepattern.zigbrains.zon
|
||||||
|
|
||||||
|
import com.intellij.openapi.fileTypes.LanguageFileType
|
||||||
|
|
||||||
|
object ZonFileType: LanguageFileType(ZonLanguage) {
|
||||||
|
override fun getName() = "Zon File"
|
||||||
|
|
||||||
|
override fun getDescription() = "Zig object notation file"
|
||||||
|
|
||||||
|
override fun getDefaultExtension() = "zon"
|
||||||
|
|
||||||
|
override fun getIcon() = Icons.ZON
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.falsepattern.zigbrains.zon
|
||||||
|
|
||||||
|
import com.intellij.lang.Language
|
||||||
|
|
||||||
|
object ZonLanguage: Language("Zon") {
|
||||||
|
private fun readResolve(): Any = ZonLanguage
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.comments
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.intellij.codeInsight.generation.IndentedCommenter
|
||||||
|
import com.intellij.lang.CodeDocumentationAwareCommenter
|
||||||
|
import com.intellij.psi.PsiComment
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZonCommenter: CodeDocumentationAwareCommenter, IndentedCommenter {
|
||||||
|
override fun getLineCommentPrefix() = "// "
|
||||||
|
|
||||||
|
override fun getBlockCommentPrefix() = null
|
||||||
|
|
||||||
|
override fun getBlockCommentSuffix() = null
|
||||||
|
|
||||||
|
override fun getCommentedBlockCommentPrefix() = null
|
||||||
|
|
||||||
|
override fun getCommentedBlockCommentSuffix() = null
|
||||||
|
|
||||||
|
override fun forceIndentedLineComment() = true
|
||||||
|
|
||||||
|
override fun getLineCommentTokenType(): IElementType = ZonTypes.COMMENT
|
||||||
|
|
||||||
|
override fun getBlockCommentTokenType() = null
|
||||||
|
|
||||||
|
override fun getDocumentationCommentTokenType() = null
|
||||||
|
|
||||||
|
override fun getDocumentationCommentPrefix() = null
|
||||||
|
|
||||||
|
override fun getDocumentationCommentLinePrefix() = null
|
||||||
|
|
||||||
|
override fun getDocumentationCommentSuffix() = null
|
||||||
|
|
||||||
|
override fun isDocumentationComment(element: PsiComment?) = false
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.completion
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonEntry
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonFile
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonProperty
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonPropertyPlaceholder
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonValuePlaceholder
|
||||||
|
import com.intellij.codeInsight.completion.*
|
||||||
|
import com.intellij.codeInsight.lookup.LookupElementBuilder
|
||||||
|
import com.intellij.patterns.ElementPattern
|
||||||
|
import com.intellij.patterns.PlatformPatterns.psiElement
|
||||||
|
import com.intellij.patterns.PsiElementPattern
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.parentOfType
|
||||||
|
import com.intellij.util.ProcessingContext
|
||||||
|
|
||||||
|
class ZonCompletionContributor : CompletionContributor() {
|
||||||
|
init {
|
||||||
|
extend(
|
||||||
|
CompletionType.BASIC,
|
||||||
|
psiElement()
|
||||||
|
.withParent(psiElement(ZonTypes.PROPERTY_PLACEHOLDER))
|
||||||
|
.withSuperParent(4, psiOfType<ZonFile>())
|
||||||
|
) { parameters, _, result ->
|
||||||
|
val placeholder = parameters.position.parentOfType<ZonPropertyPlaceholder>() ?: return@extend
|
||||||
|
val zonEntry = placeholder.parentOfType<ZonEntry>() ?: return@extend
|
||||||
|
val keys = zonEntry.keys
|
||||||
|
doAddCompletions(placeholder.text.startsWith('.'), keys, ZON_ROOT_KEYS, result)
|
||||||
|
}
|
||||||
|
extend(
|
||||||
|
CompletionType.BASIC,
|
||||||
|
psiElement()
|
||||||
|
.withParent(psiElement(ZonTypes.VALUE_PLACEHOLDER))
|
||||||
|
.withSuperParent(2, psiElement(ZonTypes.LIST))
|
||||||
|
.withSuperParent(4, psiOfType<ZonFile>())
|
||||||
|
) { _, _, result ->
|
||||||
|
doAddCompletions(false, emptySet(), ZON_ROOT_KEYS, result)
|
||||||
|
}
|
||||||
|
extend(
|
||||||
|
CompletionType.BASIC,
|
||||||
|
psiElement()
|
||||||
|
.withParent(psiElement(ZonTypes.PROPERTY_PLACEHOLDER))
|
||||||
|
.withSuperParent(4, psiElement(ZonTypes.PROPERTY))
|
||||||
|
.withSuperParent(7, psiElement(ZonTypes.PROPERTY))
|
||||||
|
.withSuperParent(10, psiOfType<ZonFile>())
|
||||||
|
) { parameters, _, result ->
|
||||||
|
val placeholder = parameters.position.parentOfType<ZonValuePlaceholder>() ?: return@extend
|
||||||
|
val depEntry = placeholder.parentOfType<ZonProperty>() ?: return@extend
|
||||||
|
if (depEntry.isDependency) {
|
||||||
|
doAddCompletions(false, emptySet(), ZON_DEP_KEYS, result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extend(
|
||||||
|
CompletionType.BASIC,
|
||||||
|
psiElement()
|
||||||
|
.withParent(psiElement(ZonTypes.VALUE_PLACEHOLDER))
|
||||||
|
.withSuperParent(5, psiElement(ZonTypes.PROPERTY))
|
||||||
|
.withSuperParent(8, psiElement(ZonTypes.PROPERTY))
|
||||||
|
.withSuperParent(11, psiOfType<ZonFile>())
|
||||||
|
) { parameters, _, result ->
|
||||||
|
val placeholder = parameters.position.parentOfType<ZonValuePlaceholder>() ?: return@extend
|
||||||
|
val valueProperty = placeholder.parentOfType<ZonProperty>() ?: return@extend
|
||||||
|
if (valueProperty.isDependency && valueProperty.identifier.value == "lazy") {
|
||||||
|
result.addElement(LookupElementBuilder.create("true"))
|
||||||
|
result.addElement(LookupElementBuilder.create("false"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun extend(type: CompletionType, place: ElementPattern<PsiElement>, crossinline action: Processor) {
|
||||||
|
extend(type, place, object : CompletionProvider<CompletionParameters>() {
|
||||||
|
override fun addCompletions(
|
||||||
|
parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet
|
||||||
|
) = action(parameters, context, result)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private typealias Processor = (
|
||||||
|
parameters: CompletionParameters, context: ProcessingContext, result: CompletionResultSet
|
||||||
|
) -> Unit
|
||||||
|
|
||||||
|
private val ZON_ROOT_KEYS: List<String> =
|
||||||
|
listOf("name", "version", "minimum_zig_version", "dependencies", "paths")
|
||||||
|
private val ZON_DEP_KEYS: List<String> = listOf("url", "hash", "path", "lazy")
|
||||||
|
|
||||||
|
private fun doAddCompletions(
|
||||||
|
hasDot: Boolean, current: Set<String>, expected: List<String>, result: CompletionResultSet
|
||||||
|
) {
|
||||||
|
for (key in expected) {
|
||||||
|
if (current.contains(key)) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
result.addElement(LookupElementBuilder.create(if (hasDot) key else ".$key"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ZonProperty.isDependency: Boolean
|
||||||
|
get() {
|
||||||
|
return parentOfType<ZonEntry>()?.isDependency ?: false
|
||||||
|
}
|
||||||
|
|
||||||
|
private val ZonEntry.isDependency: Boolean
|
||||||
|
get() {
|
||||||
|
val parentProperty = parentOfType<ZonProperty>()?.parentOfType<ZonProperty>() ?: return false
|
||||||
|
return parentProperty.identifier.value == "dependencies"
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <reified T : PsiElement> psiOfType(): PsiElementPattern.Capture<T> =
|
||||||
|
psiElement(T::class.java)
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.folding
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonStruct
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonVisitor
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.lang.folding.CustomFoldingBuilder
|
||||||
|
import com.intellij.lang.folding.FoldingDescriptor
|
||||||
|
import com.intellij.openapi.editor.Document
|
||||||
|
import com.intellij.openapi.project.DumbAware
|
||||||
|
import com.intellij.openapi.util.TextRange
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
|
||||||
|
class ZonFoldingBuilder: CustomFoldingBuilder(), DumbAware {
|
||||||
|
override fun buildLanguageFoldRegions(
|
||||||
|
descriptors: MutableList<FoldingDescriptor>,
|
||||||
|
root: PsiElement,
|
||||||
|
document: Document,
|
||||||
|
quick: Boolean
|
||||||
|
) {
|
||||||
|
root.accept(object: ZonVisitor() {
|
||||||
|
override fun visitElement(element: PsiElement) {
|
||||||
|
super.visitElement(element)
|
||||||
|
element.acceptChildren(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitStruct(o: ZonStruct) {
|
||||||
|
super.visitStruct(o)
|
||||||
|
descriptors.add(FoldingDescriptor(o, o.textRange))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getLanguagePlaceholderText(node: ASTNode, range: TextRange) = ".{...}"
|
||||||
|
|
||||||
|
override fun isRegionCollapsedByDefault(node: ASTNode) = false
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.formatter
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.intellij.formatting.*
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.psi.TokenType
|
||||||
|
import com.intellij.psi.formatter.common.AbstractBlock
|
||||||
|
|
||||||
|
class ZonBlock(
|
||||||
|
node: ASTNode,
|
||||||
|
wrap: Wrap?,
|
||||||
|
alignment: Alignment?,
|
||||||
|
private val spacingBuilder: SpacingBuilder
|
||||||
|
) : AbstractBlock(node, wrap, alignment) {
|
||||||
|
|
||||||
|
override fun buildChildren(): MutableList<Block> {
|
||||||
|
val blocks = ArrayList<Block>()
|
||||||
|
var child = myNode.firstChildNode
|
||||||
|
while (child != null) {
|
||||||
|
if (child.elementType != TokenType.WHITE_SPACE) {
|
||||||
|
blocks.add(ZonBlock(child, null, null, spacingBuilder))
|
||||||
|
}
|
||||||
|
child = child.treeNext
|
||||||
|
}
|
||||||
|
return blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getIndent(): Indent {
|
||||||
|
val parent = myNode.treeParent ?: return Indent.getNoneIndent()
|
||||||
|
val elementType = myNode.elementType
|
||||||
|
return if (parent.elementType == ZonTypes.ENTRY &&
|
||||||
|
elementType != ZonTypes.DOT &&
|
||||||
|
elementType != ZonTypes.LBRACE &&
|
||||||
|
elementType != ZonTypes.RBRACE
|
||||||
|
) {
|
||||||
|
Indent.getNormalIndent()
|
||||||
|
} else {
|
||||||
|
Indent.getNoneIndent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getSpacing(child1: Block?, child2: Block) = null
|
||||||
|
|
||||||
|
override fun isLeaf(): Boolean = myNode.firstChildNode == null
|
||||||
|
|
||||||
|
override fun getChildIndent(): Indent {
|
||||||
|
return if (myNode.elementType == ZonTypes.ENTRY) {
|
||||||
|
Indent.getNormalIndent()
|
||||||
|
} else {
|
||||||
|
Indent.getNoneIndent()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.formatter
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.ZonLanguage
|
||||||
|
import com.intellij.formatting.FormattingContext
|
||||||
|
import com.intellij.formatting.FormattingModel
|
||||||
|
import com.intellij.formatting.FormattingModelBuilder
|
||||||
|
import com.intellij.formatting.FormattingModelProvider
|
||||||
|
import com.intellij.formatting.SpacingBuilder
|
||||||
|
|
||||||
|
class ZonFormattingModelBuilder : FormattingModelBuilder {
|
||||||
|
override fun createModel(context: FormattingContext): FormattingModel {
|
||||||
|
val settings = context.codeStyleSettings
|
||||||
|
return FormattingModelProvider.createFormattingModelForPsiFile(
|
||||||
|
context.containingFile,
|
||||||
|
ZonBlock(context.node, null, null, SpacingBuilder(settings, ZonLanguage)),
|
||||||
|
settings
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.highlighting
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.Icons
|
||||||
|
import com.intellij.openapi.options.colors.AttributesDescriptor
|
||||||
|
import com.intellij.openapi.options.colors.ColorDescriptor
|
||||||
|
import com.intellij.openapi.options.colors.ColorSettingsPage
|
||||||
|
|
||||||
|
class ZonColorSettingsPage: ColorSettingsPage {
|
||||||
|
override fun getAttributeDescriptors() = DESCRIPTORS
|
||||||
|
|
||||||
|
override fun getColorDescriptors(): Array<ColorDescriptor> = ColorDescriptor.EMPTY_ARRAY
|
||||||
|
|
||||||
|
override fun getDisplayName() = "Zon"
|
||||||
|
|
||||||
|
override fun getIcon() = Icons.ZON
|
||||||
|
|
||||||
|
override fun getHighlighter() = ZonSyntaxHighlighter()
|
||||||
|
|
||||||
|
override fun getDemoText() = """
|
||||||
|
.{
|
||||||
|
//This is an example file with some random data
|
||||||
|
.name = "zls",
|
||||||
|
.version = "0.11.0",
|
||||||
|
|
||||||
|
.dependencies = .{
|
||||||
|
.known_folders = .{
|
||||||
|
.url = "https://github.com/ziglibs/known-folders/archive/fa75e1bc672952efa0cf06160bbd942b47f6d59b.tar.gz",
|
||||||
|
.hash = "122048992ca58a78318b6eba4f65c692564be5af3b30fbef50cd4abeda981b2e7fa5",
|
||||||
|
.lazy = true,
|
||||||
|
},
|
||||||
|
.diffz = .{
|
||||||
|
.url = "https://github.com/ziglibs/diffz/archive/90353d401c59e2ca5ed0abe5444c29ad3d7489aa.tar.gz",
|
||||||
|
.hash = "122089a8247a693cad53beb161bde6c30f71376cd4298798d45b32740c3581405864",
|
||||||
|
},
|
||||||
|
.binned_allocator = .{
|
||||||
|
.url = "https://gist.github.com/antlilja/8372900fcc09e38d7b0b6bbaddad3904/archive/6c3321e0969ff2463f8335da5601986cf2108690.tar.gz",
|
||||||
|
.hash = "1220363c7e27b2d3f39de6ff6e90f9537a0634199860fea237a55ddb1e1717f5d6a5",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
.paths = .{""},
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
override fun getAdditionalHighlightingTagToDescriptorMap() = null
|
||||||
|
}
|
||||||
|
|
||||||
|
val DESCRIPTORS = arrayOf(
|
||||||
|
AttributesDescriptor("Equals", ZonSyntaxHighlighter.EQ),
|
||||||
|
AttributesDescriptor("Identifier", ZonSyntaxHighlighter.ID),
|
||||||
|
AttributesDescriptor("Comment", ZonSyntaxHighlighter.COMMENT),
|
||||||
|
AttributesDescriptor("Bad value", ZonSyntaxHighlighter.BAD_CHAR),
|
||||||
|
AttributesDescriptor("String", ZonSyntaxHighlighter.STRING),
|
||||||
|
AttributesDescriptor("Comma", ZonSyntaxHighlighter.COMMA),
|
||||||
|
AttributesDescriptor("Dot", ZonSyntaxHighlighter.DOT),
|
||||||
|
AttributesDescriptor("Boolean", ZonSyntaxHighlighter.BOOLEAN),
|
||||||
|
AttributesDescriptor("Braces", ZonSyntaxHighlighter.BRACE)
|
||||||
|
)
|
|
@ -0,0 +1,53 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.highlighting
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.lexer.ZonLexerAdapter
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.intellij.openapi.editor.HighlighterColors
|
||||||
|
import com.intellij.openapi.editor.colors.TextAttributesKey
|
||||||
|
import com.intellij.openapi.fileTypes.SyntaxHighlighterBase
|
||||||
|
import com.intellij.psi.TokenType
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
import com.intellij.openapi.editor.DefaultLanguageHighlighterColors as DefaultColors
|
||||||
|
|
||||||
|
class ZonSyntaxHighlighter : SyntaxHighlighterBase() {
|
||||||
|
override fun getHighlightingLexer() = ZonLexerAdapter()
|
||||||
|
|
||||||
|
override fun getTokenHighlights(tokenType: IElementType?) = KEYMAP.getOrDefault(tokenType, EMPTY_KEYS)
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
// @formatter:off
|
||||||
|
val EQ = createKey("EQ" , DefaultColors.OPERATION_SIGN )
|
||||||
|
val ID = createKey("ID" , DefaultColors.INSTANCE_FIELD )
|
||||||
|
val COMMENT = createKey("COMMENT" , DefaultColors.LINE_COMMENT )
|
||||||
|
val BAD_CHAR = createKey("BAD_CHARACTER", HighlighterColors.BAD_CHARACTER)
|
||||||
|
val STRING = createKey("STRING" , DefaultColors.STRING )
|
||||||
|
val COMMA = createKey("COMMA" , DefaultColors.COMMA )
|
||||||
|
val BOOLEAN = createKey("BOOLEAN" , DefaultColors.KEYWORD )
|
||||||
|
val DOT = createKey("DOT" , DefaultColors.DOT )
|
||||||
|
val BRACE = createKey("BRACE" , DefaultColors.BRACES )
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
|
private val EMPTY_KEYS = emptyArray<TextAttributesKey>()
|
||||||
|
private val KEYMAP = HashMap<IElementType, Array<TextAttributesKey>>()
|
||||||
|
|
||||||
|
private fun createKey(name: String, fallback: TextAttributesKey) =
|
||||||
|
TextAttributesKey.createTextAttributesKey("ZON_$name", fallback)
|
||||||
|
|
||||||
|
private fun addMapping(key: TextAttributesKey, vararg types: IElementType) = types.forEach { KEYMAP[it] = arrayOf(key) }
|
||||||
|
|
||||||
|
init {
|
||||||
|
// @formatter:off
|
||||||
|
addMapping(DOT , ZonTypes.DOT)
|
||||||
|
addMapping(COMMA , ZonTypes.COMMA)
|
||||||
|
addMapping(BRACE , ZonTypes.LBRACE)
|
||||||
|
addMapping(BRACE , ZonTypes.RBRACE)
|
||||||
|
addMapping(STRING , ZonTypes.LINE_STRING, ZonTypes.STRING_LITERAL_SINGLE)
|
||||||
|
addMapping(BAD_CHAR, TokenType.BAD_CHARACTER)
|
||||||
|
addMapping(COMMENT , ZonTypes.COMMENT)
|
||||||
|
addMapping(ID , ZonTypes.ID)
|
||||||
|
addMapping(EQ , ZonTypes.EQ)
|
||||||
|
addMapping(BOOLEAN , ZonTypes.BOOL_FALSE, ZonTypes.BOOL_TRUE)
|
||||||
|
// @formatter:on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.highlighting
|
||||||
|
|
||||||
|
import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
|
||||||
|
class ZonSyntaxHighlighterFactory: SyntaxHighlighterFactory() {
|
||||||
|
override fun getSyntaxHighlighter(project: Project?, virtualFile: VirtualFile?) = ZonSyntaxHighlighter()
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.lexer
|
||||||
|
|
||||||
|
import com.intellij.lexer.FlexAdapter
|
||||||
|
|
||||||
|
class ZonLexerAdapter: FlexAdapter(ZonFlexLexer(null))
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.pairing
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.intellij.lang.BracePair
|
||||||
|
import com.intellij.lang.PairedBraceMatcher
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZonBraceMatcher : PairedBraceMatcher {
|
||||||
|
override fun getPairs() =
|
||||||
|
PAIRS
|
||||||
|
|
||||||
|
override fun isPairedBracesAllowedBeforeType(lbraceType: IElementType, contextType: IElementType?) =
|
||||||
|
true
|
||||||
|
|
||||||
|
override fun getCodeConstructStart(file: PsiFile?, openingBraceOffset: Int) =
|
||||||
|
file?.findElementAt(openingBraceOffset)?.parent?.textOffset ?: openingBraceOffset
|
||||||
|
}
|
||||||
|
|
||||||
|
private val PAIR = BracePair(ZonTypes.LBRACE, ZonTypes.RBRACE, true)
|
||||||
|
private val PAIRS = arrayOf(PAIR)
|
|
@ -0,0 +1,11 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.pairing
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.intellij.codeInsight.editorActions.MultiCharQuoteHandler
|
||||||
|
import com.intellij.codeInsight.editorActions.SimpleTokenSetQuoteHandler
|
||||||
|
import com.intellij.openapi.editor.highlighter.HighlighterIterator
|
||||||
|
|
||||||
|
class ZonQuoteHandler: SimpleTokenSetQuoteHandler(ZonTypes.STRING_LITERAL, ZonTypes.BAD_STRING), MultiCharQuoteHandler {
|
||||||
|
override fun getClosingQuote(iterator: HighlighterIterator, offset: Int) =
|
||||||
|
"\""
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.parser
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.ZonLanguage
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZonElementType(debugName: String): IElementType(debugName, ZonLanguage)
|
|
@ -0,0 +1,29 @@
|
||||||
|
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.ZonFile
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
import com.intellij.lang.ParserDefinition
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import com.intellij.psi.FileViewProvider
|
||||||
|
import com.intellij.psi.tree.IFileElementType
|
||||||
|
|
||||||
|
class ZonParserDefinition: ParserDefinition {
|
||||||
|
override fun createLexer(project: Project?) = ZonLexerAdapter()
|
||||||
|
|
||||||
|
override fun createParser(project: Project?) = ZonParser()
|
||||||
|
|
||||||
|
override fun getFileNodeType() = FILE
|
||||||
|
|
||||||
|
override fun getCommentTokens() = ZonTokenSets.COMMENTS
|
||||||
|
|
||||||
|
override fun getStringLiteralElements() = ZonTokenSets.STRINGS
|
||||||
|
|
||||||
|
override fun createElement(node: ASTNode?) = ZonTypes.Factory.createElement(node)!!
|
||||||
|
|
||||||
|
override fun createFile(viewProvider: FileViewProvider) = ZonFile(viewProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
val FILE = IFileElementType(ZonLanguage)
|
|
@ -0,0 +1,9 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.parser
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonTypes
|
||||||
|
import com.intellij.psi.tree.TokenSet
|
||||||
|
|
||||||
|
object ZonTokenSets {
|
||||||
|
val COMMENTS = TokenSet.create(ZonTypes.COMMENT)
|
||||||
|
val STRINGS = TokenSet.create(ZonTypes.LINE_STRING, ZonTypes.STRING_LITERAL_SINGLE)
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.parser
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.ZonLanguage
|
||||||
|
import com.intellij.psi.tree.IElementType
|
||||||
|
|
||||||
|
class ZonTokenType(debugName: String): IElementType(debugName, ZonLanguage)
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.psi
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.ZonFileType
|
||||||
|
import com.falsepattern.zigbrains.zon.ZonLanguage
|
||||||
|
import com.intellij.extapi.psi.PsiFileBase
|
||||||
|
import com.intellij.psi.FileViewProvider
|
||||||
|
|
||||||
|
class ZonFile(viewProvider: FileViewProvider): PsiFileBase(viewProvider, ZonLanguage) {
|
||||||
|
override fun getFileType() = ZonFileType
|
||||||
|
|
||||||
|
override fun toString() = "Zon File"
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.psi.impl.mixins
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonEntry
|
||||||
|
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
|
||||||
|
abstract class ZonEntryMixinImpl(node: ASTNode): ASTWrapperPsiElement(node), ZonEntry {
|
||||||
|
override val keys: Set<String> get() {
|
||||||
|
val struct = this.struct ?: return emptySet()
|
||||||
|
return struct.propertyList.map { it.identifier.value }.toSet()
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.psi.impl.mixins
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.zon.psi.ZonIdentifier
|
||||||
|
import com.intellij.extapi.psi.ASTWrapperPsiElement
|
||||||
|
import com.intellij.lang.ASTNode
|
||||||
|
|
||||||
|
abstract class ZonIdentifierMixinImpl(node: ASTNode): ASTWrapperPsiElement(node), ZonIdentifier {
|
||||||
|
override val value: String get() {
|
||||||
|
val text = this.text!!
|
||||||
|
return if (text.startsWith('@'))
|
||||||
|
text.substring(2, text.length - 1)
|
||||||
|
else
|
||||||
|
text
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.psi.mixins
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
|
||||||
|
interface ZonEntryMixin: PsiElement {
|
||||||
|
val keys: Set<String>
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.falsepattern.zigbrains.zon.psi.mixins
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
|
||||||
|
interface ZonIdentifierMixin: PsiElement {
|
||||||
|
val value: String
|
||||||
|
}
|
21
modules/zon/src/main/resources/icons/zon.svg
Normal file
21
modules/zon/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 |
|
@ -3,5 +3,7 @@ plugins {
|
||||||
}
|
}
|
||||||
rootProject.name = "ZigBrains"
|
rootProject.name = "ZigBrains"
|
||||||
|
|
||||||
include("core")
|
include("zig")
|
||||||
project(":core").projectDir = file("modules/core")
|
project(":zig").projectDir = file("modules/zig")
|
||||||
|
include("zon")
|
||||||
|
project(":zon").projectDir = file("modules/zon")
|
|
@ -5,11 +5,54 @@
|
||||||
|
|
||||||
<depends>com.intellij.modules.platform</depends>
|
<depends>com.intellij.modules.platform</depends>
|
||||||
|
|
||||||
|
<!-- region Zig -->
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
<fileType name="Zig File"
|
<fileType
|
||||||
|
name="Zig File"
|
||||||
implementationClass="com.falsepattern.zigbrains.zig.ZigFileType"
|
implementationClass="com.falsepattern.zigbrains.zig.ZigFileType"
|
||||||
fieldName="INSTANCE"
|
fieldName="INSTANCE"
|
||||||
language="Zig"
|
language="Zig"
|
||||||
extensions="zig"/>
|
extensions="zig"/>
|
||||||
|
<lang.parserDefinition
|
||||||
|
language="Zig"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zig.parser.ZigParserDefinition"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
|
<!-- endregion Zig -->
|
||||||
|
|
||||||
|
<!-- region Zon -->
|
||||||
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<colorSettingsPage
|
||||||
|
implementation="com.falsepattern.zigbrains.zon.highlighting.ZonColorSettingsPage"/>
|
||||||
|
<completion.contributor
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.completion.ZonCompletionContributor"/>
|
||||||
|
<fileType
|
||||||
|
name="Zon File"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.ZonFileType"
|
||||||
|
fieldName="INSTANCE"
|
||||||
|
language="Zon"
|
||||||
|
extensions="zon"/>
|
||||||
|
<lang.braceMatcher
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.pairing.ZonBraceMatcher"/>
|
||||||
|
<lang.commenter
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.comments.ZonCommenter"/>
|
||||||
|
<lang.foldingBuilder
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.folding.ZonFoldingBuilder"/>
|
||||||
|
<lang.formatter
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.formatter.ZonFormattingModelBuilder"/>
|
||||||
|
<lang.parserDefinition
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.parser.ZonParserDefinition"/>
|
||||||
|
<lang.quoteHandler
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.pairing.ZonQuoteHandler"/>
|
||||||
|
<lang.syntaxHighlighterFactory
|
||||||
|
language="Zon"
|
||||||
|
implementationClass="com.falsepattern.zigbrains.zon.highlighting.ZonSyntaxHighlighterFactory"/>
|
||||||
|
</extensions>
|
||||||
|
<!-- endregion Zon -->
|
||||||
</idea-plugin>
|
</idea-plugin>
|
Loading…
Add table
Reference in a new issue