Skip to content

Commit 6082084

Browse files
feat: Refactor template parsing and enhance context management with new Context class
1 parent 2905e16 commit 6082084

File tree

8 files changed

+99
-82
lines changed

8 files changed

+99
-82
lines changed

src/main/antlr4/com/hindbiswas/jhp/JhpTemplateParser.g4

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ templateElement
1717
;
1818

1919
// Echo statements
20-
echoStatement
21-
: ECHO_START expression ECHO_END
22-
;
23-
2420
rawEchoStatement
2521
: RAW_ECHO_START expression RAW_ECHO_END
2622
;
23+
24+
echoStatement
25+
: ECHO_START expression ECHO_END
26+
;
2727

2828
// Control statements
2929
controlStatement
Lines changed: 14 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
package com.hindbiswas.jhp;
22

3-
import org.antlr.v4.runtime.*;
4-
import org.antlr.v4.runtime.tree.*;
5-
6-
import com.hindbiswas.jhp.ast.AstBuilder;
7-
import com.hindbiswas.jhp.ast.AstPrettyPrinter;
8-
import com.hindbiswas.jhp.ast.AstRendererOld;
9-
import com.hindbiswas.jhp.ast.TemplateNode;
103
import com.hindbiswas.jhp.engine.FunctionLibrary;
114
import com.hindbiswas.jhp.engine.JhpEngine;
125
import com.hindbiswas.jhp.engine.Settings;
136

14-
import java.nio.file.Files;
15-
import java.nio.file.Path;
16-
import java.nio.file.Paths;
17-
import java.util.HashMap;
18-
import java.util.Map;
7+
class User {
8+
public String name;
9+
public int age;
10+
public String gender;
11+
12+
User(String name, int age, String gender) {
13+
this.name = name;
14+
this.age = age;
15+
this.gender = gender;
16+
}
17+
}
1918

