/
ProcKeyword.java
77 lines (68 loc) · 3.08 KB
/
ProcKeyword.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.laytonsmith.core.compiler.keywords;
import java.util.List;
import com.laytonsmith.PureUtilities.Version;
import com.laytonsmith.core.MSVersion;
import com.laytonsmith.core.ParseTree;
import com.laytonsmith.core.compiler.Keyword;
import com.laytonsmith.core.constructs.CFunction;
import com.laytonsmith.core.constructs.CKeyword;
import com.laytonsmith.core.constructs.CString;
import com.laytonsmith.core.exceptions.ConfigCompileException;
import com.laytonsmith.core.functions.DataHandling.proc;
/**
*
*/
@Keyword.keyword("proc")
public class ProcKeyword extends Keyword {
@Override
public int process(List<ParseTree> list, int keywordPosition) throws ConfigCompileException {
if(list.get(keywordPosition).getData() instanceof CKeyword) {
// It's a lone keyword, so we expect some function to follow, which is the proc name + variables
if(list.get(keywordPosition + 1).getData() instanceof CFunction) {
ParseTree procNode = new ParseTree(new CFunction(
proc.NAME, list.get(keywordPosition).getTarget()), list.get(keywordPosition).getFileOptions());
procNode.addChild(new ParseTree(new CString(list.get(keywordPosition + 1).getData().val(),
list.get(keywordPosition + 1).getTarget()), list.get(keywordPosition + 1).getFileOptions()));
// Grab the functions children, and put them on the stack
for(ParseTree child : list.get(keywordPosition + 1).getChildren()) {
procNode.addChild(child);
}
if(list.size() > keywordPosition + 2) {
validateCodeBlock(list.get(keywordPosition + 2), "Expected braces to follow proc definition");
procNode.addChild(getArgumentOrNull(list.get(keywordPosition + 2)));
} else {
throw new ConfigCompileException("Expected braces to follow proc definition", list.get(keywordPosition + 1).getTarget());
}
list.remove(keywordPosition); // Remove the keyword
list.remove(keywordPosition); // Remove the function definition
list.remove(keywordPosition); // Remove the cbrace
list.add(keywordPosition, procNode); // Add in the new proc definition
} else {
throw new ConfigCompileException("Unexpected use of \"proc\" keyword", list.get(keywordPosition).getTarget());
}
} else if(nodeIsProcFunction(list.get(keywordPosition))) {
// It's the functional usage, possibly followed by a cbrace. If so, pull the cbrace in, and that's it
if(list.size() > keywordPosition + 1) {
if(isValidCodeBlock(list.get(keywordPosition + 1))) {
list.get(keywordPosition).addChild(getArgumentOrNull(list.get(keywordPosition + 1)));
list.remove(keywordPosition + 1);
}
}
} else {
// Random keyword in the middle of nowhere
throw new ConfigCompileException("Unexpected use of \"proc\" keyword", list.get(keywordPosition).getTarget());
}
return keywordPosition;
}
private boolean nodeIsProcFunction(ParseTree node) {
return node.getData() instanceof CFunction && node.getData().val().equals(proc.NAME);
}
@Override
public String docs() {
return "Defines a procedure, which can be called from elsewhere in code.";
}
@Override
public Version since() {
return MSVersion.V3_3_1;
}
}