Component attr values should be working.
This commit is contained in:
parent
58e9f60530
commit
5ada84dfed
@ -23,6 +23,7 @@ channels {
|
||||
|
||||
@header {
|
||||
import java.util.Set;
|
||||
import groowt.view.component.web.WebViewComponentBugError;
|
||||
import static groowt.view.component.web.antlr.LexerSemanticPredicates.*;
|
||||
}
|
||||
|
||||
@ -109,6 +110,10 @@ channels {
|
||||
this.pushMode(GROOVY_CODE);
|
||||
}
|
||||
|
||||
private boolean inAttrComponent() {
|
||||
return this.peekMode(1) == COMPONENT_ATTR_VALUE;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------
|
||||
@ -262,11 +267,30 @@ TagStartError
|
||||
mode IN_TAG;
|
||||
|
||||
ComponentClose
|
||||
: GT -> popMode
|
||||
: GT
|
||||
{
|
||||
if (this.inAttrComponent() && this.attrComponentFinished()) {
|
||||
this.popMode();
|
||||
this.popMode();
|
||||
} else {
|
||||
this.popMode();
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
ComponentSelfClose
|
||||
: FS GT -> popMode
|
||||
: FS GT
|
||||
{
|
||||
if (this.inAttrComponent()) {
|
||||
this.exitAttrComponent();
|
||||
if (this.attrComponentFinished()) {
|
||||
this.popMode();
|
||||
this.popMode();
|
||||
}
|
||||
} else {
|
||||
this.popMode();
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
ConstructorOpen
|
||||
@ -313,10 +337,14 @@ ClosureAttrValueStart
|
||||
|
||||
ComponentAttrValueStart
|
||||
: LEFT_CURLY InTagNlws? { this.isNext('<') }?
|
||||
{
|
||||
this.enterAttrComponent();
|
||||
this.pushMode(COMPONENT_ATTR_VALUE);
|
||||
}
|
||||
;
|
||||
|
||||
ComponentAttrValueEnd
|
||||
: GT RIGHT_CURLY
|
||||
: InTagNlws? RIGHT_CURLY { this.popAttrComponent(); }
|
||||
;
|
||||
|
||||
InTagNlws
|
||||
@ -327,6 +355,85 @@ TagError
|
||||
: . -> channel(ERROR)
|
||||
;
|
||||
|
||||
// ----------------------------------------
|
||||
mode COMPONENT_ATTR_VALUE;
|
||||
|
||||
AttrComponentOpen
|
||||
: LT { !isAnyOf(this.getNextChar(), '/', '>') }? -> type(ComponentOpen), pushMode(TAG_START)
|
||||
;
|
||||
|
||||
AttrClosingComponentOpen
|
||||
: LT FS { !this.isNext('>') }?
|
||||
{
|
||||
this.exitAttrComponent();
|
||||
} -> type(ClosingComponentOpen), pushMode(TAG_START)
|
||||
;
|
||||
|
||||
AttrFragmentOpen
|
||||
: LT GT -> type(FragmentOpen)
|
||||
;
|
||||
|
||||
AttrFragmentClose
|
||||
: LT FS GT {
|
||||
this.exitAttrComponent();
|
||||
} -> type(FragmentClose), popMode
|
||||
;
|
||||
|
||||
AttrEqualsScriptletOpen
|
||||
: LT PERCENT EQ -> type(EqualsScriptletOpen), pushMode(GROOVY_CODE)
|
||||
;
|
||||
|
||||
AttrPlainScriptletOpen
|
||||
: LT PERCENT -> type(PlainScriptletOpen), pushMode(GROOVY_CODE)
|
||||
;
|
||||
|
||||
AttrDollarScriptletOpen
|
||||
: DOLLAR LEFT_CURLY {
|
||||
this.curlies.push(() -> {
|
||||
this.setType(DollarScriptletClose);
|
||||
this.popMode();
|
||||
});
|
||||
this.curlies.increment();
|
||||
this.setType(DollarScriptletOpen);
|
||||
this.pushMode(GROOVY_CODE);
|
||||
}
|
||||
;
|
||||
|
||||
AttrDollarReferenceStart
|
||||
: DOLLAR { isGStringIdentifierStartChar(this.getNextChar()) }?
|
||||
-> type(DollarReferenceStart), pushMode(IN_G_STRING_PATH)
|
||||
;
|
||||
|
||||
AttrQuestionTagOpen
|
||||
: LT QUESTION -> type(QuestionTagOpen)
|
||||
;
|
||||
|
||||
AttrQuestionTagClose
|
||||
: QUESTION GT -> type(QuestionTagClose)
|
||||
;
|
||||
|
||||
AttrHtmlCommentOpen
|
||||
: LT BANG TWO_DASH -> type(HtmlCommentOpen)
|
||||
;
|
||||
|
||||
AttrHtmlCommentClose
|
||||
: TWO_DASH GT -> type(HtmlCommentClose)
|
||||
;
|
||||
|
||||
AttrRawText
|
||||
: ( ~[-<$?]
|
||||
| MINUS { !this.isNext("->") }?
|
||||
| LT { canFollowLessThan(this.getNextCharAsString()) }?
|
||||
| LT BANG { !this.isNext("--") }?
|
||||
| DOLLAR { !(this.isNext('{') || isIdentifierStartChar(this.getNextChar())) }?
|
||||
| QUESTION { !this.isNext('>') }?
|
||||
)+ -> type(RawText)
|
||||
;
|
||||
|
||||
AttrError
|
||||
: . -> type(ErrorChar), channel(ERROR)
|
||||
;
|
||||
|
||||
// ----------------------------------------
|
||||
mode GROOVY_CODE;
|
||||
|
||||
@ -542,8 +649,11 @@ GStringPathEnd
|
||||
yield new StringContinueEndSpec();
|
||||
}
|
||||
}
|
||||
case COMPONENT_ATTR_VALUE -> new StringContinueEndSpec();
|
||||
case MAIN -> new StringContinueEndSpec();
|
||||
default -> throw new IllegalStateException("not a valid gString context: " + this.getModeName(this.peekMode(1)));
|
||||
default -> throw new IllegalStateException(
|
||||
"not a valid gStringPath context: " + this.getModeName(this.peekMode(1))
|
||||
);
|
||||
};
|
||||
switch (endSpec) {
|
||||
case StringContinueEndSpec ignored -> {
|
||||
|
@ -1,6 +1,7 @@
|
||||
package groowt.view.component.web.antlr;
|
||||
|
||||
import groovyjarjarantlr4.runtime.Token;
|
||||
import groowt.view.component.web.WebViewComponentBugError;
|
||||
import org.antlr.v4.runtime.CharStream;
|
||||
import org.antlr.v4.runtime.Lexer;
|
||||
import org.antlr.v4.runtime.atn.ATN;
|
||||
@ -13,6 +14,7 @@ import org.slf4j.LoggerFactory;
|
||||
import java.util.Arrays;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -57,6 +59,8 @@ public abstract class AbstractWebViewComponentsLexer extends Lexer {
|
||||
private boolean canPreamble = true;
|
||||
private boolean inPreamble;
|
||||
private boolean inConstructor;
|
||||
private Deque<AtomicBoolean> attrComponentFinishedStack = new LinkedList<>();
|
||||
|
||||
|
||||
public AbstractWebViewComponentsLexer(CharStream input) {
|
||||
super(input);
|
||||
@ -115,6 +119,14 @@ public abstract class AbstractWebViewComponentsLexer extends Lexer {
|
||||
this.inConstructor = inConstructor;
|
||||
}
|
||||
|
||||
public Deque<AtomicBoolean> getAttrComponentFinishedStack() {
|
||||
return this.attrComponentFinishedStack;
|
||||
}
|
||||
|
||||
public void setAttrComponentFinishedStack(Deque<AtomicBoolean> attrComponentFinishedStack) {
|
||||
this.attrComponentFinishedStack = attrComponentFinishedStack;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
this.curlies.clear();
|
||||
@ -122,6 +134,7 @@ public abstract class AbstractWebViewComponentsLexer extends Lexer {
|
||||
this.canPreamble = true;
|
||||
this.inPreamble = false;
|
||||
this.inConstructor = false;
|
||||
this.attrComponentFinishedStack = new LinkedList<>();
|
||||
super.reset();
|
||||
}
|
||||
|
||||
@ -204,6 +217,30 @@ public abstract class AbstractWebViewComponentsLexer extends Lexer {
|
||||
this.inConstructor = false;
|
||||
}
|
||||
|
||||
protected void enterAttrComponent() {
|
||||
this.attrComponentFinishedStack.push(new AtomicBoolean());
|
||||
}
|
||||
|
||||
protected void exitAttrComponent() {
|
||||
final AtomicBoolean attrComponentFinished = this.attrComponentFinishedStack.peek();
|
||||
if (attrComponentFinished == null) {
|
||||
throw new WebViewComponentBugError(new IllegalStateException());
|
||||
}
|
||||
attrComponentFinished.set(true);
|
||||
}
|
||||
|
||||
protected boolean attrComponentFinished() {
|
||||
final AtomicBoolean attrComponentFinished = this.attrComponentFinishedStack.peek();
|
||||
if (attrComponentFinished == null) {
|
||||
throw new WebViewComponentBugError(new IllegalStateException());
|
||||
}
|
||||
return attrComponentFinished.get();
|
||||
}
|
||||
|
||||
protected void popAttrComponent() {
|
||||
this.attrComponentFinishedStack.pop();
|
||||
}
|
||||
|
||||
protected String getNextCharsAsString(int numberOfChars) {
|
||||
final var b = new StringBuilder();
|
||||
for (int i = 1; i <= numberOfChars; i++) {
|
||||
@ -224,6 +261,10 @@ public abstract class AbstractWebViewComponentsLexer extends Lexer {
|
||||
return this._input.LA(1);
|
||||
}
|
||||
|
||||
protected boolean isPrevious(char test) {
|
||||
return this._input.LA(-2) == test;
|
||||
}
|
||||
|
||||
protected boolean isNext(char test) {
|
||||
return this._input.LA(1) == test;
|
||||
}
|
||||
|
@ -0,0 +1 @@
|
||||
<Test transform={<p>$it</p>} />
|
@ -0,0 +1 @@
|
||||
<Test transform={<Test transform={<Test />} />} />
|
@ -0,0 +1 @@
|
||||
<Test transform={<Test transform={<p>$it</p>} />} />
|
@ -0,0 +1 @@
|
||||
<Test transform={<Test />} />
|
@ -0,0 +1 @@
|
||||
<Test test={ <Test /> } />
|
@ -0,0 +1,27 @@
|
||||
0: ComponentOpen[1,1](<)
|
||||
1: TypedIdentifier[1,2](Test)
|
||||
2: Nlws[1,6]( )
|
||||
3: AttributeIdentifier[1,7](transform)
|
||||
4: Equals[1,16](=)
|
||||
5: ComponentAttrValueStart[1,17]({)
|
||||
6: ComponentOpen[1,18](<)
|
||||
7: TypedIdentifier[1,19](Test)
|
||||
8: Nlws[1,23]( )
|
||||
9: AttributeIdentifier[1,24](transform)
|
||||
10: Equals[1,33](=)
|
||||
11: ComponentAttrValueStart[1,34]({)
|
||||
12: ComponentOpen[1,35](<)
|
||||
13: StringIdentifier[1,36](p)
|
||||
14: ComponentClose[1,37](>)
|
||||
15: DollarReferenceStart[1,38]($)
|
||||
16: GroovyCode[1,39](it)
|
||||
17: ClosingComponentOpen[1,41](</)
|
||||
18: StringIdentifier[1,43](p)
|
||||
19: ComponentClose[1,44](>)
|
||||
20: ComponentAttrValueEnd[1,45](})
|
||||
21: Nlws[1,46]( )
|
||||
22: ComponentSelfClose[1,47](/>)
|
||||
23: ComponentAttrValueEnd[1,49](})
|
||||
24: Nlws[1,50]( )
|
||||
25: ComponentSelfClose[1,51](/>)
|
||||
26: RawText[1,53](\n)
|
@ -0,0 +1,23 @@
|
||||
0: ComponentOpen[1,1](<)
|
||||
1: TypedIdentifier[1,2](Test)
|
||||
2: Nlws[1,6]( )
|
||||
3: AttributeIdentifier[1,7](transform)
|
||||
4: Equals[1,16](=)
|
||||
5: ComponentAttrValueStart[1,17]({)
|
||||
6: ComponentOpen[1,18](<)
|
||||
7: TypedIdentifier[1,19](Test)
|
||||
8: Nlws[1,23]( )
|
||||
9: AttributeIdentifier[1,24](transform)
|
||||
10: Equals[1,33](=)
|
||||
11: ComponentAttrValueStart[1,34]({)
|
||||
12: ComponentOpen[1,35](<)
|
||||
13: TypedIdentifier[1,36](Test)
|
||||
14: Nlws[1,40]( )
|
||||
15: ComponentSelfClose[1,41](/>)
|
||||
16: ComponentAttrValueEnd[1,43](})
|
||||
17: Nlws[1,44]( )
|
||||
18: ComponentSelfClose[1,45](/>)
|
||||
19: ComponentAttrValueEnd[1,47](})
|
||||
20: Nlws[1,48]( )
|
||||
21: ComponentSelfClose[1,49](/>)
|
||||
22: RawText[1,51](\n)
|
@ -0,0 +1,14 @@
|
||||
0: ComponentOpen[1,1](<)
|
||||
1: TypedIdentifier[1,2](Test)
|
||||
2: Nlws[1,6]( )
|
||||
3: AttributeIdentifier[1,7](transform)
|
||||
4: Equals[1,16](=)
|
||||
5: ComponentAttrValueStart[1,17]({)
|
||||
6: ComponentOpen[1,18](<)
|
||||
7: TypedIdentifier[1,19](Test)
|
||||
8: Nlws[1,23]( )
|
||||
9: ComponentSelfClose[1,24](/>)
|
||||
10: ComponentAttrValueEnd[1,26](})
|
||||
11: Nlws[1,27]( )
|
||||
12: ComponentSelfClose[1,28](/>)
|
||||
13: RawText[1,30](\n)
|
@ -0,0 +1,14 @@
|
||||
0: ComponentOpen[1,1](<)
|
||||
1: TypedIdentifier[1,2](Test)
|
||||
2: Nlws[1,6]( )
|
||||
3: AttributeIdentifier[1,7](test)
|
||||
4: Equals[1,11](=)
|
||||
5: ComponentAttrValueStart[1,12]({ )
|
||||
6: ComponentOpen[1,14](<)
|
||||
7: TypedIdentifier[1,15](Test)
|
||||
8: Nlws[1,19]( )
|
||||
9: ComponentSelfClose[1,20](/>)
|
||||
10: ComponentAttrValueEnd[1,22]( })
|
||||
11: Nlws[1,24]( )
|
||||
12: ComponentSelfClose[1,25](/>)
|
||||
13: RawText[1,27](\n)
|
@ -0,0 +1,18 @@
|
||||
0: ComponentOpen[1,1](<)
|
||||
1: TypedIdentifier[1,2](Test)
|
||||
2: Nlws[1,6]( )
|
||||
3: AttributeIdentifier[1,7](transform)
|
||||
4: Equals[1,16](=)
|
||||
5: ComponentAttrValueStart[1,17]({)
|
||||
6: ComponentOpen[1,18](<)
|
||||
7: StringIdentifier[1,19](p)
|
||||
8: ComponentClose[1,20](>)
|
||||
9: DollarReferenceStart[1,21]($)
|
||||
10: GroovyCode[1,22](it)
|
||||
11: ClosingComponentOpen[1,24](</)
|
||||
12: StringIdentifier[1,26](p)
|
||||
13: ComponentClose[1,27](>)
|
||||
14: ComponentAttrValueEnd[1,28](})
|
||||
15: Nlws[1,29]( )
|
||||
16: ComponentSelfClose[1,30](/>)
|
||||
17: RawText[1,32](\n)
|
@ -0,0 +1 @@
|
||||
<Test test={<p>$it</p>} />
|
@ -0,0 +1 @@
|
||||
<Test test={<Test test={<Test />} />} />
|
@ -0,0 +1 @@
|
||||
<Test test={<Test test={<p>$it</p>} />} />
|
@ -0,0 +1,55 @@
|
||||
compilationUnit[1,1..2,1]
|
||||
body[1,1..1,43]
|
||||
component[1,1..1,43]
|
||||
selfClosingComponent[1,1..1,43]
|
||||
ComponentOpen[1,1](<)
|
||||
componentArgs[1,2..1,39]
|
||||
componentType[1,2..1,6]
|
||||
TypedIdentifier[1,2](Test)
|
||||
attr[1,7..1,39]
|
||||
keyValueAttr[1,7..1,39]
|
||||
AttributeIdentifier[1,7](test)
|
||||
Equals[1,11](=)
|
||||
value[1,12..1,39]
|
||||
componentAttrValue[1,12..1,39]
|
||||
ComponentAttrValueStart[1,12]({)
|
||||
component[1,13..1,39]
|
||||
selfClosingComponent[1,13..1,39]
|
||||
ComponentOpen[1,13](<)
|
||||
componentArgs[1,14..1,35]
|
||||
componentType[1,14..1,18]
|
||||
TypedIdentifier[1,14](Test)
|
||||
attr[1,19..1,35]
|
||||
keyValueAttr[1,19..1,35]
|
||||
AttributeIdentifier[1,19](test)
|
||||
Equals[1,23](=)
|
||||
value[1,24..1,35]
|
||||
componentAttrValue[1,24..1,35]
|
||||
ComponentAttrValueStart[1,24]({)
|
||||
component[1,25..1,34]
|
||||
componentWithChildren[1,25..1,34]
|
||||
openComponent[1,25..1,27]
|
||||
ComponentOpen[1,25](<)
|
||||
componentArgs[1,26..1,26]
|
||||
componentType[1,26..1,26]
|
||||
StringIdentifier[1,26](p)
|
||||
ComponentClose[1,27](>)
|
||||
body[1,28..1,31]
|
||||
bodyText[1,28..1,31]
|
||||
bodyTextGroovyElement[1,28..1,31]
|
||||
dollarReference[1,28..1,31]
|
||||
DollarReferenceStart[1,28]($)
|
||||
GroovyCode[1,29](it)
|
||||
closingComponent[1,31..1,34]
|
||||
ClosingComponentOpen[1,31](</)
|
||||
componentType[1,33..1,33]
|
||||
StringIdentifier[1,33](p)
|
||||
ComponentClose[1,34](>)
|
||||
ComponentAttrValueEnd[1,35](})
|
||||
ComponentSelfClose[1,37](/>)
|
||||
ComponentAttrValueEnd[1,39](})
|
||||
ComponentSelfClose[1,41](/>)
|
||||
bodyText[1,43..1,43]
|
||||
text[1,43..1,43]
|
||||
RawText[1,43](\n)
|
||||
EOF[2,1](<EOF>)
|
@ -0,0 +1,43 @@
|
||||
compilationUnit[1,1..2,1]
|
||||
body[1,1..1,41]
|
||||
component[1,1..1,41]
|
||||
selfClosingComponent[1,1..1,41]
|
||||
ComponentOpen[1,1](<)
|
||||
componentArgs[1,2..1,37]
|
||||
componentType[1,2..1,6]
|
||||
TypedIdentifier[1,2](Test)
|
||||
attr[1,7..1,37]
|
||||
keyValueAttr[1,7..1,37]
|
||||
AttributeIdentifier[1,7](test)
|
||||
Equals[1,11](=)
|
||||
value[1,12..1,37]
|
||||
componentAttrValue[1,12..1,37]
|
||||
ComponentAttrValueStart[1,12]({)
|
||||
component[1,13..1,37]
|
||||
selfClosingComponent[1,13..1,37]
|
||||
ComponentOpen[1,13](<)
|
||||
componentArgs[1,14..1,33]
|
||||
componentType[1,14..1,18]
|
||||
TypedIdentifier[1,14](Test)
|
||||
attr[1,19..1,33]
|
||||
keyValueAttr[1,19..1,33]
|
||||
AttributeIdentifier[1,19](test)
|
||||
Equals[1,23](=)
|
||||
value[1,24..1,33]
|
||||
componentAttrValue[1,24..1,33]
|
||||
ComponentAttrValueStart[1,24]({)
|
||||
component[1,25..1,33]
|
||||
selfClosingComponent[1,25..1,33]
|
||||
ComponentOpen[1,25](<)
|
||||
componentArgs[1,26..1,30]
|
||||
componentType[1,26..1,30]
|
||||
TypedIdentifier[1,26](Test)
|
||||
ComponentSelfClose[1,31](/>)
|
||||
ComponentAttrValueEnd[1,33](})
|
||||
ComponentSelfClose[1,35](/>)
|
||||
ComponentAttrValueEnd[1,37](})
|
||||
ComponentSelfClose[1,39](/>)
|
||||
bodyText[1,41..1,41]
|
||||
text[1,41..1,41]
|
||||
RawText[1,41](\n)
|
||||
EOF[2,1](<EOF>)
|
@ -0,0 +1,40 @@
|
||||
compilationUnit[1,1..2,1]
|
||||
body[1,1..1,27]
|
||||
component[1,1..1,27]
|
||||
selfClosingComponent[1,1..1,27]
|
||||
ComponentOpen[1,1](<)
|
||||
componentArgs[1,2..1,23]
|
||||
componentType[1,2..1,6]
|
||||
TypedIdentifier[1,2](Test)
|
||||
attr[1,7..1,23]
|
||||
keyValueAttr[1,7..1,23]
|
||||
AttributeIdentifier[1,7](test)
|
||||
Equals[1,11](=)
|
||||
value[1,12..1,23]
|
||||
componentAttrValue[1,12..1,23]
|
||||
ComponentAttrValueStart[1,12]({)
|
||||
component[1,13..1,22]
|
||||
componentWithChildren[1,13..1,22]
|
||||
openComponent[1,13..1,15]
|
||||
ComponentOpen[1,13](<)
|
||||
componentArgs[1,14..1,14]
|
||||
componentType[1,14..1,14]
|
||||
StringIdentifier[1,14](p)
|
||||
ComponentClose[1,15](>)
|
||||
body[1,16..1,19]
|
||||
bodyText[1,16..1,19]
|
||||
bodyTextGroovyElement[1,16..1,19]
|
||||
dollarReference[1,16..1,19]
|
||||
DollarReferenceStart[1,16]($)
|
||||
GroovyCode[1,17](it)
|
||||
closingComponent[1,19..1,22]
|
||||
ClosingComponentOpen[1,19](</)
|
||||
componentType[1,21..1,21]
|
||||
StringIdentifier[1,21](p)
|
||||
ComponentClose[1,22](>)
|
||||
ComponentAttrValueEnd[1,23](})
|
||||
ComponentSelfClose[1,25](/>)
|
||||
bodyText[1,27..1,27]
|
||||
text[1,27..1,27]
|
||||
RawText[1,27](\n)
|
||||
EOF[2,1](<EOF>)
|
Loading…
Reference in New Issue
Block a user