2019
public class App {
2120
public static void main(String[] args) throws Exception {
@@ -25,58 +24,11 @@ public static void main(String[] args) throws Exception {
2524
FunctionLibrary lib = new FunctionLibrary();
2625
JhpEngine engine = new JhpEngine(settings, lib);
2726

28-
Map<String, Object> ctx = new HashMap<>();
29-
Map<String, Object> user = new HashMap<>();
30-
user.put("name", "Alice");
31-
user.put("age", 150);
32-
user.put("gender", "f");
33-
ctx.put("user", user);
34-
ctx.put("title", "Test JHP");
27+
Context ctx = new Context();
28+
ctx.add("user", new User("Alice", 150, "f"));
29+
ctx.add("title", "Test JHP");
3530

3631
String out = engine.render(file, ctx);
3732
System.out.println(out);
3833
}
39-
40-
public static void oldReneder(String file) throws Exception {
41-
ParseTree tree = generateTree(file);
42-
AstBuilder builder = new AstBuilder();
43-
TemplateNode ast = (TemplateNode) builder.visit(tree);
44-
AstPrettyPrinter.print(ast);
45-
46-
// Context
47-
Map<String, Object> ctx = new HashMap<>();
48-
Map<String, Object> user = new HashMap<>();
49-
user.put("name", "Alice");
50-
user.put("age", 150);
51-
user.put("gender", "F");
52-
ctx.put("user", user);
53-
ctx.put("title", "Test JHP");
54-
55-
// render
56-
AstRendererOld renderer = new AstRendererOld(Path.of("examples")); // optional base dir
57-
String out = renderer.render(ast, ctx);
58-
System.out.println(out);
59-
}
60-
61-
public static ParseTree generateTree(String file) throws Exception {
62-
// Read template file
63-
String text = Files.readString(Paths.get(file));
64-
65-
// Create CharStream
66-
CharStream cs = CharStreams.fromString(text);
67-
68-
// Lexer & token stream
69-
JhpTemplateLexer lexer = new JhpTemplateLexer(cs);
70-
CommonTokenStream tokens = new CommonTokenStream(lexer);
71-
72-
// Parser
73-
JhpTemplateParser parser = new JhpTemplateParser(tokens);
74-
parser.removeErrorListeners();
75-
parser.addErrorListener(new DiagnosticErrorListener());
76-
77-
// Parse template
78-
ParseTree tree = parser.template();
79-
80-
return tree;
81-
}
8234
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package com.hindbiswas.jhp;
2+
3+
import java.lang.reflect.Array;
4+
import java.lang.reflect.Field;
5+
import java.util.*;
6+
7+
public class Context {
8+
private final Map<String, Object> context = new HashMap<>();
9+
10+
public void add(String key, Object value) {
11+
context.put(key, toContextValue(value));
12+
}
13+
14+
public Map<String, Object> getContext() {
15+
return context;
16+
}
17+
18+
private Object toContextValue(Object value) {
19+
if (value == null)
20+
return null;
21+
22+
// Primitive wrapper, String, Map -> store as-is
23+
if (isPrimitiveOrString(value) || value instanceof Map) {
24+
return value;
25+
}
26+
27+
// Arrays
28+
if (value.getClass().isArray()) {
29+
int len = Array.getLength(value);
30+
Object[] arr = new Object[len];
31+
for (int i = 0; i < len; i++) {
32+
arr[i] = toContextValue(Array.get(value, i));
33+
}
34+
return arr;
35+
}
36+
37+
// Collections
38+
if (value instanceof Collection<?> coll) {
39+
List<Object> list = new ArrayList<>();
40+
for (Object o : coll) {
41+
list.add(toContextValue(o));
42+
}
43+
return list;
44+
}
45+
46+
// POJO -> convert public fields only
47+
Map<String, Object> map = new HashMap<>();
48+
Field[] fields = value.getClass().getFields(); // only public fields
49+
for (Field f : fields) {
50+
try {
51+
Object fieldValue = f.get(value);
52+
// skip nested POJOs, only include arrays/collections/primitives
53+
if (fieldValue != null && !isPrimitiveOrString(fieldValue)
54+
&& !(fieldValue instanceof Map)
55+
&& !fieldValue.getClass().isArray()
56+
&& !(fieldValue instanceof Collection<?>)) {
57+
continue;
58+
}
59+
map.put(f.getName(), toContextValue(fieldValue));
60+
} catch (IllegalAccessException e) {
61+
// ignore inaccessible fields
62+
}
63+
}
64+
return map;
65+
}
66+
67+
private boolean isPrimitiveOrString(Object value) {
68+
return value instanceof String
69+
|| value instanceof Number
70+
|| value instanceof Boolean
71+
|| value instanceof Character
72+
|| value.getClass().isPrimitive();
73+
}
74+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
package com.hindbiswas.jhp.ast;
22

3-
public interface AstNode {
3+
interface AstNode {
44
}

src/main/java/com/hindbiswas/jhp/ast/AstRenderer.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -455,16 +455,6 @@ private Object indexAccess(Object arr, Object idx) {
455455
return null;
456456
}
457457

458-
private Object callFunction(Object callee, List<Object> args, Deque<Map<String, Object>> scopes) {
459-
if (callee instanceof String name) {
460-
return functions.callFunction(name, args, scopes);
461-
}
462-
// unknown callee type
463-
StringBuilder sb = new StringBuilder();
464-
issueResolver.handle(IssueType.FUNCTION_CALL_ERROR, "Invalid function call: " + callee, sb, includeStack);
465-
return sb.toString();
466-
}
467-
468458
private String stringify(Object o) {
469459
if (o == null)
470460
return "";

src/main/java/com/hindbiswas/jhp/ast/AstRendererOld.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import com.hindbiswas.jhp.JhpTemplateLexer;
1616
import com.hindbiswas.jhp.JhpTemplateParser;
1717

18-
public class AstRendererOld {
18+
class AstRendererOld {
1919
private final ThreadLocal<Deque<Path>> includeStack = ThreadLocal.withInitial(ArrayDeque::new);
2020
private final Map<Path, TemplateNode> astCache = new HashMap<>();
2121
private final Path baseDir; // used for includes, nullable
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
package com.hindbiswas.jhp.ast;
22

3-
public interface TemplateElementNode extends AstNode {
3+
interface TemplateElementNode extends AstNode {
44
}

src/main/java/com/hindbiswas/jhp/engine/JhpEngine.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import com.hindbiswas.jhp.ast.AstRenderer;
55
import com.hindbiswas.jhp.ast.TemplateNode;
66
import com.hindbiswas.jhp.errors.PathNotInBaseDirectoryException;
7+
import com.hindbiswas.jhp.Context;
78
import com.hindbiswas.jhp.JhpTemplateLexer;
89
import com.hindbiswas.jhp.JhpTemplateParser;
910

@@ -219,13 +220,13 @@ public JhpEngine(Settings settings, FunctionLibraryContext functionLibrary) {
219220
this.functionLibrary = functionLibrary;
220221
}
221222

222-
public String render(Path templatePath, Map<String, Object> context) throws Exception {
223+
public String render(Path templatePath, Context context) throws Exception {
223224
TemplateNode ast = parser.parse(templatePath);
224225
AstRenderer renderer = new AstRenderer(settings, functionLibrary, issueResolver, includePathResolver, parser);
225-
return renderer.render(ast, context);
226+
return renderer.render(ast, context.getContext());
226227
}
227228

228-
public String render(String pathTxt, Map<String, Object> context) throws Exception {
229+
public String render(String pathTxt, Context context) throws Exception {
229230
Path path = includePathResolver.resolve(pathTxt, null);
230231
return render(path, context);
231232
}

0 commit comments

Comments
 (0)