Skip to content

Commit 33b68c6

Browse files
committed
refactor: Improved parser code
1 parent 687c9ce commit 33b68c6

File tree

1 file changed

+51
-61
lines changed

1 file changed

+51
-61
lines changed

src/main/java/org/codejive/properties/PropertiesParser.java

Lines changed: 51 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import java.util.Objects;
66
import java.util.Spliterators;
77
import java.util.function.Consumer;
8-
import java.util.function.Supplier;
8+
import java.util.function.Function;
99
import java.util.stream.Stream;
1010
import java.util.stream.StreamSupport;
1111

@@ -72,50 +72,46 @@ public String toString() {
7272
private final Reader rdr;
7373

7474
private Type state;
75-
private int ch;
7675
private int pch;
77-
StringBuilder chr;
7876
StringBuilder str;
7977
boolean hasEscapes;
8078

8179
public PropertiesParser(Reader rdr) throws IOException {
8280
this.rdr = rdr;
8381
state = null;
84-
chr = new StringBuilder();
8582
str = new StringBuilder();
86-
pch = -1;
87-
nextChar();
83+
readChar();
8884
}
8985

9086
public Token nextToken() throws IOException {
91-
Supplier<Boolean> isValid = () -> false;
87+
int ch = peekChar();
88+
if (isEof(ch)) {
89+
return null;
90+
}
91+
Function<Integer, Boolean> isValid = (c) -> false;
9292
Type nextState = null;
93-
while (true) {
94-
if (state == null) {
95-
if (isCommentChar(ch)) {
96-
state = Type.COMMENT;
97-
isValid = () -> !isEol(ch);
98-
nextState = null;
99-
} else if (isWhitespaceChar(ch)) {
100-
state = Type.WHITESPACE;
101-
isValid = () -> isWhitespaceChar(ch);
102-
nextState = null;
103-
} else if (isEof(ch)) {
104-
return null;
105-
} else {
106-
state = Type.KEY;
107-
isValid = () -> !isSeparatorChar(ch);
108-
nextState = Type.SEPARATOR;
109-
}
110-
} else if (state == Type.SEPARATOR) {
111-
isValid = () -> isSeparatorChar(ch);
112-
nextState = Type.VALUE;
113-
} else if (state == Type.VALUE) {
114-
isValid = () -> !isEol(ch);
115-
nextState = null;
93+
if (state == null) {
94+
if (isCommentChar(ch)) {
95+
state = Type.COMMENT;
96+
isValid = this::isNotEol;
97+
} else if (isWhitespaceChar(ch)) {
98+
state = Type.WHITESPACE;
99+
isValid = this::isWhitespaceChar;
100+
} else {
101+
state = Type.KEY;
102+
isValid = (c) -> !isSeparatorChar(c);
103+
nextState = Type.SEPARATOR;
116104
}
117-
if (isValid.get()) {
118-
nextChar();
105+
} else if (state == Type.SEPARATOR) {
106+
isValid = this::isSeparatorChar;
107+
nextState = Type.VALUE;
108+
} else if (state == Type.VALUE) {
109+
isValid = this::isNotEol;
110+
}
111+
while (true) {
112+
if (isValid.apply(ch)) {
113+
addChar(readChar());
114+
ch = peekChar();
119115
} else {
120116
String text = (state == Type.VALUE || state == Type.COMMENT) ? trimmedString() : string();
121117
Token token = hasEscapes ? new Token(state, text, unescape(text)) : new Token(state, text);
@@ -126,29 +122,29 @@ public Token nextToken() throws IOException {
126122
}
127123
}
128124

129-
private void nextChar() throws IOException {
130-
str.append(chr);
131-
if (chr.length() > 0 && chr.charAt(0) == '\\') {
132-
hasEscapes = true;
133-
}
134-
if (pch == -1) {
135-
ch = rdr.read();
136-
} else {
137-
ch = pch;
138-
pch = -1;
139-
}
140-
chr.setLength(0);
141-
chr.append((char) ch);
125+
private int peekChar() {
126+
return pch;
127+
}
128+
129+
private int readChar() throws IOException {
130+
int ch = pch;
131+
pch = rdr.read();
132+
return ch;
133+
}
134+
135+
private void addChar(int ch) throws IOException {
136+
str.append((char) ch);
142137
if (ch == '\\') {
143-
int ch2 = rdr.read();
144-
chr.append((char) ch2);
138+
hasEscapes = true;
139+
int ch2 = readChar();
140+
str.append((char) ch2);
145141
if (ch2 == 'u') {
146142
for (int i = 0; i < 4; i++) {
147-
int chu = rdr.read();
143+
int chu = readChar();
148144
if (!isHexDigitChar(chu)) {
149145
throw new IOException("Invalid unicode escape character: " + chu);
150146
}
151-
chr.append((char) chu);
147+
str.append((char) chu);
152148
}
153149
} else {
154150
readEol(ch2);
@@ -193,16 +189,10 @@ private static String unescape(String escape) {
193189
return txt.toString();
194190
}
195191

196-
private void readEol(int cch) throws IOException {
197-
if (cch == '\n') {
198-
// If the next char is a \r we'll add it
199-
// to the current char buffer, otherwise
200-
// we'll save the character for next time.
201-
int nch = rdr.read();
202-
if (nch == '\r') {
203-
chr.append((char) nch);
204-
} else {
205-
pch = nch;
192+
private void readEol(int ch) throws IOException {
193+
if (ch == '\n') {
194+
if (peekChar() == '\r') {
195+
str.append((char) readChar());
206196
}
207197
}
208198
}
@@ -243,8 +233,8 @@ private boolean isHexDigitChar(int ch) {
243233
return Character.isDigit(ch) || (uch >= 'A' && uch <= 'F');
244234
}
245235

246-
private boolean isEol(int ch) {
247-
return ch == '\n' || ch == '\r' || isEof(ch);
236+
private boolean isNotEol(int ch) {
237+
return ch != '\n' && ch != '\r' && !isEof(ch);
248238
}
249239

250240
private boolean isEof(int ch) {

0 commit comments

Comments
 (0)