1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.subst;
15
16 import ch.qos.logback.core.CoreConstants;
17 import ch.qos.logback.core.spi.ScanException;
18
19 import java.util.List;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 public class Parser {
41
42 static final public String EXPECTING_DATA_AFTER_LEFT_ACCOLADE = "Expecting at least a literal between left accolade and ':-'";
43
44 final List<Token> tokenList;
45 int pointer = 0;
46
47 public Parser(List<Token> tokenList) {
48 this.tokenList = tokenList;
49 }
50
51 public Node parse() throws ScanException {
52 if (tokenList == null || tokenList.isEmpty())
53 return null;
54 return E();
55 }
56
57 private Node E() throws ScanException {
58 Node t = T();
59 if (t == null) {
60 return null;
61 }
62 Node eOpt = Eopt();
63 if (eOpt != null) {
64 t.append(eOpt);
65 }
66 return t;
67 }
68
69
70 private Node Eopt() throws ScanException {
71 Token next = peekAtCurentToken();
72 if (next == null) {
73 return null;
74 } else {
75 return E();
76 }
77 }
78
79
80 private Node T() throws ScanException {
81 Token t = peekAtCurentToken();
82 if(t == null) {
83 return null;
84 }
85 switch (t.type) {
86 case LITERAL:
87 advanceTokenPointer();
88 return makeNewLiteralNode(t.payload);
89 case CURLY_LEFT:
90 advanceTokenPointer();
91 Node innerNode = C();
92 Token right = peekAtCurentToken();
93 expectCurlyRight(right);
94 advanceTokenPointer();
95 Node curlyLeft = makeNewLiteralNode(CoreConstants.LEFT_ACCOLADE);
96 curlyLeft.append(innerNode);
97 curlyLeft.append(makeNewLiteralNode(CoreConstants.RIGHT_ACCOLADE));
98 return curlyLeft;
99 case START:
100 advanceTokenPointer();
101 Node v = V();
102 Token w = peekAtCurentToken();
103 expectCurlyRight(w);
104 advanceTokenPointer();
105 return v;
106 default:
107 return null;
108 }
109 }
110
111 private Node makeNewLiteralNode(String s) {
112 return new Node(Node.Type.LITERAL, s);
113 }
114
115
116 private Node V() throws ScanException {
117 Node e = E();
118 Node variable = new Node(Node.Type.VARIABLE, e);
119 Token t = peekAtCurentToken();
120 if (isDefaultToken(t)) {
121 advanceTokenPointer();
122 Node def = Eopt();
123 if(def != null) {
124 variable.defaultPart = def;
125 } else {
126 variable.defaultPart = makeNewLiteralNode(CoreConstants.EMPTY_STRING);
127 }
128 }
129 return variable;
130 }
131
132
133
134 private Node C() throws ScanException {
135 Node e0 = E();
136 Token t = peekAtCurentToken();
137 if (isDefaultToken(t)) {
138 advanceTokenPointer();
139 Node literal = makeNewLiteralNode(CoreConstants.DEFAULT_VALUE_SEPARATOR);
140 if(e0 == null) {
141 throw new ScanException(EXPECTING_DATA_AFTER_LEFT_ACCOLADE);
142 }
143 e0.append(literal);
144 Node e1 = E();
145 e0.append(e1);
146 }
147 return e0;
148 }
149
150 private boolean isDefaultToken(Token t) {
151 return t != null && t.type == Token.Type.DEFAULT;
152 }
153
154 void advanceTokenPointer() {
155 pointer++;
156 }
157
158 void expectNotNull(Token t, String expected) {
159 if (t == null) {
160 throw new IllegalArgumentException("All tokens consumed but was expecting \"" + expected + "\"");
161 }
162 }
163
164 void expectCurlyRight(Token t) throws ScanException {
165 expectNotNull(t, "}");
166 if (t.type != Token.Type.CURLY_RIGHT) {
167 throw new ScanException("Expecting }");
168 }
169 }
170
171 Token peekAtCurentToken() {
172 if (pointer < tokenList.size()) {
173 return tokenList.get(pointer);
174 }
175 return null;
176 }
177
178 }