summaryrefslogtreecommitdiff
path: root/dice-lang/src/bjc/dicelang/Define.java
blob: 2967af6828aa4b2d569579dcfa5a24d32884046f (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
package bjc.dicelang;

import bjc.utils.data.CircularIterator;

import static bjc.dicelang.Errors.ErrorKey.*;

import java.util.Iterator;
import java.util.function.UnaryOperator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

public class Define implements UnaryOperator<String> {
	public static enum Type { LINE, TOKEN }

	public static final int MAX_RECURS = 10;

	public final int     priority;
	public final boolean inError;

	private boolean doRecur;
	private boolean subType;

	private Pattern predicate;
	private Pattern searcher;

	private Iterator<String>  replacers;
	private String            replacer;

	public Define(int priorty,
			boolean isSub, boolean recur, boolean isCircular,
			String predicte, String searchr, Iterable<String> replacrs) {
		priority = priorty;
		doRecur  = recur;
		subType  = isSub;

		if(predicte != null) {
			try {
				predicate = Pattern.compile(predicte);
			} catch (PatternSyntaxException psex) {
				Errors.inst.printError(EK_DFN_PREDSYN, psex.getMessage());
				inError = true;
				return;
			}
		}

		try {
			searcher  = Pattern.compile(searchr);
		} catch (PatternSyntaxException psex) {
			Errors.inst.printError(EK_DFN_SRCSYN, psex.getMessage());
			inError = true;
			return;
		}

		inError = false;

		if(subType) {
			if(replacrs.iterator().hasNext()) {
				replacers = new CircularIterator<>(replacrs, isCircular);
			} else {
				replacers = null;
			}
		} else {
			Iterator<String> itr = replacrs.iterator();

			if(itr.hasNext()) replacer  = itr.next();
			else              replacer  = "";
		}
	}

	public String apply(String tok) {
		if(inError) return tok;

		if(predicate != null) {
			if(!predicate.matcher(tok).matches()) {
				return tok;
			}
		}

		String strang = doPass(tok);

		if(doRecur) {
			int recurCount = 0;

			if(strang.equals(tok)) {
				return strang;
			} else {
				String oldStrang = strang;

				do {
					strang = doPass(tok);
					recurCount += 1;
				} while(!strang.equals(oldStrang) && recurCount < MAX_RECURS);

				if(recurCount >= MAX_RECURS) {
					Errors.inst.printError(EK_DFN_RECUR, Integer.toString(MAX_RECURS), tok, strang);
					return strang;
				}
			}
		}

		return strang;
	}

	private String doPass(String tok) {
		Matcher searcherMatcher = searcher.matcher(tok);

		if(subType) {
			StringBuffer sb = new StringBuffer();
			while(searcherMatcher.find()) {
				if(replacers == null) {
					searcherMatcher.appendReplacement(sb,"");
				} else {
					String replac = replacers.next();
					searcherMatcher.appendReplacement(sb, replac);
				}
			}

			searcherMatcher.appendTail(sb);
			return sb.toString();
		} else {
			return searcherMatcher.replaceAll(replacer);
		}
	}
}