summaryrefslogtreecommitdiff
path: root/base/src/bjc/dicelang/expr/Tokens.java
blob: c307391da00150814fc5c2d414599528afb0cfca (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
package bjc.dicelang.expr;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

/**
 * Contains per-instance state for token parsing.
 *
 * @author EVE
 *
 */
public class Tokens {
	/* Contains mappings from variable references to string names. */
	private final Map<Integer, String> symTab;
	/* Reverse index into the symbol table. */
	private final Map<String, Integer> revSymTab;

	/** Read-only view on the symbol table. */
	public final Map<Integer, String> symbolTable;

	/* Next index into the symbol table. */
	private int nextSym;

	/* Mapping from literal tokens to token types. */
	private static final Map<String, TokenType> litTokens;

	static {
		/*
		 * Setup literal mappings.
		 *
		 * @NOTE Should this be a static member?
		 */
		litTokens = new HashMap<>();

		litTokens.put("+", TokenType.ADD);
		litTokens.put("-", TokenType.SUBTRACT);
		litTokens.put("*", TokenType.MULTIPLY);
		litTokens.put("/", TokenType.DIVIDE);
		litTokens.put("(", TokenType.OPAREN);
		litTokens.put(")", TokenType.CPAREN);
	}

	/** Create a new set of tokens. */
	public Tokens() {
		/* Create tables. */
		symTab = new HashMap<>();
		revSymTab = new HashMap<>();

		/* Init public view. */
		symbolTable = Collections.unmodifiableMap(symTab);

		/* Set sym ID. */
		nextSym = 0;
	}

	/**
	 * Convert the string representation of a token into a token.
	 *
	 * @param tok
	 *        The string representation of the token.
	 * @param raw
	 *        The original string the token came from.
	 *
	 * @return The token the string represents.
	 */
	public Token lexToken(final String tok, final String raw) {
		if(litTokens.containsKey(tok)) {
			/* Return matching literal token. */
			return new Token(litTokens.get(tok), raw, this);
		}

		/* Its a variable reference. */
		return parseVRef(tok, raw);
	}

	/* Parse a variable reference. */
	private Token parseVRef(final String tok, final String raw) {
		final Token tk = new Token(TokenType.VREF, raw, this);

		if(revSymTab.containsKey(tok)) {
			/* Reuse the entry if it exists. */
			tk.intValue = revSymTab.get(tok);
		} else {
			/* Create a new entry. */
			tk.intValue = nextSym;

			/* Record it. */
			symTab.put(nextSym, tok);
			revSymTab.put(tok, nextSym);

			/* Next ID. */
			nextSym += 1;
		}

		return tk;
	}
}