commonMain.agl.grammar.scopes.AglScopesGrammar.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of agl-processor-jvm8 Show documentation
Show all versions of agl-processor-jvm8 Show documentation
Dynamic, scan-on-demand, parsing; when a regular expression is just not enough
The newest version!
/**
* Copyright (C) 2021 Dr. David H. Akehurst (http://dr.david.h.akehurst.net)
*
* 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 net.akehurst.language.agl.grammar.scopes
import net.akehurst.language.agl.grammar.grammar.asm.GrammarAbstract
import net.akehurst.language.agl.grammar.grammar.asm.GrammarBuilderDefault
import net.akehurst.language.agl.grammar.grammar.asm.GrammarOptionDefault
import net.akehurst.language.agl.grammar.grammar.asm.NamespaceDefault
import net.akehurst.language.api.grammar.GrammarRule
/**
*/
internal object AglScopesGrammar : GrammarAbstract(NamespaceDefault("net.akehurst.language.agl"), "AglScopes") {
//companion object {
const val goalRuleName = "declarations"
private fun createRules(): List {
val b: GrammarBuilderDefault = GrammarBuilderDefault(NamespaceDefault("net.akehurst.language.agl"), "AglStyle");
b.skip("WHITESPACE", true).concatenation(b.terminalPattern("\\s+"));
b.skip("MULTI_LINE_COMMENT", true).concatenation(b.terminalPattern("/\\*[^*]*\\*+([^*/][^*]*\\*+)*/"));
b.skip("SINGLE_LINE_COMMENT", true).concatenation(b.terminalPattern("//[^\\n\\r]*"));
b.rule("declarations").concatenation(b.nonTerminal("rootIdentifiables"), b.nonTerminal("scopes"), b.nonTerminal("referencesOpt"))
b.rule("rootIdentifiables").multi(0, -1, b.nonTerminal("identifiable"))
b.rule("scopes").multi(0, -1, b.nonTerminal("scope"))
b.rule("scope").concatenation(b.terminalLiteral("scope"), b.nonTerminal("typeReference"), b.terminalLiteral("{"), b.nonTerminal("identifiables"), b.terminalLiteral("}"))
b.rule("identifiables").multi(0, -1, b.nonTerminal("identifiable"))
b.rule("identifiable").concatenation(b.terminalLiteral("identify"), b.nonTerminal("typeReference"), b.terminalLiteral("by"), b.nonTerminal("propertyReferenceOrNothing"))
b.rule("referencesOpt").optional(b.nonTerminal("references"))
b.rule("references").concatenation(b.terminalLiteral("references"), b.terminalLiteral("{"), b.nonTerminal("referenceDefinitions"), b.terminalLiteral("}"))
b.rule("referenceDefinitions").multi(0, -1, b.nonTerminal("referenceDefinition"))
b.rule("referenceDefinition").concatenation(
b.terminalLiteral("in"),
b.nonTerminal("typeReference"),
b.terminalLiteral("property"),
b.nonTerminal("propertyReference"),
b.terminalLiteral("refers-to"),
b.nonTerminal("typeReferences")
)
b.rule("typeReferences").separatedList(1, -1, b.terminalLiteral("|"), b.nonTerminal("typeReference"))
b.rule("typeReference").concatenation(b.nonTerminal("IDENTIFIER"))
b.rule("propertyReferenceOrNothing").choiceLongestFromConcatenationItem(b.terminalLiteral("§nothing"), b.nonTerminal("propertyReference"))
b.rule("propertyReference").concatenation(b.nonTerminal("IDENTIFIER"))
b.leaf("IDENTIFIER").concatenation(b.terminalPattern("[a-zA-Z_][a-zA-Z_0-9-]*"));
return b.grammar.grammarRule
}
override val options = listOf(GrammarOptionDefault("defaultGoal", "declarations"))
override val defaultRule: GrammarRule get() = this.findAllResolvedGrammarRule("declarations")!!
const val grammarStr = """
namespace net.akehurst.language.agl
grammar AglScopes {
skip WHITESPACE = "\s+" ;
skip MULTI_LINE_COMMENT = "/\*[^*]*\*+(?:[^*`/`][^*]*\*+)*`/`" ;
skip SINGLE_LINE_COMMENT = "//[\n\r]*?" ;
declarations = rootIdentifiables scopes references? ;
rootIdentifiables = identifiable* ;
scopes = scope* ;
scope = 'scope' typeReference '{' identifiables '}' ;
identifiables = identifiable* ;
identifiable = 'identify' typeReference 'by' propertyReferenceOrNothing ;
references = 'references' '{' referenceDefinitions '}' ;
referenceDefinitions = referenceDefinition* ;
referenceDefinition = 'in' typeReference '{' referenceExpression* '}' ;
referenceExpression = propertyReferenceExpression | collectionReferenceExpression ;
propertyReferenceExpression = 'property' propertyReference 'refers-to' typeReferences from ;
collectionReferenceExpression = 'forall' navigation '{' referenceExpression '}' ;
from = 'from' navigation ;
navigation = [propertyReference / '.']+ ;
typeReferences = [typeReference / '|']+ ;
propertyReferenceOrNothing = '§nothing' | propertyReference ;
typeReference = IDENTIFIER ; // same as grammar rule name
propertyReference = IDENTIFIER ; // same as grammar rule name
leaf IDENTIFIER = "[a-zA-Z_][a-zA-Z_0-9-]*" ;
}
"""
const val styleStr = """'scope' {
foreground: darkgreen;
font-style: bold;
}
'identify' {
foreground: darkgreen;
font-style: bold;
}
'by' {
foreground: darkgreen;
font-style: bold;
}
'references' {
foreground: darkgreen;
font-style: bold;
}
'in' {
foreground: darkgreen;
font-style: bold;
}
'property' {
foreground: darkgreen;
font-style: bold;
}
'refers-to' {
foreground: darkgreen;
font-style: bold;
}
'|' {
foreground: darkgreen;
font-style: bold;
}"""
const val formatterStr = """
@TODO
References -> when {
referenceDefinitions.isEmpty -> "references { }"
else -> "
references {
referenceDefinitions
}
"
}
ReferenceDefinitions -> [referenceDefinition / '\n']
ReferenceDefinition -> "in §typeReference property §propertyReference refers-to §typeReferences"
"""
init {
super.grammarRule.addAll(createRules())
}
//TODO: gen this from the ASM
override fun toString(): String = grammarStr.trimIndent()
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy