修改bnf

This commit is contained in:
me
2024-05-26 15:15:34 +08:00
parent 9603c24461
commit 16c1008c2c
7 changed files with 141 additions and 18 deletions

View File

@@ -151,6 +151,7 @@ InheritDeclaration ::= InheritsKeyword ReferenceIdentifier {
}
ComponentBody ::= '{' ComponentElement* '}'{
pin=1
recoverWhile=recoverWhileForComponentBody
}
//组件元素定义
private ComponentElement ::=ChildrenPlaceholder| Property | Callback
@@ -160,11 +161,7 @@ private ComponentElement ::=ChildrenPlaceholder| Property | Callback
| RepetitionElement | SubComponent {
recoverWhile(".*")=recoverWhileForComponentBody
}
private recoverWhileForComponentBody::= !(
'property'|'callback'|'changed'
|'states'|'transitions'|'pure'
|'function'|'public'|'protected'|'for'|'if'|'}'|';'|'@'
|GenericIdentifier|PropertyModifier)
private recoverWhileForComponentBody::= !('{'|';'|'}'|'@'|GenericIdentifier)
ChildrenPlaceholder ::= '@' 'children'{
pin=1
@@ -249,7 +246,8 @@ RepetitionIndex ::= '[' LocalVariable ']'{
//--------------------------------SubElementDeclaration Start---------------------------------------------------
//子组件结构元素定义
SubComponent ::= (PropertyName ':=')? ReferenceIdentifier ComponentBody{
pin=2
pin=3
recoverWhile=recoverWhileForComponentBody
}
//--------------------------------TransitionsDeclaration Start---------------------------------------------------
@@ -298,11 +296,11 @@ CodeBlock ::= '{' Statement* '}'{
pin=1
}
private Statement ::= (ReturnStatement|IfElseStatement|ExpressionStatement) ';'?{
recoverWhile=recoverWhileStatement
recoverWhile=recoverWhileForComponentBody
}
ExpressionStatement ::= Expression (';' &Statement)?
private recoverWhileStatement::=!(GenericIdentifier|';'|'}')
//private recoverWhileStatement::=!(GenericIdentifier|';'|'}')
ReturnStatement ::= 'return' (Expression)?{
pin=1
@@ -331,11 +329,14 @@ private QualifiedNamePropertyBinding::= QualifiedPropertyNameReference ':' Bindi
PropertyBinding ::= ReferenceIdentifier ':' BindingStatement{
pin=2
}
private WhileIdentifier::=!('}'|GenericIdentifier)
//优先尝试表达式解析 {}属于代码块 {name:xx}属于表达式那么需要预测后面两个token,第二个token不是':'的情况下才是代码块
//所以优先判断对象创建判断,然后进行代码块判断,最后进行表达式
//代码块分号可选
//表达式需要分号结尾
BindingStatement ::=ObjectCreationExpressionWithSem|(CodeBlock ';'?)| ExpressionWithSem
BindingStatement ::=ObjectCreationExpressionWithSem|(CodeBlock ';'?)| ExpressionWithSem{
recoverWhile=WhileIdentifier
}
//用于错误的直观化
private ObjectCreationExpressionWithSem::=ObjectCreationExpression';'{
pin=1

View File

@@ -0,0 +1,68 @@
{
generate=[token-case="as-is" element-case="as-is"]
parserClass="me.zhouxi.slint.lang.parser.SlintParser"
implements="me.zhouxi.slint.lang.psi.SlintPsiElement"
extends="me.zhouxi.slint.lang.psi.impl.SlintPsiElementImpl"
elementTypeHolderClass="me.zhouxi.slint.lang.psi.SlintTypes"
elementTypeClass="me.zhouxi.slint.lang.SlintElementType"
tokenTypeClass="me.zhouxi.slint.lang.SlintTokenType"
psiClassPrefix="Slint"
psiImplClassSuffix="Impl"
psiPackage="me.zhouxi.slint.lang.psi"
psiImplPackage="me.zhouxi.slint.lang.psi.impl"
tokens=[
Comma = ","
FatArrow = "=>"
DoubleArrow = "<=>"
PlusEqual = "+="
MinusEqual = "-="
StarEqual = "*="
DivEqual = "/="
LessEqual = "<="
GreaterEqual = ">="
EqualEqual = "=="
NotEqual = "!="
ColonEqual = ":="
Arrow = "->"
OrOr = "||"
AndAnd = "&&"
LBrace = "{"
RBrace = "}"
LParent = "("
RParent = ")"
LAngle = "<"
RAngle = ">"
LBracket = "["
RBracket = "]"
Plus = "+"
Minus = "-"
Star = "*"
Div = "/"
Equal = "="
Colon = ":"
Comma = ","
Semicolon = ";"
Bang = "!"
Dot = "."
Question = "?"
Dollar = "$"
At = "@"
Pipe = "|"
Percent = "%"
Whitespace = "regexp:(\s+)"
NumberLiteral = "regexp:\d+(\.(\d+)?)?([a-z]+|%)?"
Identifier = "regexp:^[a-zA-Z_][A-Za-z0-9\-_]*"
ColorLiteral = "regexp:#([a-zA-Z0-9]+)"
StringLiteral = 'regexp:(^"[^"\r\n]*")'
LineComment = 'regexp:^//[^\r\n]*'
BlockComment = 'regexp:/\*[\s\S]*?\*/'
]
}
Document ::= Binding*
Binding ::=Identifier ':' Identifier ';'{
pin=2
recoverWhile=while
}
private while::=!(';'|Identifier)

View File

@@ -3,10 +3,7 @@ package me.zhouxi.slint.completion
import com.intellij.codeInsight.completion.CompletionContributor
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.patterns.PlatformPatterns
import me.zhouxi.slint.completion.provider.BasicTypeProvider
import me.zhouxi.slint.completion.provider.ComponentProvider
import me.zhouxi.slint.completion.provider.ElementKeywordProvider
import me.zhouxi.slint.completion.provider.TopKeywordProvider
import me.zhouxi.slint.completion.provider.*
import me.zhouxi.slint.lang.psi.SlintTypes
import me.zhouxi.slint.lang.psi.stubs.types.SlintFileElementType
@@ -38,6 +35,12 @@ class SlintCompletionContributor : CompletionContributor() {
PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(SlintTypes.ComponentBody)),
ComponentProvider
)
//propertyBinding
extend(
CompletionType.BASIC,
PlatformPatterns.psiElement().withAncestor(2, PlatformPatterns.psiElement(SlintTypes.ComponentBody)),
PropertyBindingProvider
)
}
}

View File

@@ -0,0 +1,34 @@
package me.zhouxi.slint.completion.provider
import com.intellij.codeInsight.completion.CompletionParameters
import com.intellij.codeInsight.completion.CompletionProvider
import com.intellij.codeInsight.completion.CompletionResultSet
import com.intellij.codeInsight.lookup.LookupElementBuilder
import com.intellij.icons.AllIcons
import com.intellij.psi.util.parentOfType
import com.intellij.util.ProcessingContext
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintSubComponent
import me.zhouxi.slint.lang.psi.extension.inheritsProperties
object PropertyBindingProvider : CompletionProvider<CompletionParameters>() {
override fun addCompletions(
parameters: CompletionParameters,
context: ProcessingContext,
result: CompletionResultSet
) {
val element = parameters.position
val subComponent = element.parentOfType<SlintSubComponent>()
if (subComponent != null) {
val component = subComponent.referenceIdentifier.reference?.resolve() as SlintComponent? ?: return
val builders = component.inheritsProperties()
.map { LookupElementBuilder.create(it).withTypeText(component.name).withIcon(AllIcons.Nodes.Property) }
result.addAllElements(builders)
} else {
val component = element.parentOfType<SlintComponent>() ?: return
val builders = component.inheritsProperties()
.map { LookupElementBuilder.create(it).withTypeText(component.name).withIcon(AllIcons.Nodes.Property) }
result.addAllElements(builders)
}
}
}

View File

@@ -0,0 +1,12 @@
package me.zhouxi.slint.lang.psi.extension
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintProperty
fun SlintComponent.inheritsProperties(): List<SlintProperty> {
val properties = this.componentBody?.propertyList ?: emptyList()
val inherit =
this.inheritDeclaration?.referenceIdentifier?.reference?.resolve() as SlintComponent? ?: return properties
return properties + inherit.inheritsProperties()
}

View File

@@ -41,7 +41,7 @@ class SlintReferenceContributor : PsiReferenceContributor() {
psiElement(ComponentBody)
)
),
PropertyReferenceProvider()
PropertyReferenceProvider
)
}
}

