Browse Source

Interpolation in BEPs

kindlich 5 years ago
parent
commit
f387449a4e
No known key found for this signature in database

+ 124
- 0
Parser/src/main/java/org/openzen/zenscript/parser/EscapableBracketParser.java View File

@@ -0,0 +1,124 @@
1
+/*
2
+ * To change this license header, choose License Headers in Project Properties.
3
+ * To change this template file, choose Tools | Templates
4
+ * and open the template in the editor.
5
+ */
6
+package org.openzen.zenscript.parser;
7
+
8
+import org.openzen.zencode.shared.CodePosition;
9
+import org.openzen.zencode.shared.CompileException;
10
+import org.openzen.zenscript.codemodel.OperatorType;
11
+import org.openzen.zenscript.codemodel.expression.CallArguments;
12
+import org.openzen.zenscript.codemodel.expression.CallStaticExpression;
13
+import org.openzen.zenscript.codemodel.expression.Expression;
14
+import org.openzen.zenscript.codemodel.member.ref.FunctionalMemberRef;
15
+import org.openzen.zenscript.codemodel.partial.IPartialExpression;
16
+import org.openzen.zenscript.codemodel.scope.ExpressionScope;
17
+import org.openzen.zenscript.codemodel.type.GlobalTypeRegistry;
18
+import org.openzen.zenscript.codemodel.type.StringTypeID;
19
+import org.openzen.zenscript.codemodel.type.TypeID;
20
+import org.openzen.zenscript.lexer.ParseException;
21
+import org.openzen.zenscript.lexer.ZSToken;
22
+import org.openzen.zenscript.lexer.ZSTokenParser;
23
+import org.openzen.zenscript.lexer.ZSTokenType;
24
+import org.openzen.zenscript.parser.expression.ParsedExpression;
25
+import org.openzen.zenscript.parser.expression.ParsedExpressionBinary;
26
+import org.openzen.zenscript.parser.expression.ParsedExpressionString;
27
+
28
+import java.util.ArrayList;
29
+import java.util.List;
30
+
31
+/**
32
+ * @author Hoofdgebruiker and kindlich
33
+ */
34
+public class EscapableBracketParser implements BracketExpressionParser {
35
+    private final FunctionalMemberRef method;
36
+    private final TypeID targetType;
37
+
38
+    public EscapableBracketParser(GlobalTypeRegistry registry, FunctionalMemberRef method) {
39
+        if (!method.isStatic())
40
+            throw new IllegalArgumentException("Method must be static");
41
+        if (method.getHeader().getNumberOfTypeParameters() > 0)
42
+            throw new IllegalArgumentException("Method cannot have type parameters");
43
+
44
+        this.method = method;
45
+        this.targetType = registry.getForDefinition(method.getTarget().definition);
46
+    }
47
+
48
+    @Override
49
+    public ParsedExpression parse(CodePosition position, ZSTokenParser tokens) throws ParseException {
50
+        StringBuilder string = new StringBuilder();
51
+
52
+        //This list will contain the BEP calls
53
+        //If this is only a normal BEP, then it will contain exactly one String ParsedExpression.
54
+        final List<ParsedExpression> expressionList = new ArrayList<>();
55
+
56
+        while (tokens.optional(ZSTokenType.T_GREATER) == null) {
57
+            ZSToken next = tokens.next();
58
+
59
+            if (next.type != ZSTokenType.T_DOLLAR) {
60
+                string.append(next.content);
61
+                string.append(tokens.getLastWhitespace());
62
+                continue;
63
+            }
64
+
65
+            //We found a $, now check that it has a { directly after it.
66
+            final String ws = tokens.getLastWhitespace();
67
+            if (!ws.isEmpty()) {
68
+                //$  {..} is not ${..} so we print it as literal
69
+                string.append(next.content).append(ws);
70
+                continue;
71
+            }
72
+
73
+            next = tokens.next();
74
+            //Now we check if it is a {
75
+            if (next.type == ZSTokenType.T_AOPEN) {
76
+                if (string.length() != 0) {
77
+                    expressionList.add(new ParsedExpressionString(position, string.toString(), false));
78
+                    string = new StringBuilder();
79
+                }
80
+                expressionList.add(ParsedExpression.parse(tokens));
81
+                tokens.required(ZSTokenType.T_ACLOSE, "} expected.");
82
+                string.append(tokens.getLastWhitespace());
83
+            } else {
84
+                //No { after the $, so we treat them both as literal
85
+                string.append("$").append(ws); //Technically, the whitespace here is empty, but let's be sure
86
+                string.append(next.content).append(tokens.getLastWhitespace());
87
+            }
88
+
89
+        }
90
+
91
+        if (string.length() != 0) {
92
+            expressionList.add(new ParsedExpressionString(position, string.toString(), false));
93
+        }
94
+
95
+        return new StaticMethodCallExpression(position, expressionList);
96
+    }
97
+
98
+    private class StaticMethodCallExpression extends ParsedExpression {
99
+
100
+        private final ParsedExpression call;
101
+
102
+        public StaticMethodCallExpression(CodePosition position, List<ParsedExpression> expressions) {
103
+            super(position);
104
+            ParsedExpression p = null;
105
+            for (ParsedExpression expression : expressions) {
106
+                p = p == null ? expression : new ParsedExpressionBinary(expression.position, p, expression, OperatorType.ADD);
107
+            }
108
+
109
+            this.call = p;
110
+        }
111
+
112
+        @Override
113
+        public IPartialExpression compile(ExpressionScope scope) throws CompileException {
114
+            final Expression methodCall = call.compile(scope.withHint(StringTypeID.AUTO)).eval();
115
+            final CallArguments arguments = new CallArguments(methodCall);
116
+            return new CallStaticExpression(position, targetType, method, method.getHeader(), arguments);
117
+        }
118
+
119
+        @Override
120
+        public boolean hasStrongType() {
121
+            return true;
122
+        }
123
+    }
124
+}

