Lexer identifier refactorings and basic lexer/parser error listeners.
This commit is contained in:
parent
e747ac3c32
commit
80b01ec27a
@ -112,11 +112,11 @@ PreambleOpen
|
|||||||
;
|
;
|
||||||
|
|
||||||
ComponentOpen
|
ComponentOpen
|
||||||
: LT -> pushMode(IN_TAG)
|
: LT -> pushMode(TAG_START)
|
||||||
;
|
;
|
||||||
|
|
||||||
ClosingComponentOpen
|
ClosingComponentOpen
|
||||||
: LT FS -> pushMode(IN_TAG)
|
: LT FS -> pushMode(TAG_START)
|
||||||
;
|
;
|
||||||
|
|
||||||
EqualsScriptletOpen
|
EqualsScriptletOpen
|
||||||
@ -159,34 +159,87 @@ RawText
|
|||||||
;
|
;
|
||||||
|
|
||||||
// ----------------------------------------
|
// ----------------------------------------
|
||||||
mode IN_TAG;
|
mode TAG_START;
|
||||||
|
|
||||||
ComponentSelfClose
|
FragmentClose
|
||||||
: FS GT -> popMode
|
: GT -> popMode
|
||||||
;
|
;
|
||||||
|
|
||||||
|
TypedIdentifier
|
||||||
|
: ( PackageIdentifier DOT )* ClassIdentifier ( DOT ClassIdentifier )* -> mode(IN_TAG)
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
PackageIdentifier
|
||||||
|
: PackageIdentifierStartChar PackageIdentifierChar*
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
PackageIdentifierStartChar
|
||||||
|
: [\p{Ll}]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
PackageIdentifierChar
|
||||||
|
: [\p{L}_0-9]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ClassIdentifier
|
||||||
|
: ClassIdentifierStartChar ClassIdentifierChar*
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ClassIdentifierStartChar
|
||||||
|
: [\p{Lu}]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ClassIdentifierChar
|
||||||
|
: [\p{L}_0-9]
|
||||||
|
;
|
||||||
|
|
||||||
|
StringIdentifier
|
||||||
|
: StringIdentifierStartChar StringIdentifierChar* -> mode(IN_TAG)
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
StringIdentifierStartChar
|
||||||
|
: [\p{Ll}]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
StringIdentifierChar
|
||||||
|
: [-_0-9\p{L}]
|
||||||
|
;
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
mode IN_TAG;
|
||||||
|
|
||||||
ComponentClose
|
ComponentClose
|
||||||
: GT -> popMode
|
: GT -> popMode
|
||||||
;
|
;
|
||||||
|
|
||||||
Identifier
|
ComponentSelfClose
|
||||||
: IdentifierStartChar IdentifierChar*
|
: FS GT -> popMode
|
||||||
;
|
|
||||||
|
|
||||||
IdentifierStartChar
|
|
||||||
: ~[.] { isIdentifierStartChar(this.getCurrentChar()) }?
|
|
||||||
;
|
|
||||||
|
|
||||||
IdentifierChar
|
|
||||||
: ~[.] { isIdentifierChar(this.getCurrentChar()) }?
|
|
||||||
;
|
;
|
||||||
|
|
||||||
ConstructorOpen
|
ConstructorOpen
|
||||||
: LP { this.enterConstructor(); }
|
: LP { this.enterConstructor(); }
|
||||||
;
|
;
|
||||||
|
|
||||||
Dot
|
AttributeIdentifier
|
||||||
: DOT
|
: AttributeIdentifierStartChar AttributeIdentifierChar*
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
AttributeIdentifierStartChar
|
||||||
|
: [\p{L}_$]
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
AttributeIdentifierChar
|
||||||
|
: [\p{L}_$0-9]
|
||||||
;
|
;
|
||||||
|
|
||||||
Equals
|
Equals
|
||||||
|
@ -67,7 +67,7 @@ componentArgs
|
|||||||
;
|
;
|
||||||
|
|
||||||
componentType
|
componentType
|
||||||
: Identifier ( Dot Identifier )*
|
: TypedIdentifier | StringIdentifier
|
||||||
;
|
;
|
||||||
|
|
||||||
componentConstructor
|
componentConstructor
|
||||||
@ -79,11 +79,11 @@ attr
|
|||||||
;
|
;
|
||||||
|
|
||||||
keyValueAttr
|
keyValueAttr
|
||||||
: Identifier Equals value
|
: AttributeIdentifier Equals value
|
||||||
;
|
;
|
||||||
|
|
||||||
booleanAttr
|
booleanAttr
|
||||||
: Identifier
|
: AttributeIdentifier
|
||||||
;
|
;
|
||||||
|
|
||||||
value
|
value
|
||||||
|
@ -1,17 +1,25 @@
|
|||||||
@file:JvmName("MismatchedComponentTypeAnalysis")
|
@file:JvmName("MismatchedComponentTypeAnalysis")
|
||||||
package groowt.view.component.web.analysis
|
package groowt.view.component.web.analysis
|
||||||
|
|
||||||
|
import groowt.view.component.web.WebViewComponentBugError
|
||||||
import groowt.view.component.web.antlr.WebViewComponentsParser.ComponentTypeContext
|
import groowt.view.component.web.antlr.WebViewComponentsParser.ComponentTypeContext
|
||||||
import groowt.view.component.web.antlr.WebViewComponentsParser.ComponentWithChildrenContext
|
import groowt.view.component.web.antlr.WebViewComponentsParser.ComponentWithChildrenContext
|
||||||
import groowt.view.component.web.util.SourcePosition
|
import groowt.view.component.web.util.SourcePosition
|
||||||
import org.antlr.v4.runtime.ParserRuleContext
|
import org.antlr.v4.runtime.ParserRuleContext
|
||||||
import org.antlr.v4.runtime.Token
|
import org.antlr.v4.runtime.Token
|
||||||
import org.antlr.v4.runtime.tree.ParseTree
|
import org.antlr.v4.runtime.tree.ParseTree
|
||||||
import org.antlr.v4.runtime.tree.TerminalNode
|
|
||||||
|
|
||||||
private fun getIdentifiers(
|
private fun getIdentifiers(ctx: ComponentTypeContext): Token {
|
||||||
componentTypeContext: ComponentTypeContext
|
val typedIdentifier = ctx.TypedIdentifier()
|
||||||
): List<Token> = componentTypeContext.Identifier().map(TerminalNode::getSymbol)
|
if (typedIdentifier != null) {
|
||||||
|
return typedIdentifier.symbol
|
||||||
|
}
|
||||||
|
val stringIdentifier = ctx.StringIdentifier()
|
||||||
|
if (stringIdentifier != null) {
|
||||||
|
return stringIdentifier.symbol
|
||||||
|
}
|
||||||
|
throw WebViewComponentBugError("Could not determine identifier type: $ctx")
|
||||||
|
}
|
||||||
|
|
||||||
private fun getErrorMessage(
|
private fun getErrorMessage(
|
||||||
openType: ComponentTypeContext,
|
openType: ComponentTypeContext,
|
||||||
@ -20,20 +28,8 @@ private fun getErrorMessage(
|
|||||||
"Found '${openType.text}' at ${SourcePosition.formatStartOfTokenLong(openType.start)} " +
|
"Found '${openType.text}' at ${SourcePosition.formatStartOfTokenLong(openType.start)} " +
|
||||||
"and '${closingType.text}' at ${SourcePosition.formatStartOfTokenLong(closingType.start)}."
|
"and '${closingType.text}' at ${SourcePosition.formatStartOfTokenLong(closingType.start)}."
|
||||||
|
|
||||||
private fun test(
|
private fun test(openIdentifiers: Token, closingIdentifiers: Token): Boolean =
|
||||||
openIdentifiers: List<Token>,
|
openIdentifiers.text.equals(closingIdentifiers.text)
|
||||||
closingIdentifiers: List<Token>
|
|
||||||
): Boolean {
|
|
||||||
if (openIdentifiers.size != closingIdentifiers.size) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
openIdentifiers.zip(closingIdentifiers).forEach { (openIdentifier, closingIdentifier) ->
|
|
||||||
if (!openIdentifier.text.equals(closingIdentifier.text)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doCheck(tree: ParseTree, destination: MutableList<MismatchedComponentTypeError>) {
|
private fun doCheck(tree: ParseTree, destination: MutableList<MismatchedComponentTypeError>) {
|
||||||
if (tree is ParserRuleContext) {
|
if (tree is ParserRuleContext) {
|
||||||
@ -43,9 +39,9 @@ private fun doCheck(tree: ParseTree, destination: MutableList<MismatchedComponen
|
|||||||
if (tree is ComponentWithChildrenContext) {
|
if (tree is ComponentWithChildrenContext) {
|
||||||
val openType: ComponentTypeContext = tree.openComponent().componentArgs().componentType()
|
val openType: ComponentTypeContext = tree.openComponent().componentArgs().componentType()
|
||||||
val closingType: ComponentTypeContext = tree.closingComponent().componentType()
|
val closingType: ComponentTypeContext = tree.closingComponent().componentType()
|
||||||
val openTypeIdentifiers = getIdentifiers(openType)
|
val openIdentifier = getIdentifiers(openType)
|
||||||
val closingTypeIdentifiers = getIdentifiers(closingType)
|
val closingIdentifier = getIdentifiers(closingType)
|
||||||
if (!test(openTypeIdentifiers, closingTypeIdentifiers)) {
|
if (!test(openIdentifier, closingIdentifier)) {
|
||||||
destination.add(MismatchedComponentTypeError(tree, getErrorMessage(openType, closingType)))
|
destination.add(MismatchedComponentTypeError(tree, getErrorMessage(openType, closingType)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package groowt.view.component.web.antlr
|
||||||
|
|
||||||
|
import groowt.view.component.web.util.SourcePosition
|
||||||
|
|
||||||
|
data class LexerError(val type: LexerErrorType, val sourcePosition: SourcePosition)
|
||||||
|
|
||||||
|
fun format(lexerError: LexerError): String {
|
||||||
|
return "At ${lexerError.sourcePosition.toStringLong()}: ${lexerError.type.message}"
|
||||||
|
}
|
@ -0,0 +1,66 @@
|
|||||||
|
package groowt.view.component.web.antlr
|
||||||
|
|
||||||
|
import groowt.view.component.web.util.SourcePosition
|
||||||
|
import org.antlr.v4.runtime.*
|
||||||
|
import org.antlr.v4.runtime.atn.ATNConfigSet
|
||||||
|
import org.antlr.v4.runtime.dfa.DFA
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class LexerErrorListener : ANTLRErrorListener {
|
||||||
|
|
||||||
|
private val errors: MutableList<LexerError> = ArrayList()
|
||||||
|
|
||||||
|
fun getErrors(): List<LexerError> = this.errors
|
||||||
|
|
||||||
|
override fun syntaxError(
|
||||||
|
recognizer: Recognizer<*, *>,
|
||||||
|
offendingSymbol: Any?,
|
||||||
|
line: Int,
|
||||||
|
charPositionInLine: Int,
|
||||||
|
msg: String,
|
||||||
|
e: RecognitionException
|
||||||
|
) {
|
||||||
|
if (e is LexerNoViableAltException) {
|
||||||
|
val sourcePosition = SourcePosition(line, charPositionInLine + 1)
|
||||||
|
val lexerError = LexerError(LexerErrorType.NO_VIABLE_ALTERNATIVE, sourcePosition)
|
||||||
|
errors.add(lexerError)
|
||||||
|
} else {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportAmbiguity(
|
||||||
|
recognizer: Parser?,
|
||||||
|
dfa: DFA?,
|
||||||
|
startIndex: Int,
|
||||||
|
stopIndex: Int,
|
||||||
|
exact: Boolean,
|
||||||
|
ambigAlts: BitSet?,
|
||||||
|
configs: ATNConfigSet?
|
||||||
|
) {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportAttemptingFullContext(
|
||||||
|
recognizer: Parser?,
|
||||||
|
dfa: DFA?,
|
||||||
|
startIndex: Int,
|
||||||
|
stopIndex: Int,
|
||||||
|
conflictingAlts: BitSet?,
|
||||||
|
configs: ATNConfigSet?
|
||||||
|
) {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun reportContextSensitivity(
|
||||||
|
recognizer: Parser?,
|
||||||
|
dfa: DFA?,
|
||||||
|
startIndex: Int,
|
||||||
|
stopIndex: Int,
|
||||||
|
prediction: Int,
|
||||||
|
configs: ATNConfigSet?
|
||||||
|
) {
|
||||||
|
throw UnsupportedOperationException()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package groowt.view.component.web.antlr
|
||||||
|
|
||||||
|
enum class LexerErrorType(val message: String) {
|
||||||
|
NO_VIABLE_ALTERNATIVE("No viable alternative.")
|
||||||
|
}
|
@ -70,7 +70,7 @@ fun isIdentifierStartChar(c: Char): Boolean = Character.isJavaIdentifierStart(c)
|
|||||||
|
|
||||||
fun isIdentifierStartChar(subject: Int) = isIdentifierStartChar(subject.toChar())
|
fun isIdentifierStartChar(subject: Int) = isIdentifierStartChar(subject.toChar())
|
||||||
|
|
||||||
fun isIdentifierChar(c: Char): Boolean = Character.isJavaIdentifierPart(c)
|
fun isIdentifierChar(c: Char): Boolean = Character.isJavaIdentifierPart(c) || c == '-'
|
||||||
|
|
||||||
fun isIdentifierChar(subject: Int) = isIdentifierChar(subject.toChar())
|
fun isIdentifierChar(subject: Int) = isIdentifierChar(subject.toChar())
|
||||||
|
|
||||||
|
@ -4,4 +4,12 @@ package groowt.view.component.web.antlr
|
|||||||
import org.antlr.v4.runtime.CharStream
|
import org.antlr.v4.runtime.CharStream
|
||||||
import org.antlr.v4.runtime.Token
|
import org.antlr.v4.runtime.Token
|
||||||
|
|
||||||
fun runLexerAllTokens(input: CharStream): List<Token> = WebViewComponentsLexer(input).allTokens
|
fun runLexerAllTokensRaw(input: CharStream): List<Token> = WebViewComponentsLexer(input).allTokens
|
||||||
|
|
||||||
|
fun runLexerAllTokens(input: CharStream, withEOF: Boolean = false): List<Token> {
|
||||||
|
val lexer = WebViewComponentsLexer(input)
|
||||||
|
val stream = WebViewComponentsTokenStream(lexer)
|
||||||
|
return if (withEOF) stream.getAllTokens() else stream.getAllTokens()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun runLexerAllTokens(input: CharStream) = runLexerAllTokens(input, withEOF = false)
|
||||||
|
@ -0,0 +1,50 @@
|
|||||||
|
package groowt.view.component.web.antlr
|
||||||
|
|
||||||
|
import groowt.view.component.web.util.SourcePosition
|
||||||
|
import groowt.view.component.web.util.excerpt
|
||||||
|
import org.antlr.v4.runtime.ParserRuleContext
|
||||||
|
import org.antlr.v4.runtime.Token
|
||||||
|
|
||||||
|
open class ParserError(val type: ParserErrorType, val offending: Token, val context: ParserRuleContext)
|
||||||
|
|
||||||
|
class MismatchedInputParserError(
|
||||||
|
type: ParserErrorType,
|
||||||
|
offending: Token,
|
||||||
|
context: ParserRuleContext,
|
||||||
|
val expectedTokenTypes: Set<Int>
|
||||||
|
) : ParserError(type, offending, context)
|
||||||
|
|
||||||
|
fun format(error: ParserError): String {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val sourcePosition = SourcePosition.fromStartOfToken(error.offending)
|
||||||
|
sb.append("At ")
|
||||||
|
.append(sourcePosition.toStringLong())
|
||||||
|
.append(": ")
|
||||||
|
.append(error.type.message)
|
||||||
|
.append(" Offending token: ")
|
||||||
|
.append(formatTokenForError(error.offending))
|
||||||
|
.append(". ")
|
||||||
|
if (error is MismatchedInputParserError) {
|
||||||
|
sb.append("Expected any of: ")
|
||||||
|
.append(formatExpected(error.expectedTokenTypes))
|
||||||
|
.append(". ")
|
||||||
|
}
|
||||||
|
sb.append("(" + formatContext(error.context) + ").")
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatTokenForError(token: Token): String {
|
||||||
|
return "'${token.text}' (${getTokenName(token)})"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatContext(context: ParserRuleContext): String {
|
||||||
|
val sb = StringBuilder()
|
||||||
|
sb.append("context: ${context.javaClass.simpleName}")
|
||||||
|
if (context.text.isNotEmpty()) {
|
||||||
|
sb.append(", text: ")
|
||||||
|
.append(escapeChars(excerpt(context.text)))
|
||||||
|
}
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun formatExpected(expectedTokenTypes: Set<Int>): String = expectedTokenTypes.joinToString { getTokenName(it) }
|
@ -0,0 +1,41 @@
|
|||||||
|
package groowt.view.component.web.antlr
|
||||||
|
|
||||||
|
import org.antlr.v4.runtime.*
|
||||||
|
|
||||||
|
class ParserErrorListener : BaseErrorListener() {
|
||||||
|
|
||||||
|
private val errors: MutableList<ParserError> = ArrayList()
|
||||||
|
|
||||||
|
fun getErrors(): List<ParserError> = this.errors
|
||||||
|
|
||||||
|
override fun syntaxError(
|
||||||
|
recognizer: Recognizer<*, *>,
|
||||||
|
offendingSymbol: Any,
|
||||||
|
line: Int,
|
||||||
|
charPositionInLine: Int,
|
||||||
|
msg: String,
|
||||||
|
e: RecognitionException
|
||||||
|
) {
|
||||||
|
val parser = recognizer as WebViewComponentsParser
|
||||||
|
when (e) {
|
||||||
|
is NoViableAltException -> {
|
||||||
|
val error = ParserError(ParserErrorType.NO_VIABLE_ALTERNATIVE, e.offendingToken, parser.context)
|
||||||
|
errors.add(error)
|
||||||
|
}
|
||||||
|
is InputMismatchException -> {
|
||||||
|
val error = MismatchedInputParserError(
|
||||||
|
ParserErrorType.INPUT_MISMATCH,
|
||||||
|
e.offendingToken,
|
||||||
|
parser.context,
|
||||||
|
e.expectedTokens.toSet()
|
||||||
|
)
|
||||||
|
errors.add(error)
|
||||||
|
}
|
||||||
|
is FailedPredicateException -> {
|
||||||
|
val error = ParserError(ParserErrorType.FAILED_PREDICATE, e.offendingToken, parser.context)
|
||||||
|
errors.add(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package groowt.view.component.web.antlr
|
||||||
|
|
||||||
|
enum class ParserErrorType(val message: String) {
|
||||||
|
NO_VIABLE_ALTERNATIVE("No viable alternative."),
|
||||||
|
INPUT_MISMATCH("Input mismatch."),
|
||||||
|
FAILED_PREDICATE("Input failed predicate.")
|
||||||
|
}
|
@ -38,9 +38,6 @@ fun parseCompilationUnit(charStream: CharStream): CompilationUnitParseResult {
|
|||||||
return CompilationUnitParseResult(lexer, tokenStream, parser, cu)
|
return CompilationUnitParseResult(lexer, tokenStream, parser, cu)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun parseCompilationUnit(tokenStream: TokenStream): CompilationUnitContext =
|
|
||||||
parse(tokenStream, WebViewComponentsParser::compilationUnit)
|
|
||||||
|
|
||||||
fun parseCompilationUnit(
|
fun parseCompilationUnit(
|
||||||
tokenStream: TokenStream,
|
tokenStream: TokenStream,
|
||||||
onResult: BiConsumer<CompilationUnitContext, WebViewComponentsParser>
|
onResult: BiConsumer<CompilationUnitContext, WebViewComponentsParser>
|
||||||
|
@ -3,17 +3,18 @@ package groowt.view.component.web.antlr
|
|||||||
|
|
||||||
import groowt.view.component.web.antlr.WebViewComponentsLexer.GStringParts
|
import groowt.view.component.web.antlr.WebViewComponentsLexer.GStringParts
|
||||||
import groowt.view.component.web.antlr.WebViewComponentsLexer.GroovyTokens
|
import groowt.view.component.web.antlr.WebViewComponentsLexer.GroovyTokens
|
||||||
|
import groowt.view.component.web.util.SourcePosition
|
||||||
import org.antlr.v4.runtime.Token
|
import org.antlr.v4.runtime.Token
|
||||||
|
|
||||||
fun isGroovyTokenType(token: Token) = isGroovyTokenType(token.type)
|
fun isGroovyTokenType(token: Token) = isGroovyTokenType(token.type)
|
||||||
|
|
||||||
fun isGroovyTokenType(type: Int): Boolean = type in GroovyTokens
|
fun isGroovyTokenType(type: Int): Boolean = type in GroovyTokens
|
||||||
|
|
||||||
fun isGStringPart (token: Token) = isGStringPart(token.type)
|
fun isGStringPart(token: Token) = isGStringPart(token.type)
|
||||||
|
|
||||||
fun isGStringPart(type: Int): Boolean = type in GStringParts
|
fun isGStringPart(type: Int): Boolean = type in GStringParts
|
||||||
|
|
||||||
fun getTokenName (token: Token) = getTokenName(token.type)
|
fun getTokenName(token: Token) = getTokenName(token.type)
|
||||||
|
|
||||||
fun getTokenName(type: Int): String = WebViewComponentsLexer.VOCABULARY.getDisplayName(type)
|
fun getTokenName(type: Int): String = WebViewComponentsLexer.VOCABULARY.getDisplayName(type)
|
||||||
|
|
||||||
@ -25,15 +26,17 @@ fun interface TokenTextFormatter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun formatToken(token: Token, textFormatter: TokenTextFormatter): String =
|
fun formatToken(token: Token, textFormatter: TokenTextFormatter): String =
|
||||||
"${getTokenName(token)}[${token.line},${token.charPositionInLine}](${textFormatter.format(token.text)})"
|
getTokenName(token) + "[${formatTokenPositionShort(token)}](${textFormatter.format(token.text)})"
|
||||||
|
|
||||||
fun shortFormatToken(token: Token): String =
|
|
||||||
"${getTokenName(token)}[${token.line},${token.charPositionInLine},${token.text.length}]"
|
|
||||||
|
|
||||||
fun formatTokenText(text: String): String = excerptTokenParts(escapeTokenPartsToList(text))
|
fun formatTokenText(text: String): String = excerptTokenParts(escapeTokenPartsToList(text))
|
||||||
|
|
||||||
fun formatTokenPosition(token: Token): String {
|
fun formatTokenPositionShort(token: Token): String {
|
||||||
return "line ${token.line}, column ${token.charPositionInLine + 1}"
|
val sourcePosition = getTokenSourcePosition(token)
|
||||||
|
return "${sourcePosition.line},${sourcePosition.column}"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getTokenSourcePosition(token: Token): SourcePosition {
|
||||||
|
return SourcePosition(token.line, token.charPositionInLine + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun excerptToken(token: Token) = excerptToken(token, 30, 7, "...")
|
fun excerptToken(token: Token) = excerptToken(token, 30, 7, "...")
|
||||||
@ -42,7 +45,7 @@ fun excerptToken(token: Token, startLength: Int = 30, endLength: Int = 7, separa
|
|||||||
return excerptTokenParts(escapeTokenPartsToList(token.text), startLength, endLength, separator)
|
return excerptTokenParts(escapeTokenPartsToList(token.text), startLength, endLength, separator)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun excerptTokenParts(
|
private fun excerptTokenParts(
|
||||||
parts: List<String>,
|
parts: List<String>,
|
||||||
startLength: Int = 30,
|
startLength: Int = 30,
|
||||||
endLength: Int = 7,
|
endLength: Int = 7,
|
||||||
|
@ -7,7 +7,7 @@ private operator fun Interval.component1(): Int = this.a
|
|||||||
|
|
||||||
private operator fun Interval.component2(): Int = this.b
|
private operator fun Interval.component2(): Int = this.b
|
||||||
|
|
||||||
class WebViewComponentsTokenStream (private val tokenSource: TokenSource) : TokenStream {
|
class WebViewComponentsTokenStream(private val tokenSource: TokenSource) : TokenStream {
|
||||||
|
|
||||||
private val tokens: MutableList<Token> = ArrayList()
|
private val tokens: MutableList<Token> = ArrayList()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package groowt.view.component.web.ast;
|
package groowt.view.component.web.ast;
|
||||||
|
|
||||||
|
import groowt.view.component.web.WebViewComponentBugError;
|
||||||
import groowt.view.component.web.antlr.MergedGroovyCodeToken;
|
import groowt.view.component.web.antlr.MergedGroovyCodeToken;
|
||||||
import groowt.view.component.web.antlr.TokenUtil;
|
import groowt.view.component.web.antlr.TokenUtil;
|
||||||
import groowt.view.component.web.antlr.WebViewComponentsParser;
|
import groowt.view.component.web.antlr.WebViewComponentsParser;
|
||||||
@ -219,16 +220,18 @@ public class DefaultAstBuilderVisitor extends WebViewComponentsParserBaseVisitor
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitComponentType(WebViewComponentsParser.ComponentTypeContext ctx) {
|
public Node visitComponentType(WebViewComponentsParser.ComponentTypeContext ctx) {
|
||||||
final var identifiers = ctx.Identifier();
|
final var typedIdentifier = ctx.TypedIdentifier();
|
||||||
if (identifiers.size() == 1) {
|
if (typedIdentifier != null) {
|
||||||
final TerminalNode first = identifiers.getFirst();
|
return this.nodeFactory.classComponentTypeNode(this.getTokenRange(ctx));
|
||||||
if (startsWithLowercaseLetter(first.getText())) {
|
}
|
||||||
|
final var stringIdentifier = ctx.StringIdentifier();
|
||||||
|
if (stringIdentifier != null) {
|
||||||
return this.nodeFactory.stringComponentTypeNode(
|
return this.nodeFactory.stringComponentTypeNode(
|
||||||
this.getTokenRange(ctx), first.getSymbol().getTokenIndex()
|
this.getTokenRange(ctx),
|
||||||
|
stringIdentifier.getSymbol().getTokenIndex()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
throw new WebViewComponentBugError("Could not determine type of " + ctx);
|
||||||
return this.nodeFactory.classComponentTypeNode(this.getTokenRange(ctx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -253,7 +256,7 @@ public class DefaultAstBuilderVisitor extends WebViewComponentsParserBaseVisitor
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitKeyValueAttr(WebViewComponentsParser.KeyValueAttrContext ctx) {
|
public Node visitKeyValueAttr(WebViewComponentsParser.KeyValueAttrContext ctx) {
|
||||||
final TerminalNode identifier = ctx.Identifier();
|
final TerminalNode identifier = ctx.AttributeIdentifier();
|
||||||
final KeyNode keyNode = this.nodeFactory.keyNode(TokenRange.of(
|
final KeyNode keyNode = this.nodeFactory.keyNode(TokenRange.of(
|
||||||
identifier.getSymbol(),
|
identifier.getSymbol(),
|
||||||
ctx.Equals().getSymbol()
|
ctx.Equals().getSymbol()
|
||||||
@ -264,7 +267,7 @@ public class DefaultAstBuilderVisitor extends WebViewComponentsParserBaseVisitor
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Node visitBooleanAttr(WebViewComponentsParser.BooleanAttrContext ctx) {
|
public Node visitBooleanAttr(WebViewComponentsParser.BooleanAttrContext ctx) {
|
||||||
final Token identifierToken = ctx.Identifier().getSymbol();
|
final Token identifierToken = ctx.AttributeIdentifier().getSymbol();
|
||||||
final KeyNode keyNode = this.nodeFactory.keyNode(
|
final KeyNode keyNode = this.nodeFactory.keyNode(
|
||||||
TokenRange.of(identifierToken),
|
TokenRange.of(identifierToken),
|
||||||
identifierToken.getTokenIndex()
|
identifierToken.getTokenIndex()
|
||||||
|
@ -116,7 +116,7 @@ public final class CompilerPipeline {
|
|||||||
// build ast
|
// build ast
|
||||||
final var tokenList = new TokenList(parseResult.getTokenStream());
|
final var tokenList = new TokenList(parseResult.getTokenStream());
|
||||||
final var astBuilder = new DefaultAstBuilder(new DefaultNodeFactory(tokenList));
|
final var astBuilder = new DefaultAstBuilder(new DefaultNodeFactory(tokenList));
|
||||||
return (CompilationUnitNode) astBuilder.build(parseResult.getCompilationUnitContext());
|
return astBuilder.buildCompilationUnit(parseResult.getCompilationUnitContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
private CompilerPipeline() {}
|
private CompilerPipeline() {}
|
||||||
|
@ -0,0 +1,12 @@
|
|||||||
|
@file:JvmName("TextUtil")
|
||||||
|
package groowt.view.component.web.util
|
||||||
|
|
||||||
|
fun excerpt(s: String, startLength: Int = 30, endLength: Int = 7, ellipsis: String = "..."): String {
|
||||||
|
if (s.length > startLength + endLength + ellipsis.length) {
|
||||||
|
val start = s.substring(0..<startLength)
|
||||||
|
val end = s.substring((s.length - endLength)..<s.length)
|
||||||
|
return start + ellipsis + end
|
||||||
|
} else {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
}
|
@ -1,75 +1,69 @@
|
|||||||
CompilationUnitNode(1,1..21,6)
|
CompilationUnitNode(1,1..21,6)
|
||||||
PreambleNode(1,1..6,1)
|
PreambleNode(1,1..6,1)
|
||||||
PreambleBreak[1,0](---\n)
|
PreambleBreak[1,1](---\n)
|
||||||
GroovyCode[2,0](import some.Thing // a comment...World!')
|
GroovyCode[2,1](import some.Thing // a comment...World!')
|
||||||
PreambleBreak[4,30](\n---\n)
|
PreambleBreak[4,31](\n---\n)
|
||||||
BodyNode(6,1..21,1)
|
BodyNode(6,1..21,1)
|
||||||
JStringBodyTextNode(6,1..7,1)
|
JStringBodyTextNode(6,1..7,1)
|
||||||
RawText[6,0](<!DOCTYPE html>\n)
|
RawText[6,1](<!DOCTYPE html>\n)
|
||||||
TypedComponentNode(7,1..20,8)
|
TypedComponentNode(7,1..20,8)
|
||||||
ComponentArgsNode(7,2..7,6)
|
ComponentArgsNode(7,2..7,6)
|
||||||
StringComponentTypeNode(7,2..7,6)
|
StringComponentTypeNode(7,2..7,6)
|
||||||
Identifier[7,1](html)
|
StringIdentifier[7,2](html)
|
||||||
BodyNode(7,7..20,1)
|
BodyNode(7,7..20,1)
|
||||||
TypedComponentNode(8,5..8,18)
|
TypedComponentNode(8,5..8,18)
|
||||||
ComponentArgsNode(8,6..8,10)
|
ComponentArgsNode(8,6..8,10)
|
||||||
StringComponentTypeNode(8,6..8,10)
|
StringComponentTypeNode(8,6..8,10)
|
||||||
Identifier[8,5](head)
|
StringIdentifier[8,6](head)
|
||||||
TypedComponentNode(9,5..19,12)
|
TypedComponentNode(9,5..19,12)
|
||||||
ComponentArgsNode(9,6..9,10)
|
ComponentArgsNode(9,6..9,10)
|
||||||
StringComponentTypeNode(9,6..9,10)
|
StringComponentTypeNode(9,6..9,10)
|
||||||
Identifier[9,5](body)
|
StringIdentifier[9,6](body)
|
||||||
BodyNode(9,11..19,5)
|
BodyNode(9,11..19,5)
|
||||||
TypedComponentNode(10,9..10,29)
|
TypedComponentNode(10,9..10,29)
|
||||||
ComponentArgsNode(10,10..10,12)
|
ComponentArgsNode(10,10..10,12)
|
||||||
StringComponentTypeNode(10,10..10,12)
|
StringComponentTypeNode(10,10..10,12)
|
||||||
Identifier[10,9](h1)
|
StringIdentifier[10,10](h1)
|
||||||
BodyNode(10,13..10,24)
|
BodyNode(10,13..10,24)
|
||||||
GStringBodyTextNode(10,13..10,24)
|
GStringBodyTextNode(10,13..10,24)
|
||||||
DollarScriptletNode(10,13..10,24)
|
DollarScriptletNode(10,13..10,24)
|
||||||
DollarScriptletOpen[10,12](${)
|
DollarScriptletOpen[10,13](${)
|
||||||
GroovyCode[10,14](greeting)
|
GroovyCode[10,15](greeting)
|
||||||
DollarScriptletClose[10,22](})
|
DollarScriptletClose[10,23](})
|
||||||
TypedComponentNode(11,9..18,34)
|
TypedComponentNode(11,9..18,34)
|
||||||
ComponentArgsNode(11,10..11,32)
|
ComponentArgsNode(11,10..11,32)
|
||||||
ClassComponentTypeNode(11,10..11,32)
|
ClassComponentTypeNode(11,10..11,32)
|
||||||
Identifier[11,9](groowt)
|
TypedIdentifier[11,10](groowt.view.web.Select)
|
||||||
Dot[11,15](.)
|
|
||||||
Identifier[11,16](view)
|
|
||||||
Dot[11,20](.)
|
|
||||||
Identifier[11,21](web)
|
|
||||||
Dot[11,24](.)
|
|
||||||
Identifier[11,25](Select)
|
|
||||||
BodyNode(11,33..18,9)
|
BodyNode(11,33..18,9)
|
||||||
TypedComponentNode(12,13..14,20)
|
TypedComponentNode(12,13..14,20)
|
||||||
ComponentArgsNode(12,14..12,36)
|
ComponentArgsNode(12,14..12,36)
|
||||||
ClassComponentTypeNode(12,14..12,18)
|
ClassComponentTypeNode(12,14..12,18)
|
||||||
Identifier[12,13](Case)
|
TypedIdentifier[12,14](Case)
|
||||||
KeyValueAttrNode(12,19..12,36)
|
KeyValueAttrNode(12,19..12,36)
|
||||||
KeyNode(12,19..12,24)
|
KeyNode(12,19..12,24)
|
||||||
Identifier[12,18](cond)
|
AttributeIdentifier[12,19](cond)
|
||||||
Equals[12,22](=)
|
Equals[12,23](=)
|
||||||
ClosureValueNode(12,24..12,36)
|
ClosureValueNode(12,24..12,36)
|
||||||
ClosureAttrValueStart[12,23]({)
|
ClosureAttrValueStart[12,24]({)
|
||||||
GroovyCode[12,24](isItTrue())
|
GroovyCode[12,25](isItTrue())
|
||||||
ClosureAttrValueEnd[12,34](})
|
ClosureAttrValueEnd[12,35](})
|
||||||
BodyNode(12,37..14,13)
|
BodyNode(12,37..14,13)
|
||||||
TypedComponentNode(13,17..13,37)
|
TypedComponentNode(13,17..13,37)
|
||||||
ComponentArgsNode(13,18..13,19)
|
ComponentArgsNode(13,18..13,19)
|
||||||
StringComponentTypeNode(13,18..13,19)
|
StringComponentTypeNode(13,18..13,19)
|
||||||
Identifier[13,17](p)
|
StringIdentifier[13,18](p)
|
||||||
BodyNode(13,20..13,33)
|
BodyNode(13,20..13,33)
|
||||||
JStringBodyTextNode(13,20..13,33)
|
JStringBodyTextNode(13,20..13,33)
|
||||||
RawText[13,19](It's true! :))
|
RawText[13,20](It's true! :))
|
||||||
TypedComponentNode(15,13..17,23)
|
TypedComponentNode(15,13..17,23)
|
||||||
ComponentArgsNode(15,14..15,21)
|
ComponentArgsNode(15,14..15,21)
|
||||||
ClassComponentTypeNode(15,14..15,21)
|
ClassComponentTypeNode(15,14..15,21)
|
||||||
Identifier[15,13](Default)
|
TypedIdentifier[15,14](Default)
|
||||||
BodyNode(15,22..17,13)
|
BodyNode(15,22..17,13)
|
||||||
TypedComponentNode(16,17..16,40)
|
TypedComponentNode(16,17..16,40)
|
||||||
ComponentArgsNode(16,18..16,19)
|
ComponentArgsNode(16,18..16,19)
|
||||||
StringComponentTypeNode(16,18..16,19)
|
StringComponentTypeNode(16,18..16,19)
|
||||||
Identifier[16,17](p)
|
StringIdentifier[16,18](p)
|
||||||
BodyNode(16,20..16,36)
|
BodyNode(16,20..16,36)
|
||||||
JStringBodyTextNode(16,20..16,36)
|
JStringBodyTextNode(16,20..16,36)
|
||||||
RawText[16,19](It's false... :()
|
RawText[16,20](It's false... :()
|
||||||
|
@ -2,9 +2,9 @@ CompilationUnitNode(1,1..2,6)
|
|||||||
BodyNode(1,1..2,1)
|
BodyNode(1,1..2,1)
|
||||||
GStringBodyTextNode(1,1..2,1)
|
GStringBodyTextNode(1,1..2,1)
|
||||||
JStringBodyTextNode(1,1..1,8)
|
JStringBodyTextNode(1,1..1,8)
|
||||||
RawText[1,0](Hello, )
|
RawText[1,1](Hello, )
|
||||||
DollarReferenceNode(1,8..1,15)
|
DollarReferenceNode(1,8..1,15)
|
||||||
DollarReferenceStart[1,7]($)
|
DollarReferenceStart[1,8]($)
|
||||||
GroovyCode[1,8](target)
|
GroovyCode[1,9](target)
|
||||||
JStringBodyTextNode(1,15..2,1)
|
JStringBodyTextNode(1,15..2,1)
|
||||||
RawText[1,14](!\n)
|
RawText[1,15](!\n)
|
||||||
|
@ -3,7 +3,7 @@ CompilationUnitNode(1,1..2,6)
|
|||||||
TypedComponentNode(1,1..1,35)
|
TypedComponentNode(1,1..1,35)
|
||||||
ComponentArgsNode(1,2..1,10)
|
ComponentArgsNode(1,2..1,10)
|
||||||
ClassComponentTypeNode(1,2..1,10)
|
ClassComponentTypeNode(1,2..1,10)
|
||||||
Identifier[1,1](Greeting)
|
TypedIdentifier[1,2](Greeting)
|
||||||
BodyNode(1,11..1,24)
|
BodyNode(1,11..1,24)
|
||||||
JStringBodyTextNode(1,11..1,24)
|
JStringBodyTextNode(1,11..1,24)
|
||||||
RawText[1,10](to the world!)
|
RawText[1,11](to the world!)
|
||||||
|
20
web-view-components-compiler/src/test/lexer/complicated.wvc
Normal file
20
web-view-components-compiler/src/test/lexer/complicated.wvc
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
import some.Thing // a comment
|
||||||
|
|
||||||
|
def greeting = 'Hello, World!'
|
||||||
|
---
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head></head>
|
||||||
|
<body>
|
||||||
|
<h1>${greeting}</h1>
|
||||||
|
<groowt.view.web.Select>
|
||||||
|
<Case cond={isItTrue()}>
|
||||||
|
<p>It's true! :)</p>
|
||||||
|
</Case>
|
||||||
|
<Default>
|
||||||
|
<p>It's false... :(</p>
|
||||||
|
</Default>
|
||||||
|
</groowt.view.web.Select>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1 @@
|
|||||||
|
<data-test />
|
@ -0,0 +1 @@
|
|||||||
|
<html></html>
|
@ -0,0 +1 @@
|
|||||||
|
<groowt.Test></groowt.Test>
|
@ -0,0 +1,83 @@
|
|||||||
|
PreambleBreak[1,1](---\n)
|
||||||
|
GroovyCode[2,1](import some.Thing // a comment...World!')
|
||||||
|
PreambleBreak[4,31](\n---\n)
|
||||||
|
RawText[6,1](<!DOCTYPE html>\n)
|
||||||
|
ComponentOpen[7,1](<)
|
||||||
|
StringIdentifier[7,2](html)
|
||||||
|
ComponentClose[7,6](>)
|
||||||
|
RawText[7,7](\n )
|
||||||
|
ComponentOpen[8,5](<)
|
||||||
|
StringIdentifier[8,6](head)
|
||||||
|
ComponentClose[8,10](>)
|
||||||
|
ClosingComponentOpen[8,11](</)
|
||||||
|
StringIdentifier[8,13](head)
|
||||||
|
ComponentClose[8,17](>)
|
||||||
|
RawText[8,18](\n )
|
||||||
|
ComponentOpen[9,5](<)
|
||||||
|
StringIdentifier[9,6](body)
|
||||||
|
ComponentClose[9,10](>)
|
||||||
|
RawText[9,11](\n )
|
||||||
|
ComponentOpen[10,9](<)
|
||||||
|
StringIdentifier[10,10](h1)
|
||||||
|
ComponentClose[10,12](>)
|
||||||
|
DollarScriptletOpen[10,13](${)
|
||||||
|
GroovyCode[10,15](greeting)
|
||||||
|
DollarScriptletClose[10,23](})
|
||||||
|
ClosingComponentOpen[10,24](</)
|
||||||
|
StringIdentifier[10,26](h1)
|
||||||
|
ComponentClose[10,28](>)
|
||||||
|
RawText[10,29](\n )
|
||||||
|
ComponentOpen[11,9](<)
|
||||||
|
TypedIdentifier[11,10](groowt.view.web.Select)
|
||||||
|
ComponentClose[11,32](>)
|
||||||
|
RawText[11,33](\n )
|
||||||
|
ComponentOpen[12,13](<)
|
||||||
|
TypedIdentifier[12,14](Case)
|
||||||
|
ComponentNlws[12,18]( )
|
||||||
|
AttributeIdentifier[12,19](cond)
|
||||||
|
Equals[12,23](=)
|
||||||
|
ClosureAttrValueStart[12,24]({)
|
||||||
|
GroovyCode[12,25](isItTrue())
|
||||||
|
ClosureAttrValueEnd[12,35](})
|
||||||
|
ComponentClose[12,36](>)
|
||||||
|
RawText[12,37](\n )
|
||||||
|
ComponentOpen[13,17](<)
|
||||||
|
StringIdentifier[13,18](p)
|
||||||
|
ComponentClose[13,19](>)
|
||||||
|
RawText[13,20](It's true! :))
|
||||||
|
ClosingComponentOpen[13,33](</)
|
||||||
|
StringIdentifier[13,35](p)
|
||||||
|
ComponentClose[13,36](>)
|
||||||
|
RawText[13,37](\n )
|
||||||
|
ClosingComponentOpen[14,13](</)
|
||||||
|
TypedIdentifier[14,15](Case)
|
||||||
|
ComponentClose[14,19](>)
|
||||||
|
RawText[14,20](\n )
|
||||||
|
ComponentOpen[15,13](<)
|
||||||
|
TypedIdentifier[15,14](Default)
|
||||||
|
ComponentClose[15,21](>)
|
||||||
|
RawText[15,22](\n )
|
||||||
|
ComponentOpen[16,17](<)
|
||||||
|
StringIdentifier[16,18](p)
|
||||||
|
ComponentClose[16,19](>)
|
||||||
|
RawText[16,20](It's false... :()
|
||||||
|
ClosingComponentOpen[16,36](</)
|
||||||
|
StringIdentifier[16,38](p)
|
||||||
|
ComponentClose[16,39](>)
|
||||||
|
RawText[16,40](\n )
|
||||||
|
ClosingComponentOpen[17,13](</)
|
||||||
|
TypedIdentifier[17,15](Default)
|
||||||
|
ComponentClose[17,22](>)
|
||||||
|
RawText[17,23](\n )
|
||||||
|
ClosingComponentOpen[18,9](</)
|
||||||
|
TypedIdentifier[18,11](groowt.view.web.Select)
|
||||||
|
ComponentClose[18,33](>)
|
||||||
|
RawText[18,34](\n )
|
||||||
|
ClosingComponentOpen[19,5](</)
|
||||||
|
StringIdentifier[19,7](body)
|
||||||
|
ComponentClose[19,11](>)
|
||||||
|
RawText[19,12](\n)
|
||||||
|
ClosingComponentOpen[20,1](</)
|
||||||
|
StringIdentifier[20,3](html)
|
||||||
|
ComponentClose[20,7](>)
|
||||||
|
RawText[20,8](\n)
|
@ -0,0 +1,5 @@
|
|||||||
|
ComponentOpen[1,1](<)
|
||||||
|
StringIdentifier[1,2](data-test)
|
||||||
|
ComponentNlws[1,11]( )
|
||||||
|
ComponentSelfClose[1,12](/>)
|
||||||
|
RawText[1,14](\n)
|
@ -0,0 +1,7 @@
|
|||||||
|
ComponentOpen[1,1](<)
|
||||||
|
StringIdentifier[1,2](html)
|
||||||
|
ComponentClose[1,6](>)
|
||||||
|
ClosingComponentOpen[1,7](</)
|
||||||
|
StringIdentifier[1,9](html)
|
||||||
|
ComponentClose[1,13](>)
|
||||||
|
RawText[1,14](\n)
|
@ -0,0 +1,7 @@
|
|||||||
|
ComponentOpen[1,1](<)
|
||||||
|
TypedIdentifier[1,2](groowt.Test)
|
||||||
|
ComponentClose[1,13](>)
|
||||||
|
ClosingComponentOpen[1,14](</)
|
||||||
|
TypedIdentifier[1,16](groowt.Test)
|
||||||
|
ComponentClose[1,27](>)
|
||||||
|
RawText[1,28](\n)
|
@ -1,4 +1,4 @@
|
|||||||
RawText[1,0](Hello, )
|
RawText[1,1](Hello, )
|
||||||
DollarReferenceStart[1,7]($)
|
DollarReferenceStart[1,8]($)
|
||||||
GroovyCode[1,8](target)
|
GroovyCode[1,9](target)
|
||||||
RawText[1,14](!\n)
|
RawText[1,15](!\n)
|
@ -1 +1 @@
|
|||||||
RawText[1,0](Hello, World!\n)
|
RawText[1,1](Hello, World!\n)
|
@ -0,0 +1 @@
|
|||||||
|
<html></html>
|
@ -13,7 +13,7 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[7,1](<)
|
ComponentOpen[7,1](<)
|
||||||
componentArgs[7,2..7,2]
|
componentArgs[7,2..7,2]
|
||||||
componentType[7,2..7,2]
|
componentType[7,2..7,2]
|
||||||
Identifier[7,2](html)
|
StringIdentifier[7,2](html)
|
||||||
ComponentClose[7,6](>)
|
ComponentClose[7,6](>)
|
||||||
body[7,7..19,12]
|
body[7,7..19,12]
|
||||||
bodyText[7,7..7,7]
|
bodyText[7,7..7,7]
|
||||||
@ -25,12 +25,12 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[8,5](<)
|
ComponentOpen[8,5](<)
|
||||||
componentArgs[8,6..8,6]
|
componentArgs[8,6..8,6]
|
||||||
componentType[8,6..8,6]
|
componentType[8,6..8,6]
|
||||||
Identifier[8,6](head)
|
StringIdentifier[8,6](head)
|
||||||
ComponentClose[8,10](>)
|
ComponentClose[8,10](>)
|
||||||
closingComponent[8,11..8,17]
|
closingComponent[8,11..8,17]
|
||||||
ClosingComponentOpen[8,11](</)
|
ClosingComponentOpen[8,11](</)
|
||||||
componentType[8,13..8,13]
|
componentType[8,13..8,13]
|
||||||
Identifier[8,13](head)
|
StringIdentifier[8,13](head)
|
||||||
ComponentClose[8,17](>)
|
ComponentClose[8,17](>)
|
||||||
bodyText[8,18..8,18]
|
bodyText[8,18..8,18]
|
||||||
jStringBodyText[8,18..8,18]
|
jStringBodyText[8,18..8,18]
|
||||||
@ -41,7 +41,7 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[9,5](<)
|
ComponentOpen[9,5](<)
|
||||||
componentArgs[9,6..9,6]
|
componentArgs[9,6..9,6]
|
||||||
componentType[9,6..9,6]
|
componentType[9,6..9,6]
|
||||||
Identifier[9,6](body)
|
StringIdentifier[9,6](body)
|
||||||
ComponentClose[9,10](>)
|
ComponentClose[9,10](>)
|
||||||
body[9,11..18,34]
|
body[9,11..18,34]
|
||||||
bodyText[9,11..9,11]
|
bodyText[9,11..9,11]
|
||||||
@ -53,7 +53,7 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[10,9](<)
|
ComponentOpen[10,9](<)
|
||||||
componentArgs[10,10..10,10]
|
componentArgs[10,10..10,10]
|
||||||
componentType[10,10..10,10]
|
componentType[10,10..10,10]
|
||||||
Identifier[10,10](h1)
|
StringIdentifier[10,10](h1)
|
||||||
ComponentClose[10,12](>)
|
ComponentClose[10,12](>)
|
||||||
body[10,13..10,23]
|
body[10,13..10,23]
|
||||||
bodyText[10,13..10,23]
|
bodyText[10,13..10,23]
|
||||||
@ -66,7 +66,7 @@ compilationUnit[1,1..21,1]
|
|||||||
closingComponent[10,24..10,28]
|
closingComponent[10,24..10,28]
|
||||||
ClosingComponentOpen[10,24](</)
|
ClosingComponentOpen[10,24](</)
|
||||||
componentType[10,26..10,26]
|
componentType[10,26..10,26]
|
||||||
Identifier[10,26](h1)
|
StringIdentifier[10,26](h1)
|
||||||
ComponentClose[10,28](>)
|
ComponentClose[10,28](>)
|
||||||
bodyText[10,29..10,29]
|
bodyText[10,29..10,29]
|
||||||
jStringBodyText[10,29..10,29]
|
jStringBodyText[10,29..10,29]
|
||||||
@ -75,15 +75,9 @@ compilationUnit[1,1..21,1]
|
|||||||
componentWithChildren[11,9..18,33]
|
componentWithChildren[11,9..18,33]
|
||||||
openComponent[11,9..11,32]
|
openComponent[11,9..11,32]
|
||||||
ComponentOpen[11,9](<)
|
ComponentOpen[11,9](<)
|
||||||
componentArgs[11,10..11,26]
|
componentArgs[11,10..11,10]
|
||||||
componentType[11,10..11,26]
|
componentType[11,10..11,10]
|
||||||
Identifier[11,10](groowt)
|
TypedIdentifier[11,10](groowt.view.web.Select)
|
||||||
Dot[11,16](.)
|
|
||||||
Identifier[11,17](view)
|
|
||||||
Dot[11,21](.)
|
|
||||||
Identifier[11,22](web)
|
|
||||||
Dot[11,25](.)
|
|
||||||
Identifier[11,26](Select)
|
|
||||||
ComponentClose[11,32](>)
|
ComponentClose[11,32](>)
|
||||||
body[11,33..17,23]
|
body[11,33..17,23]
|
||||||
bodyText[11,33..11,33]
|
bodyText[11,33..11,33]
|
||||||
@ -95,11 +89,11 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[12,13](<)
|
ComponentOpen[12,13](<)
|
||||||
componentArgs[12,14..12,35]
|
componentArgs[12,14..12,35]
|
||||||
componentType[12,14..12,14]
|
componentType[12,14..12,14]
|
||||||
Identifier[12,14](Case)
|
TypedIdentifier[12,14](Case)
|
||||||
ComponentNlws[12,18]( )
|
ComponentNlws[12,18]( )
|
||||||
attr[12,19..12,35]
|
attr[12,19..12,35]
|
||||||
keyValueAttr[12,19..12,35]
|
keyValueAttr[12,19..12,35]
|
||||||
Identifier[12,19](cond)
|
AttributeIdentifier[12,19](cond)
|
||||||
Equals[12,23](=)
|
Equals[12,23](=)
|
||||||
value[12,24..12,35]
|
value[12,24..12,35]
|
||||||
closureAttrValue[12,24..12,35]
|
closureAttrValue[12,24..12,35]
|
||||||
@ -117,7 +111,7 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[13,17](<)
|
ComponentOpen[13,17](<)
|
||||||
componentArgs[13,18..13,18]
|
componentArgs[13,18..13,18]
|
||||||
componentType[13,18..13,18]
|
componentType[13,18..13,18]
|
||||||
Identifier[13,18](p)
|
StringIdentifier[13,18](p)
|
||||||
ComponentClose[13,19](>)
|
ComponentClose[13,19](>)
|
||||||
body[13,20..13,20]
|
body[13,20..13,20]
|
||||||
bodyText[13,20..13,20]
|
bodyText[13,20..13,20]
|
||||||
@ -126,7 +120,7 @@ compilationUnit[1,1..21,1]
|
|||||||
closingComponent[13,33..13,36]
|
closingComponent[13,33..13,36]
|
||||||
ClosingComponentOpen[13,33](</)
|
ClosingComponentOpen[13,33](</)
|
||||||
componentType[13,35..13,35]
|
componentType[13,35..13,35]
|
||||||
Identifier[13,35](p)
|
StringIdentifier[13,35](p)
|
||||||
ComponentClose[13,36](>)
|
ComponentClose[13,36](>)
|
||||||
bodyText[13,37..13,37]
|
bodyText[13,37..13,37]
|
||||||
jStringBodyText[13,37..13,37]
|
jStringBodyText[13,37..13,37]
|
||||||
@ -134,7 +128,7 @@ compilationUnit[1,1..21,1]
|
|||||||
closingComponent[14,13..14,19]
|
closingComponent[14,13..14,19]
|
||||||
ClosingComponentOpen[14,13](</)
|
ClosingComponentOpen[14,13](</)
|
||||||
componentType[14,15..14,15]
|
componentType[14,15..14,15]
|
||||||
Identifier[14,15](Case)
|
TypedIdentifier[14,15](Case)
|
||||||
ComponentClose[14,19](>)
|
ComponentClose[14,19](>)
|
||||||
bodyText[14,20..14,20]
|
bodyText[14,20..14,20]
|
||||||
jStringBodyText[14,20..14,20]
|
jStringBodyText[14,20..14,20]
|
||||||
@ -145,7 +139,7 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[15,13](<)
|
ComponentOpen[15,13](<)
|
||||||
componentArgs[15,14..15,14]
|
componentArgs[15,14..15,14]
|
||||||
componentType[15,14..15,14]
|
componentType[15,14..15,14]
|
||||||
Identifier[15,14](Default)
|
TypedIdentifier[15,14](Default)
|
||||||
ComponentClose[15,21](>)
|
ComponentClose[15,21](>)
|
||||||
body[15,22..16,40]
|
body[15,22..16,40]
|
||||||
bodyText[15,22..15,22]
|
bodyText[15,22..15,22]
|
||||||
@ -157,7 +151,7 @@ compilationUnit[1,1..21,1]
|
|||||||
ComponentOpen[16,17](<)
|
ComponentOpen[16,17](<)
|
||||||
componentArgs[16,18..16,18]
|
componentArgs[16,18..16,18]
|
||||||
componentType[16,18..16,18]
|
componentType[16,18..16,18]
|
||||||
Identifier[16,18](p)
|
StringIdentifier[16,18](p)
|
||||||
ComponentClose[16,19](>)
|
ComponentClose[16,19](>)
|
||||||
body[16,20..16,20]
|
body[16,20..16,20]
|
||||||
bodyText[16,20..16,20]
|
bodyText[16,20..16,20]
|
||||||
@ -166,7 +160,7 @@ compilationUnit[1,1..21,1]
|
|||||||
closingComponent[16,36..16,39]
|
closingComponent[16,36..16,39]
|
||||||
ClosingComponentOpen[16,36](</)
|
ClosingComponentOpen[16,36](</)
|
||||||
componentType[16,38..16,38]
|
componentType[16,38..16,38]
|
||||||
Identifier[16,38](p)
|
StringIdentifier[16,38](p)
|
||||||
ComponentClose[16,39](>)
|
ComponentClose[16,39](>)
|
||||||
bodyText[16,40..16,40]
|
bodyText[16,40..16,40]
|
||||||
jStringBodyText[16,40..16,40]
|
jStringBodyText[16,40..16,40]
|
||||||
@ -174,21 +168,15 @@ compilationUnit[1,1..21,1]
|
|||||||
closingComponent[17,13..17,22]
|
closingComponent[17,13..17,22]
|
||||||
ClosingComponentOpen[17,13](</)
|
ClosingComponentOpen[17,13](</)
|
||||||
componentType[17,15..17,15]
|
componentType[17,15..17,15]
|
||||||
Identifier[17,15](Default)
|
TypedIdentifier[17,15](Default)
|
||||||
ComponentClose[17,22](>)
|
ComponentClose[17,22](>)
|
||||||
bodyText[17,23..17,23]
|
bodyText[17,23..17,23]
|
||||||
jStringBodyText[17,23..17,23]
|
jStringBodyText[17,23..17,23]
|
||||||
RawText[17,23](\n )
|
RawText[17,23](\n )
|
||||||
closingComponent[18,9..18,33]
|
closingComponent[18,9..18,33]
|
||||||
ClosingComponentOpen[18,9](</)
|
ClosingComponentOpen[18,9](</)
|
||||||
componentType[18,11..18,27]
|
componentType[18,11..18,11]
|
||||||
Identifier[18,11](groowt)
|
TypedIdentifier[18,11](groowt.view.web.Select)
|
||||||
Dot[18,17](.)
|
|
||||||
Identifier[18,18](view)
|
|
||||||
Dot[18,22](.)
|
|
||||||
Identifier[18,23](web)
|
|
||||||
Dot[18,26](.)
|
|
||||||
Identifier[18,27](Select)
|
|
||||||
ComponentClose[18,33](>)
|
ComponentClose[18,33](>)
|
||||||
bodyText[18,34..18,34]
|
bodyText[18,34..18,34]
|
||||||
jStringBodyText[18,34..18,34]
|
jStringBodyText[18,34..18,34]
|
||||||
@ -196,7 +184,7 @@ compilationUnit[1,1..21,1]
|
|||||||
closingComponent[19,5..19,11]
|
closingComponent[19,5..19,11]
|
||||||
ClosingComponentOpen[19,5](</)
|
ClosingComponentOpen[19,5](</)
|
||||||
componentType[19,7..19,7]
|
componentType[19,7..19,7]
|
||||||
Identifier[19,7](body)
|
StringIdentifier[19,7](body)
|
||||||
ComponentClose[19,11](>)
|
ComponentClose[19,11](>)
|
||||||
bodyText[19,12..19,12]
|
bodyText[19,12..19,12]
|
||||||
jStringBodyText[19,12..19,12]
|
jStringBodyText[19,12..19,12]
|
||||||
@ -204,7 +192,7 @@ compilationUnit[1,1..21,1]
|
|||||||
closingComponent[20,1..20,7]
|
closingComponent[20,1..20,7]
|
||||||
ClosingComponentOpen[20,1](</)
|
ClosingComponentOpen[20,1](</)
|
||||||
componentType[20,3..20,3]
|
componentType[20,3..20,3]
|
||||||
Identifier[20,3](html)
|
StringIdentifier[20,3](html)
|
||||||
ComponentClose[20,7](>)
|
ComponentClose[20,7](>)
|
||||||
bodyText[20,8..20,8]
|
bodyText[20,8..20,8]
|
||||||
jStringBodyText[20,8..20,8]
|
jStringBodyText[20,8..20,8]
|
||||||
|
@ -0,0 +1,19 @@
|
|||||||
|
compilationUnit[1,1..2,1]
|
||||||
|
body[1,1..1,14]
|
||||||
|
component[1,1..1,13]
|
||||||
|
componentWithChildren[1,1..1,13]
|
||||||
|
openComponent[1,1..1,6]
|
||||||
|
ComponentOpen[1,1](<)
|
||||||
|
componentArgs[1,2..1,2]
|
||||||
|
componentType[1,2..1,2]
|
||||||
|
StringIdentifier[1,2](html)
|
||||||
|
ComponentClose[1,6](>)
|
||||||
|
closingComponent[1,7..1,13]
|
||||||
|
ClosingComponentOpen[1,7](</)
|
||||||
|
componentType[1,9..1,9]
|
||||||
|
StringIdentifier[1,9](html)
|
||||||
|
ComponentClose[1,13](>)
|
||||||
|
bodyText[1,14..1,14]
|
||||||
|
jStringBodyText[1,14..1,14]
|
||||||
|
RawText[1,14](\n)
|
||||||
|
EOF[2,1](<EOF>)
|
@ -5,7 +5,6 @@ import groowt.view.component.web.antlr.TokenList;
|
|||||||
import groowt.view.component.web.ast.DefaultAstBuilder;
|
import groowt.view.component.web.ast.DefaultAstBuilder;
|
||||||
import groowt.view.component.web.ast.DefaultNodeFactory;
|
import groowt.view.component.web.ast.DefaultNodeFactory;
|
||||||
import groowt.view.component.web.ast.node.BodyNode;
|
import groowt.view.component.web.ast.node.BodyNode;
|
||||||
import groowt.view.component.web.ast.node.CompilationUnitNode;
|
|
||||||
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
import groowt.view.component.web.compiler.WebViewComponentTemplateCompileUnit;
|
||||||
import groowt.view.component.web.transpile.BodyTranspiler;
|
import groowt.view.component.web.transpile.BodyTranspiler;
|
||||||
import groowt.view.component.web.transpile.TranspilerConfiguration;
|
import groowt.view.component.web.transpile.TranspilerConfiguration;
|
||||||
@ -39,7 +38,7 @@ public abstract class BodyTranspilerTests {
|
|||||||
final var parseResult = ParserUtil.parseCompilationUnit(source);
|
final var parseResult = ParserUtil.parseCompilationUnit(source);
|
||||||
final var tokenList = new TokenList(parseResult.getTokenStream());
|
final var tokenList = new TokenList(parseResult.getTokenStream());
|
||||||
final var b = new DefaultAstBuilder(new DefaultNodeFactory(tokenList));
|
final var b = new DefaultAstBuilder(new DefaultNodeFactory(tokenList));
|
||||||
final var cuNode = (CompilationUnitNode) b.build(parseResult.getCompilationUnitContext());
|
final var cuNode = b.buildCompilationUnit(parseResult.getCompilationUnitContext());
|
||||||
final var bodyNode = cuNode.getBodyNode();
|
final var bodyNode = cuNode.getBodyNode();
|
||||||
if (bodyNode == null) {
|
if (bodyNode == null) {
|
||||||
fail("No BodyNode was built for source: " + source);
|
fail("No BodyNode was built for source: " + source);
|
||||||
|
@ -5,7 +5,6 @@ import groowt.view.component.web.antlr.TokenList;
|
|||||||
import groowt.view.component.web.ast.DefaultAstBuilder;
|
import groowt.view.component.web.ast.DefaultAstBuilder;
|
||||||
import groowt.view.component.web.ast.DefaultNodeFactory;
|
import groowt.view.component.web.ast.DefaultNodeFactory;
|
||||||
import groowt.view.component.web.ast.node.BodyNode;
|
import groowt.view.component.web.ast.node.BodyNode;
|
||||||
import groowt.view.component.web.ast.node.CompilationUnitNode;
|
|
||||||
import groowt.view.component.web.ast.node.GStringBodyTextNode;
|
import groowt.view.component.web.ast.node.GStringBodyTextNode;
|
||||||
import groowt.view.component.web.transpile.GStringTranspiler;
|
import groowt.view.component.web.transpile.GStringTranspiler;
|
||||||
import org.codehaus.groovy.ast.expr.ClosureExpression;
|
import org.codehaus.groovy.ast.expr.ClosureExpression;
|
||||||
@ -34,7 +33,7 @@ public abstract class GStringTranspilerTests {
|
|||||||
final var tokenList = new TokenList(parseResult.getTokenStream());
|
final var tokenList = new TokenList(parseResult.getTokenStream());
|
||||||
final var nodeFactory = new DefaultNodeFactory(tokenList);
|
final var nodeFactory = new DefaultNodeFactory(tokenList);
|
||||||
final var astBuilder = new DefaultAstBuilder(nodeFactory);
|
final var astBuilder = new DefaultAstBuilder(nodeFactory);
|
||||||
final var cuNode = (CompilationUnitNode) astBuilder.build(parseResult.getCompilationUnitContext());
|
final var cuNode = astBuilder.buildCompilationUnit(parseResult.getCompilationUnitContext());
|
||||||
return Objects.requireNonNull(cuNode.getBodyNode());
|
return Objects.requireNonNull(cuNode.getBodyNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import groowt.view.component.web.antlr.ParserUtil;
|
|||||||
import groowt.view.component.web.antlr.TokenList;
|
import groowt.view.component.web.antlr.TokenList;
|
||||||
import groowt.view.component.web.ast.DefaultAstBuilder;
|
import groowt.view.component.web.ast.DefaultAstBuilder;
|
||||||
import groowt.view.component.web.ast.DefaultNodeFactory;
|
import groowt.view.component.web.ast.DefaultNodeFactory;
|
||||||
import groowt.view.component.web.ast.node.CompilationUnitNode;
|
|
||||||
import groowt.view.component.web.compiler.AnonymousWebViewComponent;
|
import groowt.view.component.web.compiler.AnonymousWebViewComponent;
|
||||||
import groowt.view.component.web.compiler.DefaultWebViewComponentTemplateCompileUnit;
|
import groowt.view.component.web.compiler.DefaultWebViewComponentTemplateCompileUnit;
|
||||||
import groowt.view.component.web.transpile.GroovyTranspiler;
|
import groowt.view.component.web.transpile.GroovyTranspiler;
|
||||||
@ -39,7 +38,7 @@ public abstract class GroovyTranspilerTests {
|
|||||||
final var parseResult = ParserUtil.parseCompilationUnit(source);
|
final var parseResult = ParserUtil.parseCompilationUnit(source);
|
||||||
final var tokenList = new TokenList(parseResult.getTokenStream());
|
final var tokenList = new TokenList(parseResult.getTokenStream());
|
||||||
final var astBuilder = new DefaultAstBuilder(new DefaultNodeFactory(tokenList));
|
final var astBuilder = new DefaultAstBuilder(new DefaultNodeFactory(tokenList));
|
||||||
final var cuNode = (CompilationUnitNode) astBuilder.build(parseResult.getCompilationUnitContext());
|
final var cuNode = astBuilder.buildCompilationUnit(parseResult.getCompilationUnitContext());
|
||||||
try {
|
try {
|
||||||
this.transpiler.transpile(
|
this.transpiler.transpile(
|
||||||
new DefaultComponentTemplateCompilerConfiguration(),
|
new DefaultComponentTemplateCompilerConfiguration(),
|
||||||
|
@ -3,8 +3,10 @@ package groowt.view.component.web.tools
|
|||||||
import groovy.transform.InheritConstructors
|
import groovy.transform.InheritConstructors
|
||||||
import groowt.view.component.web.antlr.*
|
import groowt.view.component.web.antlr.*
|
||||||
import groowt.view.component.web.antlr.AntlrUtil.ParseErrorCollector
|
import groowt.view.component.web.antlr.AntlrUtil.ParseErrorCollector
|
||||||
|
import groowt.view.component.web.antlr.WebViewComponentsParser.CompilationUnitContext
|
||||||
import groowt.view.component.web.util.ExtensionUtil
|
import groowt.view.component.web.util.ExtensionUtil
|
||||||
import org.antlr.v4.runtime.CharStreams
|
import org.antlr.v4.runtime.CharStreams
|
||||||
|
import org.antlr.v4.runtime.ConsoleErrorListener
|
||||||
|
|
||||||
@InheritConstructors
|
@InheritConstructors
|
||||||
final class ParseTreeFileMaker extends AbstractOutputFileMaker {
|
final class ParseTreeFileMaker extends AbstractOutputFileMaker {
|
||||||
@ -36,7 +38,7 @@ final class ParseTreeFileMaker extends AbstractOutputFileMaker {
|
|||||||
private boolean onErrors(
|
private boolean onErrors(
|
||||||
String name,
|
String name,
|
||||||
WebViewComponentsParser parser,
|
WebViewComponentsParser parser,
|
||||||
WebViewComponentsParser.CompilationUnitContext cu,
|
CompilationUnitContext cu,
|
||||||
ParseErrorCollector errors
|
ParseErrorCollector errors
|
||||||
) {
|
) {
|
||||||
def errorCount = errors.errorCount
|
def errorCount = errors.errorCount
|
||||||
@ -53,14 +55,35 @@ final class ParseTreeFileMaker extends AbstractOutputFileMaker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Tuple3<WebViewComponentsParser, WebViewComponentsParser.CompilationUnitContext, ParseErrorCollector> parse(
|
private Tuple3<WebViewComponentsParser, CompilationUnitContext, ParseErrorCollector> parse(File sourceFile) {
|
||||||
File sourceFile
|
|
||||||
) {
|
|
||||||
def input = CharStreams.fromFileName(sourceFile.toString())
|
def input = CharStreams.fromFileName(sourceFile.toString())
|
||||||
|
|
||||||
def lexer = new WebViewComponentsLexer(input)
|
def lexer = new WebViewComponentsLexer(input)
|
||||||
|
def lexerErrorListener = new LexerErrorListener()
|
||||||
|
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE)
|
||||||
|
lexer.addErrorListener(lexerErrorListener)
|
||||||
|
|
||||||
def tokenStream = new WebViewComponentsTokenStream(lexer)
|
def tokenStream = new WebViewComponentsTokenStream(lexer)
|
||||||
|
|
||||||
def parser = new WebViewComponentsParser(tokenStream)
|
def parser = new WebViewComponentsParser(tokenStream)
|
||||||
|
def parserErrorListener = new ParserErrorListener()
|
||||||
|
parser.removeErrorListener(ConsoleErrorListener.INSTANCE)
|
||||||
|
parser.addErrorListener(parserErrorListener)
|
||||||
|
|
||||||
def cu = parser.compilationUnit()
|
def cu = parser.compilationUnit()
|
||||||
|
|
||||||
|
if (!lexerErrorListener.errors.isEmpty()) {
|
||||||
|
println 'There were lexer errors.'
|
||||||
|
lexerErrorListener.errors.each { println LexerErrorKt.format(it) }
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parserErrorListener.errors.isEmpty()) {
|
||||||
|
println 'There were parser errors.'
|
||||||
|
parserErrorListener.errors.each { println ParserErrorKt.format(it) }
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
def errors = AntlrUtil.findErrorNodes(cu)
|
def errors = AntlrUtil.findErrorNodes(cu)
|
||||||
new Tuple3<>(parser, cu, errors)
|
new Tuple3<>(parser, cu, errors)
|
||||||
}
|
}
|
||||||
@ -71,12 +94,28 @@ final class ParseTreeFileMaker extends AbstractOutputFileMaker {
|
|||||||
println "Processing: $name"
|
println "Processing: $name"
|
||||||
boolean doneYet = false
|
boolean doneYet = false
|
||||||
while (!doneYet) {
|
while (!doneYet) {
|
||||||
def (parser, cu, errors) = this.parse(sourceFile)
|
final WebViewComponentsParser parser
|
||||||
|
final CompilationUnitContext cu
|
||||||
|
final ParseErrorCollector errors
|
||||||
|
try {
|
||||||
|
def result = this.parse(sourceFile)
|
||||||
|
if (result != null) {
|
||||||
|
(parser, cu, errors) = result
|
||||||
if (errors.isEmpty()) {
|
if (errors.isEmpty()) {
|
||||||
doneYet = this.onSuccess(name, parser, cu)
|
doneYet = this.onSuccess(name, parser, cu)
|
||||||
} else {
|
} else {
|
||||||
doneYet = this.onErrors(name, parser, cu, errors)
|
doneYet = this.onErrors(name, parser, cu, errors)
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
doneYet = !this.getYesNoInput('Would you like to try again? (y/n)', true)
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
println "There was an exception: $e"
|
||||||
|
if (this.verbose) {
|
||||||
|
e.printStackTrace()
|
||||||
|
}
|
||||||
|
doneYet = !this.getYesNoInput('Would you like to try again? (y/n)', true)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,10 @@
|
|||||||
package groowt.view.component.web.tools
|
package groowt.view.component.web.tools
|
||||||
|
|
||||||
import groovy.transform.InheritConstructors
|
import groovy.transform.InheritConstructors
|
||||||
import groowt.view.component.web.antlr.TokenUtil
|
import groowt.view.component.web.antlr.*
|
||||||
import groowt.view.component.web.antlr.WebViewComponentsLexer
|
|
||||||
import groowt.view.component.web.antlr.WebViewComponentsTokenStream
|
|
||||||
import groowt.view.component.web.util.ExtensionUtil
|
import groowt.view.component.web.util.ExtensionUtil
|
||||||
import org.antlr.v4.runtime.CharStreams
|
import org.antlr.v4.runtime.CharStreams
|
||||||
|
import org.antlr.v4.runtime.ConsoleErrorListener
|
||||||
import org.antlr.v4.runtime.Token
|
import org.antlr.v4.runtime.Token
|
||||||
|
|
||||||
@InheritConstructors
|
@InheritConstructors
|
||||||
@ -25,6 +24,18 @@ class TokensFileMaker extends AbstractOutputFileMaker {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected boolean onLexerErrors(String name, List<LexerError> errors) {
|
||||||
|
println "There were lexer errors in $name."
|
||||||
|
errors.each { println LexerError.format(it) }
|
||||||
|
if (this.getYesNoInput('Do you wish to try again? (y/n)', true)) {
|
||||||
|
println "Trying $name again..."
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
println "Skipping $name..."
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected boolean onException(String name, Exception e) {
|
protected boolean onException(String name, Exception e) {
|
||||||
println "There was an exception while tokenizing $name: $e.message"
|
println "There was an exception while tokenizing $name: $e.message"
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
@ -46,8 +57,16 @@ class TokensFileMaker extends AbstractOutputFileMaker {
|
|||||||
try {
|
try {
|
||||||
def input = CharStreams.fromString(sourceFile.getText())
|
def input = CharStreams.fromString(sourceFile.getText())
|
||||||
def lexer = new WebViewComponentsLexer(input)
|
def lexer = new WebViewComponentsLexer(input)
|
||||||
|
lexer.removeErrorListener(ConsoleErrorListener.INSTANCE)
|
||||||
|
def lexerErrorListener = new LexerErrorListener()
|
||||||
|
lexer.addErrorListener(lexerErrorListener)
|
||||||
def tokenStream = new WebViewComponentsTokenStream(lexer)
|
def tokenStream = new WebViewComponentsTokenStream(lexer)
|
||||||
doneYet = this.onSuccess(name, tokenStream.getAllTokensSkipEOF())
|
def allTokens = tokenStream.getAllTokensSkipEOF()
|
||||||
|
if (!lexerErrorListener.errors.isEmpty()) {
|
||||||
|
|
||||||
|
} else {
|
||||||
|
doneYet = this.onSuccess(name, allTokens)
|
||||||
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
doneYet = this.onException(name, e)
|
doneYet = this.onException(name, e)
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
package groowt.view.component.web.tools
|
package groowt.view.component.web.tools
|
||||||
|
|
||||||
import groowt.view.component.web.antlr.formatToken
|
import groowt.view.component.web.antlr.formatToken
|
||||||
import groowt.view.component.web.antlr.runLexerAllTokens
|
import groowt.view.component.web.antlr.runLexerAllTokensRaw
|
||||||
|
|
||||||
fun main(args: Array<String>) {
|
fun main(args: Array<String>) {
|
||||||
val options = processArgs(args)
|
val options = processArgs(args)
|
||||||
configureLog(options.logLevel)
|
configureLog(options.logLevel)
|
||||||
val input = getInput(options.source)
|
val input = getInput(options.source)
|
||||||
runLexerAllTokens(input).forEachIndexed { i, t -> println("$i: ${formatToken(t)}") }
|
runLexerAllTokensRaw(input).forEachIndexed { i, t -> println("$i: ${formatToken(t)}") }
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user