View File

@@ -10,18 +10,23 @@ import com.intellij.util.ProcessingContext
import me.zhouxi.slint.lang.psi.SlintComponent
import me.zhouxi.slint.lang.psi.SlintPropertyBinding
import me.zhouxi.slint.lang.psi.SlintSubComponent
import me.zhouxi.slint.lang.psi.extension.inheritsProperties
import me.zhouxi.slint.lang.psi.utils.searchProperty
class PropertyReferenceProvider : PsiReferenceProvider() {
object PropertyReferenceProvider : PsiReferenceProvider() {
override fun getReferencesByElement(element: PsiElement, context: ProcessingContext): Array<PsiReference> {
return arrayOf(PropertyReference(element))
}
class PropertyReference(element: PsiElement) : PsiReferenceBase<PsiElement?>(element) {
override fun resolve(): PsiElement? {
val binding = element.parentOfType<SlintPropertyBinding>() ?: return null
val parent = binding.parentOfTypes(SlintSubComponent::class, SlintComponent::class) ?: return null
return searchProperty(parent) { it.propertyName?.textMatches(element) == true }
val subComponent = element.parentOfType<SlintSubComponent>()
if (subComponent != null) {
val component = subComponent.referenceIdentifier.reference?.resolve() as SlintComponent? ?: return null
return component.inheritsProperties().find { it.propertyName?.textMatches(element) == true }
}
val component = element.parentOfType<SlintComponent>() ?: return null
return component.inheritsProperties().find { it.propertyName?.textMatches(element) == true }
}
}
}