Skip to content

Commit

Permalink
Add antlr parsing of expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
Sheikah45 committed May 16, 2024
1 parent b48d511 commit 5129a5b
Show file tree
Hide file tree
Showing 20 changed files with 2,848 additions and 60 deletions.
16 changes: 16 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions fx2j-parser/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
plugins {
id("io.github.sheikah45.fx2j.conventions-publish")
id("io.github.sheikah45.fx2j.conventions-library")
}

dependencies {
implementation("org.antlr:antlr4:4.13.1")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
grammar BindExpression;
@header {
package io.github.sheikah45.fx2j.parser.antlr;
}

expression
: base=expression '.' property=Identifier # propertyRead
| base=expression '.' method=Identifier
'('
(args+=expression (',' args+=expression)*)?
')' # methodCall
| collection=expression '[' accessor=expression ']' # collectionAccess
| '!' base=expression # invert
| '-' base=expression # negate
| left=expression '*' right=expression # multiply
| left=expression '/' right=expression # divide
| left=expression '%' right=expression # remainder
| left=expression '+' right=expression # add
| left=expression '-' right=expression # subtract
| left=expression '>' right=expression # greaterThan
| left=expression '>=' right=expression # greaterThanEqual
| left=expression '<' right=expression # lessThan
| left=expression '<=' right=expression # lessThanEqual
| left=expression '==' right=expression # equality
| left=expression '!=' right=expression # inequality
| left=expression '&&' right=expression # and
| left=expression '||' right=expression # or
| '(' inside=expression ')' # enclosed
| Identifier # variable
| String # stringLiteral
| Decimal # decimalLiteral
| Fractional # fractionalLiteral
| 'null' # nullLiteral
| 'true' # trueLiteral
| 'false' # falseLiteral
;

String
: ('"' StringCharacters? '"')
| ('\'' StringCharacters? '\'')
;

Decimal
: [0-9]+
;

Fractional
: Decimal '.' Decimal? ExponentPart?
| '.' Decimal ExponentPart?
| Decimal ExponentPart
| Decimal
;

Identifier
: [a-zA-Z][a-zA-Z0-9]*
;

fragment
StringCharacters
: ~["'\\]+
;
fragment
ExponentPart
: [eE][+-]?Decimal
;
Whitespace: [ \n\t\r]+ -> skip;
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package io.github.sheikah45.fx2j.parser;

import io.github.sheikah45.fx2j.parser.antlr.BindExpressionLexer;
import io.github.sheikah45.fx2j.parser.antlr.BindExpressionParser;
import io.github.sheikah45.fx2j.parser.antlr.BindExpressionVisitorImpl;
import io.github.sheikah45.fx2j.parser.attribute.ControllerAttribute;
import io.github.sheikah45.fx2j.parser.attribute.EventHandlerAttribute;
import io.github.sheikah45.fx2j.parser.attribute.FxmlAttribute;
import io.github.sheikah45.fx2j.parser.attribute.IdAttribute;
import io.github.sheikah45.fx2j.parser.attribute.InstancePropertyAttribute;
import io.github.sheikah45.fx2j.parser.attribute.NameSpaceAttribute;
import io.github.sheikah45.fx2j.parser.attribute.StaticPropertyAttribute;
import io.github.sheikah45.fx2j.parser.element.ClassInstanceElement;
import io.github.sheikah45.fx2j.parser.element.ConstantElement;
Expand All @@ -24,6 +28,9 @@
import io.github.sheikah45.fx2j.parser.element.ValueElement;
import io.github.sheikah45.fx2j.parser.property.Value;
import io.github.sheikah45.fx2j.parser.utils.StringUtils;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CodePointCharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
Expand All @@ -35,6 +42,7 @@

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
Expand Down Expand Up @@ -96,11 +104,11 @@ private static Value createPropertyValue(Element element) {
}

return commonAttribute;
}).map(Value.Attribute::new).forEach(values::add);
}).map(io.github.sheikah45.fx2j.parser.property.Value.Attribute::new).forEach(values::add);

createChildren(element)
.stream()
.map(Value.Element::new)
.map(io.github.sheikah45.fx2j.parser.property.Value.Element::new)
.forEach(values::add);

Value.Single innerValue = createPropertyValue(retrieveInnerText(element));
Expand All @@ -126,7 +134,6 @@ private static List<FxmlAttribute> createAttributes(Element element) {
.mapToObj(attributesNodeMap::item)
.filter(Attr.class::isInstance)
.map(Attr.class::cast)
.filter(attr -> !attr.getNodeName().startsWith("xmlns"))
.map(FxmlParser::createFxmlAttribute)
.toList();
}
Expand Down Expand Up @@ -239,10 +246,32 @@ private static IncludeElement createIncludeElement(Element element) {
return new IncludeElement(source, resources, charset, createContent(element));
}

private static Value.Single createPropertyValue(String value) {
return switch (value) {
case String val when val.startsWith("@") -> new Value.Location(Path.of(val.substring(1)));
case String val when val.startsWith("%") -> new Value.Resource(val.substring(1));
case String val when val.matches("\\$\\{.*}") -> createExpressionValue(val);
case String val when val.startsWith("$") -> new Value.Reference(val.substring(1));
case String val when val.startsWith("\\") -> new Value.Literal(val.substring(1));
case String val when val.isBlank() -> new Value.Empty();
case String val -> new Value.Literal(val);
};
}

private static Value.Expression createExpressionValue(String val) {
CodePointCharStream charStream = CharStreams.fromString(val.substring(2, val.length() - 1));
BindExpressionLexer expressionLexer = new BindExpressionLexer(charStream);
CommonTokenStream commonTokenStream = new CommonTokenStream(expressionLexer);
BindExpressionParser expressionParser = new BindExpressionParser(commonTokenStream);
return expressionParser.expression().accept(new BindExpressionVisitorImpl());
}

private static FxmlAttribute createFxmlAttribute(Attr attr) {
return switch (attr.getName()) {
case "fx:id" -> new IdAttribute(attr.getValue());
case "fx:controller" -> new ControllerAttribute(attr.getValue());
case String name when name.startsWith("xmlns:") ->
new NameSpaceAttribute(name.substring(6), URI.create(attr.getValue()));
case String name when name.startsWith("on") ->
new EventHandlerAttribute(name, createEventHandler(attr.getValue()));
case String name when name.matches("(\\w*\\.)*[A-Z]\\w*\\.[a-z]\\w*") -> {
Expand All @@ -254,18 +283,6 @@ yield new StaticPropertyAttribute(name.substring(0, separatorIndex), name.substr
};
}

private static Value.Single createPropertyValue(String value) {
return switch (value) {
case String val when val.startsWith("@") -> new Value.Location(Path.of(val.substring(1)));
case String val when val.startsWith("%") -> new Value.Resource(val.substring(1));
case String val when val.matches("\\$\\{.*}") -> new Value.Expression(val.substring(2, val.length() - 1));
case String val when val.startsWith("$") -> new Value.Reference(val.substring(1));
case String val when val.startsWith("\\") -> new Value.Literal(val.substring(1));
case String val when val.isBlank() -> new Value.Empty();
case String val -> new Value.Literal(val);
};
}

private static Value.Handler createEventHandler(String value) {
return switch (value) {
case String val when val.startsWith("#") -> new Value.Method(val.substring(1));
Expand Down
Loading

0 comments on commit 5129a5b

Please sign in to comment.