1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.pattern.parser;
15
16 import java.util.HashMap;
17 import java.util.List;
18 import java.util.Map;
19 import java.util.function.Supplier;
20
21 import ch.qos.logback.core.CoreConstants;
22 import ch.qos.logback.core.pattern.*;
23 import ch.qos.logback.core.pattern.util.IEscapeUtil;
24 import ch.qos.logback.core.pattern.util.RegularEscapeUtil;
25 import ch.qos.logback.core.spi.ContextAwareBase;
26 import ch.qos.logback.core.spi.ScanException;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 public class Parser<E> extends ContextAwareBase {
43
44 public final static String MISSING_RIGHT_PARENTHESIS = CoreConstants.CODES_URL + "#missingRightParenthesis";
45 public final static Map<String, Supplier<DynamicConverter>> DEFAULT_COMPOSITE_CONVERTER_MAP = new HashMap<>();
46 public final static String REPLACE_CONVERTER_WORD = "replace";
47 static {
48 DEFAULT_COMPOSITE_CONVERTER_MAP.put(Token.BARE_COMPOSITE_KEYWORD_TOKEN.getValue().toString(),
49 IdentityCompositeConverter::new);
50 DEFAULT_COMPOSITE_CONVERTER_MAP.put(REPLACE_CONVERTER_WORD, ReplacingCompositeConverter::new);
51 }
52
53 final List<Token> tokenList;
54 int pointer = 0;
55
56 Parser(TokenStream ts) throws ScanException {
57 this.tokenList = ts.tokenize();
58 }
59
60 public Parser(String pattern) throws ScanException {
61 this(pattern, new RegularEscapeUtil());
62 }
63
64 public Parser(String pattern, IEscapeUtil escapeUtil) throws ScanException {
65 try {
66 TokenStream ts = new TokenStream(pattern, escapeUtil);
67 this.tokenList = ts.tokenize();
68 } catch (IllegalArgumentException npe) {
69 throw new ScanException("Failed to initialize Parser", npe);
70 }
71 }
72
73
74
75
76
77
78
79
80
81 public Converter<E> compile(final Node top, Map<String, Supplier<DynamicConverter>> converterMap) {
82 Compiler<E> compiler = new Compiler<E>(top, converterMap);
83 compiler.setContext(context);
84
85 return compiler.compile();
86 }
87
88 public Node parse() throws ScanException {
89 return E();
90 }
91
92
93 Node E() throws ScanException {
94 Node t = T();
95 if (t == null) {
96 return null;
97 }
98 Node eOpt = Eopt();
99 if (eOpt != null) {
100 t.setNext(eOpt);
101 }
102 return t;
103 }
104
105
106 Node Eopt() throws ScanException {
107
108 Token next = getCurentToken();
109
110 if (next == null) {
111 return null;
112 } else {
113 return E();
114 }
115 }
116
117
118 Node T() throws ScanException {
119 Token t = getCurentToken();
120 expectNotNull(t, "a LITERAL or '%'");
121
122 switch (t.getType()) {
123 case Token.LITERAL:
124 advanceTokenPointer();
125 return new Node(Node.LITERAL, t.getValue());
126 case Token.PERCENT:
127 advanceTokenPointer();
128
129 FormatInfo fi;
130 Token u = getCurentToken();
131 FormattingNode c;
132 expectNotNull(u, "a FORMAT_MODIFIER, SIMPLE_KEYWORD or COMPOUND_KEYWORD");
133 if (u.getType() == Token.FORMAT_MODIFIER) {
134 fi = FormatInfo.valueOf((String) u.getValue());
135 advanceTokenPointer();
136 c = C();
137 c.setFormatInfo(fi);
138 } else {
139 c = C();
140 }
141 return c;
142
143 default:
144 return null;
145
146 }
147
148 }
149
150 FormattingNode C() throws ScanException {
151 Token t = getCurentToken();
152
153
154 expectNotNull(t, "a LEFT_PARENTHESIS or KEYWORD");
155 int type = t.getType();
156 switch (type) {
157 case Token.SIMPLE_KEYWORD:
158 return SINGLE();
159 case Token.COMPOSITE_KEYWORD:
160 advanceTokenPointer();
161 return COMPOSITE(t.getValue().toString());
162 default:
163 throw new IllegalStateException("Unexpected token " + t);
164 }
165 }
166
167 FormattingNode SINGLE() throws ScanException {
168
169 Token t = getNextToken();
170
171 SimpleKeywordNode keywordNode = new SimpleKeywordNode(t.getValue());
172
173 Token ot = getCurentToken();
174 if (ot != null && ot.getType() == Token.OPTION) {
175 List<String> optionList = ot.getOptionsList();
176 keywordNode.setOptions(optionList);
177 advanceTokenPointer();
178 }
179 return keywordNode;
180 }
181
182 FormattingNode COMPOSITE(String keyword) throws ScanException {
183 CompositeNode compositeNode = new CompositeNode(keyword);
184
185 Node childNode = E();
186 compositeNode.setChildNode(childNode);
187
188 Token t = getNextToken();
189
190 if (t == null || t.getType() != Token.RIGHT_PARENTHESIS) {
191 String msg = "Expecting RIGHT_PARENTHESIS token but got " + t;
192 addError(msg);
193 addError("See also " + MISSING_RIGHT_PARENTHESIS);
194 throw new ScanException(msg);
195 }
196 Token ot = getCurentToken();
197 if (ot != null && ot.getType() == Token.OPTION) {
198 List<String> optionList = ot.getOptionsList();
199 compositeNode.setOptions(optionList);
200 advanceTokenPointer();
201 }
202 return compositeNode;
203 }
204
205 Token getNextToken() {
206 if (pointer < tokenList.size()) {
207 return (Token) tokenList.get(pointer++);
208 }
209 return null;
210 }
211
212 Token getCurentToken() {
213 if (pointer < tokenList.size()) {
214 return (Token) tokenList.get(pointer);
215 }
216 return null;
217 }
218
219 void advanceTokenPointer() {
220 pointer++;
221 }
222
223 void expectNotNull(Token t, String expected) {
224 if (t == null) {
225 throw new IllegalStateException("All tokens consumed but was expecting " + expected);
226 }
227 }
228
229
230
231
232 }