Skip to content

Commit 88e3534

Browse files
committed
improve the ability for API users to configure the caching behavior of the ASTParser (and by extension the *ASTTransformers),
added two new parser classes: one that uses a different (smaller) cache for translation units and one that doesn't cache translation units at all, added the ability to change which parser and AST build cache is used by an ASTParser, and removed methods that are now pointless
1 parent 0071d43 commit 88e3534

File tree

8 files changed

+128
-41
lines changed

8 files changed

+128
-41
lines changed

glsl-transformer/src/main/java/io/github/douira/glsl_transformer/ast/data/TypedTreeCache.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import io.github.douira.glsl_transformer.util.LRUCache;
99

1010
public class TypedTreeCache<V> extends LRUCache<CacheKey, V> {
11-
private static final int defaultCacheSize = 400;
11+
private static final int DEFAULT_CACHE_SIZE = 400;
1212

1313
public TypedTreeCache(int maxSize, float loadFactor) {
1414
super(maxSize, loadFactor);
@@ -19,7 +19,7 @@ public TypedTreeCache(int maxSize) {
1919
}
2020

2121
public TypedTreeCache() {
22-
super(defaultCacheSize);
22+
super(DEFAULT_CACHE_SIZE);
2323
}
2424

2525
public static class CacheKey {
@@ -55,11 +55,8 @@ public boolean equals(Object obj) {
5555
} else if (!input.equals(other.input))
5656
return false;
5757
if (ruleType == null) {
58-
if (other.ruleType != null)
59-
return false;
60-
} else if (!ruleType.equals(other.ruleType))
61-
return false;
62-
return true;
58+
return other.ruleType == null;
59+
} else return ruleType.equals(other.ruleType);
6360
}
6461
}
6562

glsl-transformer/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTParser.java

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ public static ASTParser _getInternalInstance() {
2727
return INSTANCE;
2828
}
2929

30-
private EnhancedParser parser = new CachingParser();
31-
private TypedTreeCache<ASTNode> buildCache = new TypedTreeCache<>();
30+
private EnhancedParser parser;
31+
private TypedTreeCache<ASTNode> buildCache;
3232
private ASTCacheStrategy astCacheStrategy = ASTCacheStrategy.ALL_EXCLUDING_TRANSLATION_UNIT;
3333
private boolean parseLineDirectives = false;
3434