+ 4
- 0
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/Globals.java View File

@@ -67,6 +67,10 @@ public class Globals implements ZenCodeGlobals {
67 67
 	public static TestClass bracket(String value) {
68 68
 		return new TestClass(value);
69 69
 	}
70
+
71
+	public static String staticToString(String value) {
72
+		return value;
73
+	}
70 74
 	
71 75
 	@FunctionalInterface
72 76
 	public static interface MyFunctionalInterface {

+ 13
- 7
ScriptingExample/src/main/java/org/openzen/zenscript/scriptingexample/Main.java View File

@@ -15,13 +15,15 @@ import org.openzen.zenscript.codemodel.SemanticModule;
15 15
 import org.openzen.zenscript.codemodel.type.StringTypeID;
16 16
 import org.openzen.zenscript.lexer.ParseException;
17 17
 import org.openzen.zenscript.parser.BracketExpressionParser;
18
+import org.openzen.zenscript.parser.EscapableBracketParser;
19
+import org.openzen.zenscript.parser.PrefixedBracketParser;
18 20
 import org.openzen.zenscript.parser.SimpleBracketParser;
19 21
 
20 22
 public class Main {
21 23
 	public static void main(String[] args) throws CompileException, ParseException, IOException, NoSuchMethodException {
22 24
 		ScriptingEngine scriptingEngine = new ScriptingEngine();
23 25
 		scriptingEngine.debug = true;
24
-		
26
+
25 27
 		JavaNativeModule example = scriptingEngine.createNativeModule("example", "org.openzen.zenscript.scriptingexample");
26 28
 		example.addGlobals(Globals.class);
27 29
 		example.addClass(TestBaseInterface.class);
@@ -29,21 +31,25 @@ public class Main {
29 31
 		example.addClass(TestClass.class);
30 32
 		example.addClass(TestInterface.class);
31 33
 		scriptingEngine.registerNativeProvided(example);
32
-		
34
+
33 35
 		File inputDirectory = new File("scripts");
34 36
 		File[] inputFiles = Optional.ofNullable(inputDirectory.listFiles((dir, name) -> name.endsWith(".zs"))).orElseGet(() -> new File[0]);
35 37
 		SourceFile[] sourceFiles = new SourceFile[inputFiles.length];
36 38
 		for (int i = 0; i < inputFiles.length; i++)
37 39
 			sourceFiles[i] = new FileSourceFile(inputFiles[i].getName(), inputFiles[i]);
38
-		
39
-		BracketExpressionParser bracketParser = new SimpleBracketParser(scriptingEngine.registry, example.loadStaticMethod(Globals.class.getMethod("bracket", String.class)));
40
+
41
+		final PrefixedBracketParser parser = new PrefixedBracketParser(null);
42
+		BracketExpressionParser testParser = new SimpleBracketParser(scriptingEngine.registry, example.loadStaticMethod(Globals.class.getMethod("bracket", String.class)));
43
+		parser.register("test", testParser);
44
+		BracketExpressionParser toStringParser = new EscapableBracketParser(scriptingEngine.registry, example.loadStaticMethod(Globals.class.getMethod("staticToString", String.class)));
45
+		parser.register("toString", toStringParser);
40 46
 		FunctionParameter parameter = new FunctionParameter(scriptingEngine.registry.getArray(StringTypeID.AUTO, 1).stored(), "args");
41
-		SemanticModule scripts = scriptingEngine.createScriptedModule("script", sourceFiles, bracketParser, new FunctionParameter[] { parameter });
47
+		SemanticModule scripts = scriptingEngine.createScriptedModule("script", sourceFiles, parser, new FunctionParameter[] { parameter });
42 48
 		if (!scripts.isValid())
43 49
 			return;
44
-		
50
+
45 51
 		scriptingEngine.registerCompiled(scripts);
46
-		
52
+
47 53
 		Map<FunctionParameter, Object> scriptArgs = new HashMap<>();
48 54
 		scriptArgs.put(parameter, new String[] { "hello", "world", "example" });
49 55
 		scriptingEngine.run(scriptArgs);

Loading…
Cancel
Save