1 | package com.framsticks.framclipse; |
---|
2 | |
---|
3 | import org.antlr.runtime.CharStream; |
---|
4 | import org.antlr.runtime.RecognitionException; |
---|
5 | import org.antlr.runtime.Token; |
---|
6 | |
---|
7 | import com.framsticks.framclipse.parser.antlr.internal.InternalFramScriptLexer; |
---|
8 | |
---|
9 | public class FramScriptAuxiliaryLexer extends InternalFramScriptLexer { |
---|
10 | |
---|
11 | private static final int FLG_MULTILINE = 0x1; |
---|
12 | private static final int FLG_TYPE_IS_NUMERIC = 0x2; // if raised, the default value should be analysed with internal lexer |
---|
13 | private static final int FLG_TYPE_IS_STRING = 0x4; // if raised, the max value can be omitted and should be 0 |
---|
14 | private static final int CTX_NONE = 0; |
---|
15 | private static final int CTX_TYPE = 1; |
---|
16 | private static final int CTX_TYPE_ID = 2; |
---|
17 | private static final int CTX_TYPE_MIN = 3; |
---|
18 | private static final int CTX_TYPE_MAX = 4; |
---|
19 | private static final int CTX_TYPE_DEFAULT = 5; |
---|
20 | |
---|
21 | private int context = CTX_NONE; |
---|
22 | private int flags = 0; |
---|
23 | private Token previous = Token.INVALID_TOKEN; |
---|
24 | |
---|
25 | private void checkML() { |
---|
26 | setFlag(FLG_MULTILINE, next() == '~'); |
---|
27 | } |
---|
28 | |
---|
29 | private boolean isSet(int flag) { |
---|
30 | return (flags & flag) != 0; |
---|
31 | } |
---|
32 | |
---|
33 | private void setFlag(int flag, boolean state) { |
---|
34 | if (state) |
---|
35 | flags |= flag; |
---|
36 | else |
---|
37 | flags &= ~flag; |
---|
38 | } |
---|
39 | |
---|
40 | private void setState(int tokenType) { |
---|
41 | state.token = null; |
---|
42 | state.channel = Token.DEFAULT_CHANNEL; |
---|
43 | state.tokenStartCharIndex = input.index(); |
---|
44 | state.tokenStartCharPositionInLine = input.getCharPositionInLine(); |
---|
45 | state.tokenStartLine = input.getLine(); |
---|
46 | state.text = null; |
---|
47 | state.type = tokenType; |
---|
48 | } |
---|
49 | |
---|
50 | char next() { |
---|
51 | return next(1); |
---|
52 | } |
---|
53 | |
---|
54 | char next(int i) { |
---|
55 | return (char)input.LA(i); |
---|
56 | } |
---|
57 | |
---|
58 | void consumeUntilAny(String term) { |
---|
59 | term += (char)CharStream.EOF; |
---|
60 | while (term.indexOf(next()) == -1) |
---|
61 | matchAny(); |
---|
62 | } |
---|
63 | |
---|
64 | @Override |
---|
65 | public Token nextToken() { |
---|
66 | switch (previous.getType()) { |
---|
67 | case RULE_HEADER_ID: |
---|
68 | setState(RULE_HEADER_VALUE); |
---|
69 | checkML(); |
---|
70 | mHEADER_VALUE(); |
---|
71 | return previous = emit(); |
---|
72 | case RULE_TYPE_HEADER: |
---|
73 | checkML(); |
---|
74 | context = CTX_TYPE; |
---|
75 | if (isSet(FLG_MULTILINE)) { |
---|
76 | setState(RULE_WS); // any ignored token |
---|
77 | matchAny(); // consume '~' |
---|
78 | return previous = emit(); |
---|
79 | } |
---|
80 | break; |
---|
81 | case RULE_WS: |
---|
82 | if (context == CTX_TYPE_MIN) { |
---|
83 | if (isSet(FLG_TYPE_IS_STRING)) { |
---|
84 | if (!Character.isDigit(next()) && next() != '-') { // if string length is omitted |
---|
85 | if (isSet(FLG_MULTILINE)) |
---|
86 | matchAny(); // ignore expected '~' |
---|
87 | setState(RULE_INT); |
---|
88 | state.text = "0"; // pretend the max value is 0 |
---|
89 | return previous = emit(); |
---|
90 | } |
---|
91 | } |
---|
92 | } |
---|
93 | if (previous.getText().indexOf('\n') != -1 || |
---|
94 | previous.getText().indexOf('\r') != -1) { |
---|
95 | if (!isSet(FLG_MULTILINE)) { |
---|
96 | context = CTX_NONE; |
---|
97 | } |
---|
98 | // workaround for '#include' |
---|
99 | if (willMatch("#include")) { |
---|
100 | setState(RULE_PROP_INCLUDE); |
---|
101 | try { |
---|
102 | mRULE_PROP_INCLUDE(); |
---|
103 | } catch (RecognitionException e) { |
---|
104 | reportError(e); |
---|
105 | } |
---|
106 | return previous = emit(); |
---|
107 | } |
---|
108 | if (!isSet(FLG_MULTILINE)) { |
---|
109 | break; |
---|
110 | } |
---|
111 | } |
---|
112 | if (context == CTX_TYPE_MAX) { |
---|
113 | if (isSet(FLG_MULTILINE)) { |
---|
114 | context = CTX_TYPE_DEFAULT; |
---|
115 | } else { |
---|
116 | context = CTX_NONE; |
---|
117 | } |
---|
118 | if (isSet(FLG_TYPE_IS_NUMERIC)) { |
---|
119 | if (isSet(FLG_MULTILINE) && !Character.isDigit(next()) |
---|
120 | && next() != '-') { // if default value is omitted |
---|
121 | previous = aux_ENUM_LITERAL(); |
---|
122 | if (previous != null) |
---|
123 | return previous; |
---|
124 | } |
---|
125 | break; |
---|
126 | } else { |
---|
127 | setState(RULE_HEADER_VALUE); |
---|
128 | mRULE_TYPE_HEADER_VALUE(); |
---|
129 | return previous = emit(); |
---|
130 | } |
---|
131 | } else if (context == CTX_TYPE_DEFAULT) { |
---|
132 | previous = aux_ENUM_LITERAL(); |
---|
133 | if (previous != null) |
---|
134 | return previous; |
---|
135 | } |
---|
136 | break; |
---|
137 | case RULE_ID: |
---|
138 | if (context == CTX_TYPE) { |
---|
139 | if ("df".indexOf(previous.getText().charAt(0)) == -1) { |
---|
140 | setFlag(FLG_TYPE_IS_NUMERIC, false); |
---|
141 | setFlag(FLG_TYPE_IS_STRING, previous.getText().charAt(0) == (int)'s'); |
---|
142 | } else { |
---|
143 | setFlag(FLG_TYPE_IS_NUMERIC, true); |
---|
144 | } |
---|
145 | context = CTX_TYPE_ID; |
---|
146 | break; |
---|
147 | } |
---|
148 | context = CTX_NONE; |
---|
149 | break; |
---|
150 | case RULE_HEADER_VALUE: |
---|
151 | case RULE_ENUM_LITERAL: |
---|
152 | if (context == CTX_TYPE_DEFAULT) { |
---|
153 | previous = aux_ENUM_LITERAL(); |
---|
154 | if (previous != null) |
---|
155 | return previous; |
---|
156 | } |
---|
157 | context = CTX_NONE; |
---|
158 | break; |
---|
159 | case RULE_DOUBLE: |
---|
160 | case RULE_INT: |
---|
161 | if (context == CTX_TYPE_DEFAULT) { |
---|
162 | break; // avoid changing context |
---|
163 | } else if (context == CTX_TYPE_ID) { |
---|
164 | context = CTX_TYPE_MIN; |
---|
165 | break; |
---|
166 | } else if (context == CTX_TYPE_MIN) { |
---|
167 | context = CTX_TYPE_MAX; |
---|
168 | break; |
---|
169 | } |
---|
170 | context = CTX_NONE; |
---|
171 | break; |
---|
172 | default: |
---|
173 | if ("-".equals(previous.getText()) || |
---|
174 | "+".equals(previous.getText())) { |
---|
175 | break; |
---|
176 | } |
---|
177 | context = CTX_NONE; |
---|
178 | case RULE_SL_COMMENT: |
---|
179 | break; |
---|
180 | } |
---|
181 | return previous = super.nextToken(); |
---|
182 | } |
---|
183 | |
---|
184 | private boolean willMatch(String string) { |
---|
185 | for (int i = 0; i < string.length(); ++i) { |
---|
186 | if (next(i+1) != string.charAt(i)) |
---|
187 | return false; |
---|
188 | } |
---|
189 | return true; |
---|
190 | } |
---|
191 | |
---|
192 | private Token aux_ENUM_LITERAL() { |
---|
193 | // CTX_TYPE_DEFAULT assumes raised FLG_MULTILINE |
---|
194 | if (next() == '~') { |
---|
195 | setState(RULE_WS); // any ignored token |
---|
196 | matchAny(); |
---|
197 | context = CTX_NONE; |
---|
198 | return emit(); |
---|
199 | } else if (next() == '\\' && next(2) == '~') { |
---|
200 | matchAny(); // not assigned to any terminal |
---|
201 | setState(RULE_ENUM_LITERAL); |
---|
202 | matchAny(); // consume '~' |
---|
203 | mRULE_TYPE_HEADER_VALUE(); |
---|
204 | return emit(); |
---|
205 | } |
---|
206 | return null; |
---|
207 | } |
---|
208 | |
---|
209 | private void mRULE_TYPE_HEADER_VALUE() { |
---|
210 | if (isSet(FLG_MULTILINE)) { |
---|
211 | do { |
---|
212 | consumeUntilAny("\\~"); |
---|
213 | if (next() == '\\' && next(2) != '~') { |
---|
214 | matchAny(); |
---|
215 | continue; |
---|
216 | } |
---|
217 | } while (false); |
---|
218 | } else { |
---|
219 | consumeUntilAny("~\r\n"); |
---|
220 | } |
---|
221 | } |
---|
222 | |
---|
223 | private void mHEADER_VALUE() { |
---|
224 | if (isSet(FLG_MULTILINE)) { |
---|
225 | matchAny(); // consume '~' |
---|
226 | do { |
---|
227 | consumeUntilAny("\\~"); |
---|
228 | if (next() == '\\') { |
---|
229 | matchAny(); |
---|
230 | if (next() == '~') |
---|
231 | matchAny(); |
---|
232 | continue; |
---|
233 | } |
---|
234 | } while (false); |
---|
235 | matchAny(); |
---|
236 | } else { |
---|
237 | consumeUntilAny("\r\n"); |
---|
238 | } |
---|
239 | } |
---|
240 | } |
---|