@@ -40,47 +40,66 @@ public enum ASTCacheStrategy {
4040

4141
public enum ParsingCacheStrategy {
4242
ALL,
43+
TWO_TIER,
44+
ALL_EXCLUDING_TRANSLATION_UNIT,
4345
NONE
4446
}
4547

46-
public void setBuildCacheSizeAndClear(int size) {
47-
buildCache = new TypedTreeCache<>(size);
48+
public ASTParser(EnhancedParser parser, TypedTreeCache<ASTNode> buildCache) {
49+
this.parser = parser;
50+
this.buildCache = buildCache;
4851
}
4952

50-
public void setParseCacheSizeAndClear(int size) {
51-
if (parser instanceof CachingParser cachingParser) {
52-
cachingParser.setParseCacheSizeAndClear(size);
53-
}
53+
public ASTParser() {
54+
this(new CachingParser(), new TypedTreeCache<>());
55+
}
56+
57+
public void setParser(EnhancedParser parser) {
58+
this.parser = parser;
59+
}
60+
61+
public void setBuildCache(TypedTreeCache<ASTNode> buildCache) {
62+
this.buildCache = buildCache;
5463
}
5564

5665
/**
5766
* Sets the AST cache strategy. If set to ALL, the parser will cache all
5867
* generated ASTs. If set to ALL_EXCLUDING_TRANSLATION_UNIT, the parser will
5968
* cache all generated ASTs except for the TranslationUnit. If set to NONE, the
6069
* parser will cache nothing.
61-
*
70+
*
6271
* @param astCacheStrategy the AST cache strategy
6372
*/
6473
public void setASTCacheStrategy(ASTCacheStrategy astCacheStrategy) {
6574
this.astCacheStrategy = astCacheStrategy;
6675
}
6776

6877
/**
69-
* Sets the parsing cache strategy. If set to ALL, the parser will cache all
70-
* parsed strings. If set to NONE, the parser will cache nothing. Only
71-
* influences how the CST is parsed from the input and not the AST.
72-
*
78+
* Sets the parsing cache strategy. If set to {@link ParsingCacheStrategy#ALL},
79+
* the parser will cache all parsed strings. If set to
80+
* {@link ParsingCacheStrategy#TWO_TIER}, the parser will cache all parsed strings
81+
* in a two-tier cache. If set to {@link ParsingCacheStrategy#NONE},
82+
* the parser will cache nothing. If set to
83+
* {@link ParsingCacheStrategy#ALL_EXCLUDING_TRANSLATION_UNIT}, the parser
84+
* will cache all parsed strings except for the {@link TranslationUnit}.
85+
* This only influences how the CST is parsed from the input and not the AST.
86+
*
7387
* @param parsingCacheStrategy the parsing cache strategy
7488
*/
7589
public void setParsingCacheStrategy(ParsingCacheStrategy parsingCacheStrategy) {
76-
parser = parsingCacheStrategy == ParsingCacheStrategy.ALL ? new CachingParser() : new EnhancedParser();
90+
parser = switch (parsingCacheStrategy) {
91+
case ALL -> new CachingParser();
92+
case TWO_TIER -> new TwoTierCachingParser();
93+
case ALL_EXCLUDING_TRANSLATION_UNIT -> new TranslationUnitFilterCachingParser();
94+
case NONE -> new EnhancedParser();
95+
};
7796
}
7897

7998
/**
8099
* Sets whether the AST parser should handle line directives. If set to true,
81100
* the parser will parse line directives and add them to the AST. If set to
82101
* false, the parser will ignore line directives and not add them to the AST.
83-
*
102+
*
84103
* @param parseLineDirectives whether the parser should parse line directives
85104
*/
86105
public void setParseLineDirectives(boolean parseLineDirectives) {
@@ -179,7 +198,7 @@ public <C extends ParserRuleContext, N extends ASTNode> N parseNode(
179198
String input) {
180199
if (astCacheStrategy == ASTCacheStrategy.NONE
181200
|| astCacheStrategy == ASTCacheStrategy.ALL_EXCLUDING_TRANSLATION_UNIT
182-
&& parseShape.ruleType == TranslationUnitContext.class) {
201+
&& parseShape.ruleType == TranslationUnitContext.class) {
183202
try {
184203
var parsed = parser.parse(input, parseShape);
185204
setBuilderTokenStream();

glsl-transformer/src/main/java/io/github/douira/glsl_transformer/ast/transform/ASTTransformer.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@
22

33
import java.util.Objects;
44

5+
import io.github.douira.glsl_transformer.ast.data.TypedTreeCache;
56
import io.github.douira.glsl_transformer.ast.node.TranslationUnit;
7+
import io.github.douira.glsl_transformer.ast.node.abstract_node.ASTNode;
68
import io.github.douira.glsl_transformer.ast.node.expression.Expression;
79
import io.github.douira.glsl_transformer.ast.node.external_declaration.ExternalDeclaration;
810
import io.github.douira.glsl_transformer.ast.node.statement.Statement;
911
import io.github.douira.glsl_transformer.ast.print.PrintType;
1012
import io.github.douira.glsl_transformer.ast.query.*;
13+
import io.github.douira.glsl_transformer.parser.EnhancedParser;
1114
import io.github.douira.glsl_transformer.token_filter.TokenFilter;
1215

1316
/**

glsl-transformer/src/main/java/io/github/douira/glsl_transformer/parser/CachingParser.java

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,16 @@
1414
* is safe to use this.
1515
*/
1616
public class CachingParser extends EnhancedParser {
17-
record CacheContents(ParserRuleContext parseTree, BufferedTokenStream tokenStream) {
17+
protected record CacheContents(ParserRuleContext parseTree, BufferedTokenStream tokenStream) {
1818
}
1919

20-
private TypedTreeCache<CacheContents> parseCache;
20+
protected TypedTreeCache<CacheContents> parseCache;
2121

2222
public CachingParser(boolean throwParseErrors, int cacheSize) {
2323
super(throwParseErrors);
2424
parseCache = new TypedTreeCache<>(cacheSize);
2525
}
2626

27-
public CachingParser(int cacheSize) {
28-
parseCache = new TypedTreeCache<>(cacheSize);
29-
}
30-
31-
public CachingParser(boolean throwParseErrors) {
32-
super(throwParseErrors);
33-
parseCache = new TypedTreeCache<>();
34-
}
35-
3627
public CachingParser() {
3728
parseCache = new TypedTreeCache<>();
3829
}
@@ -49,19 +40,27 @@ public <C extends ParserRuleContext> C parse(
4940
}
5041

5142
@Override
52-
@SuppressWarnings("unchecked")
5343
public <C extends ParserRuleContext> C parse(
5444
String str,
5545
ParserRuleContext parent,
5646
ParseShape<C, ?> parseShape) {
57-
var result = parseCache.cachedGet(str, parseShape.ruleType,
47+
return parseWithCache(str, parent, parseShape, parseCache);
48+
}
49+
50+
@SuppressWarnings("unchecked")
51+
protected <C extends ParserRuleContext> C parseWithCache(
52+
String str,
53+
ParserRuleContext parent,
54+
ParseShape<C, ?> parseShape,
55+
TypedTreeCache<CacheContents> cache) {
56+
var result = cache.cachedGet(str, parseShape.ruleType,
5857
() -> {
5958
var node = parse(str, parent, parseShape.parseMethod);
6059
return new CacheContents(node, getTokenStream());
6160
});
6261
if (result != null) {
6362
// so that when a cache hit happens, the getTokenStream method returns the
64-
// correct token stream 
63+
// correct token stream
6564
tokenStream = result.tokenStream;
6665
return (C) result.parseTree;
6766
} else {

glsl-transformer/src/main/java/io/github/douira/glsl_transformer/parser/EnhancedParser.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ public enum ParsingStrategy {
8585
* It filters the tokens coming from the lexer before the parser consumes them.
8686
* The contained token filter can be {@code null} if no filter is to be used.
8787
*/
88-
private FilterTokenSource tokenSource = new FilterTokenSource(lexer);
88+
private final FilterTokenSource tokenSource = new FilterTokenSource(lexer);
8989

9090
/**
9191
* Creates a new parser and specifies if parse errors should be
@@ -196,13 +196,13 @@ public TranslationUnitContext parse(String str) {
196196
public <C extends ParserRuleContext> C parse(
197197
String str,
198198
Function<GLSLParser, C> parseMethod) {
199-
return parse(str, (ParserRuleContext) null, parseMethod);
199+
return parse(str, null, parseMethod);
200200
}
201201

202202
public <C extends ParserRuleContext> C parse(
203203
String str,
204204
ParseShape<C, ?> parseShape) {
205-
return parse(str, (ParserRuleContext) null, parseShape.parseMethod);
205+
return parse(str, null, parseShape.parseMethod);
206206
}
207207

208208
/**
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package io.github.douira.glsl_transformer.parser;
2+
3+
import io.github.douira.glsl_transformer.GLSLParser;
4+
import org.antlr.v4.runtime.ParserRuleContext;
5+
6+
public class TranslationUnitFilterCachingParser extends CachingParser {
7+
public TranslationUnitFilterCachingParser(boolean throwParseErrors, int cacheSize) {
8+
super(throwParseErrors, cacheSize);
9+
}
10+
11+
public TranslationUnitFilterCachingParser() {
12+
super();
13+
}
14+
15+
@Override
16+
public <C extends ParserRuleContext> C parse(String str, ParserRuleContext parent, ParseShape<C, ?> parseShape) {
17+
if (parseShape.ruleType == GLSLParser.TranslationUnitContext.class) {
18+
return parse(str, parent, parseShape);
19+
}
20+
return super.parse(str, parent, parseShape);
21+
}
22+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package io.github.douira.glsl_transformer.parser;
2+
3+
import io.github.douira.glsl_transformer.GLSLParser;
4+
import io.github.douira.glsl_transformer.ast.data.TypedTreeCache;
5+
import io.github.douira.glsl_transformer.token_filter.TokenFilter;
6+
import org.antlr.v4.runtime.ParserRuleContext;
7+
8+
public class TwoTierCachingParser extends CachingParser {
9+
private static final int DEFAULT_SECONDARY_CACHE_SIZE = 10;
10+
11+
protected TypedTreeCache<CacheContents> secondaryCache;
12+
13+
public TwoTierCachingParser() {
14+
super();
15+
secondaryCache = new TypedTreeCache<>(DEFAULT_SECONDARY_CACHE_SIZE);
16+
}
17+
18+
public TwoTierCachingParser(boolean throwParseErrors, int cacheSize, int secondaryCacheSize) {
19+
super(throwParseErrors, cacheSize);
20+
secondaryCache = new TypedTreeCache<>(secondaryCacheSize);
21+
}
22+
23+
@Override
24+
public void setParseCacheSizeAndClear(int size) {
25+
throw new UnsupportedOperationException(
26+
"This parser uses a two-tier cache. Use setTwoTierCacheSizesAndClear instead.");
27+
}
28+
29+
public void setTwoTierCacheSizesAndClear(int primarySize, int secondarySize) {
30+
parseCache = new TypedTreeCache<>(primarySize);
31+
secondaryCache = new TypedTreeCache<>(secondarySize);
32+
}
33+
34+
@Override
35+
public <C extends ParserRuleContext> C parse(String str, ParserRuleContext parent, ParseShape<C, ?> parseShape) {
36+
if (parseShape.ruleType == GLSLParser.TranslationUnitContext.class) {
37+
return parseWithCache(str, parent, parseShape, secondaryCache);
38+
}
39+
return super.parse(str, parent, parseShape);
40+
}
41+
42+
@Override
43+
public void setTokenFilter(TokenFilter<?> tokenFilter) {
44+
super.setTokenFilter(tokenFilter);
45+
secondaryCache.clear();
46+
}
47+
}

glsl-transformer/src/test/java/io/github/douira/glsl_transformer/ParsingPerformanceTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ void testDeepParenExpressionParsing() {
100100
@Test
101101
void testDeepParenExpressionParsingCaching() {
102102
// with warmup, the caching parser needs basically no time
103-
parser = new CachingParser(true);
103+
parser = new CachingParser();
104104
parser.setSLLOnly();
105105
assertFilePerformance(10, FileLocation.DEEP_PAREN_EXPRESSION_TEST);
106106
}

0 commit comments

Comments
 (0)