summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/v2/DiceLangEngine.java
blob: 2bfa53a72ce68eeb06050b0ec577ade5ba49e712 (plain)
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
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package bjc.utils.dicelang.v2;

import bjc.utils.funcdata.FunctionalList;
import bjc.utils.funcdata.FunctionalMap;
import bjc.utils.funcdata.FunctionalStringTokenizer;
import bjc.utils.funcdata.IList;
import bjc.utils.funcdata.IMap;
import bjc.utils.funcutils.ListUtils;

import java.util.Deque;
import java.util.LinkedList;

public class DiceLangEngine {
	// Input rules for processing tokens
	private Deque<IPair<String, String>> opExpansionTokens;
	private Deque<IPair<String, String>> deaffixationTokens;

	// ID for generation of string literal variables
	private int nextLiteral;

	// Debug indicator
	private boolean debugMode;

	public DiceLangEngine() {
		opExpansionTokens = new LinkedList<>();

		opExpansionTokens.add(new Pair<>("+", "\\+"));
		opExpansionTokens.add(new Pair<>("-", "-"));
		opExpansionTokens.add(new Pair<>("*", "\\*"));
		opExpansionTokens.add(new Pair<>("/", "/"));
		opExpansionTokens.add(new Pair<>(":=", ":="));
		opExpansionTokens.add(new Pair<>("=>", "=>"));

		deaffixationTokens = new LinkedList<>();

		deaffixationTokens.add(new Pair<>("(", "\\("));
		deaffixationTokens.add(new Pair<>(")", "\\("));
		deaffixationTokens.add(new Pair<>("[", "\\["));
		deaffixationTokens.add(new Pair<>("]", "\\]"));

		nextLiteral = 1;
		
		// @TODO make configurable
		debugMode = true;
	}

	public boolean runCommand(String command) {
		// Split the command into tokens
		IList<String> tokens = FunctionalStringTokenizer
			.fromString(currentLine)
			.toList();

		// Will hold tokens with string literals removed
		IList<String> destringed = new FunctionalList<>();

		// Where we keep the string literals
		// @TODO put these in the sym-table early instead
		// 		 once there is a sym-table
		IMap<String, String> stringLiterals = new FunctionalMap<>();

		boolean success = destringTokens(tokens, stringLiterals,
				destringed);

		if(!success) return success;

		if(debugMode)
			System.out.println("Command after destringing: "
					+ destringed.toString());
	}

	private boolean destringTokens(IList<String> tokens,
			IMap<String, String> stringLiterals,
			IList<String> destringed) {
		// Are we parsing a string literal?
		boolean stringMode = false;

		// The current string literal
		StringBuilder currentLiteral = new StringBuilder();

		for(String token : tokens.toIterable()) {
			String[] tokenParts = token.split("^(?!\\\\\")\"");

			if(tokenParts.length == 1) {
				// Insert token into correct place
				if(stringMode) {
					currentLiteral.add(tokenParts[0]);
				} else {
					destringed.add(tokenParts[0]);
				}
			} else {
				// Handle multiple "'s in a token
				for(String stringPart : tokenParts) {
					// Insert token into correct place
					if(stringMode) {
						currentLiteral.add(stringPart);
					} else {
						destringed.add(stringPart);
					}

					// We found a quote. Toggle string mode
					// and collect the literal
					stringMode = !stringMode;

					if(debugMode)
						System.out.printf("DEBUG: Parsed string"
								+ " literal (" 
								+ currentLiteral.toString() + ")");

					stringLiterals.put("stringLiteral"
							+ nextLiteral,
							currentLiteral.toString());
					destringed.add("stringLiteral" + nextLiteral);

					nextLiteral += 1;
					currentLiteral = new StringBuilder();
				}
			}
		}

		if(stringMode) {
			System.out.printf("\tERROR: Unclosed string literal (%s"
					+ ").\n", currentLiteral.toString());

			return false;
		}

		return true;
	}
}