Skip to content

Commit 33d68ac

Browse files
committed
Added support for hierarchial parsing state
Renamed and moved "matching" functionality which was really parsing functionality
1 parent 24e115c commit 33d68ac

25 files changed

+551
-306
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package info.codesaway.bex;
2+
3+
/**
4+
* Value with an index.
5+
*
6+
* @param <T> the value's type
7+
* @since 0.13
8+
*/
9+
public interface Indexed<T> {
10+
public int getIndex();
11+
12+
public T getValue();
13+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package info.codesaway.bex;
2+
3+
import java.util.Objects;
4+
5+
/**
6+
* Value with an index.
7+
*
8+
* <p>Instances of this class are immutable if the generic class type is also immutable</p>
9+
*
10+
* @param <T> the value's type
11+
* @since 0.13
12+
*/
13+
public final class IndexedValue<T> implements Indexed<T> {
14+
// Referenced https://github.com/poetix/protonpack/blob/master/src/main/java/com/codepoetics/protonpack/Indexed.java
15+
16+
private final int index;
17+
private final T value;
18+
19+
public IndexedValue(final int index, final T value) {
20+
this.index = index;
21+
this.value = value;
22+
}
23+
24+
@Override
25+
public int getIndex() {
26+
return this.index;
27+
}
28+
29+
@Override
30+
public T getValue() {
31+
return this.value;
32+
}
33+
34+
@Override
35+
public String toString() {
36+
return this.index + " " + this.value;
37+
}
38+
39+
@Override
40+
public int hashCode() {
41+
return Objects.hash(this.index, this.value);
42+
}
43+
44+
@Override
45+
public boolean equals(final Object obj) {
46+
if (this == obj) {
47+
return true;
48+
}
49+
if (obj == null) {
50+
return false;
51+
}
52+
if (this.getClass() != obj.getClass()) {
53+
return false;
54+
}
55+
IndexedValue<?> other = (IndexedValue<?>) obj;
56+
return this.index == other.index && Objects.equals(this.value, other.value);
57+
}
58+
}

BEXCodeCompare/src/main/java/info/codesaway/bex/diff/DiffWithIndex.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@
33
import java.util.Optional;
44

55
import info.codesaway.bex.BEXSide;
6+
import info.codesaway.bex.Indexed;
67

7-
public final class DiffWithIndex {
8+
public final class DiffWithIndex implements Indexed<DiffEdit> {
89
private final DiffEdit diffEdit;
910
private final int index;
1011

@@ -17,6 +18,12 @@ public DiffEdit getDiffEdit() {
1718
return this.diffEdit;
1819
}
1920

21+
@Override
22+
public DiffEdit getValue() {
23+
return this.getDiffEdit();
24+
}
25+
26+
@Override
2027
public int getIndex() {
2128
return this.index;
2229
}

BEXCodeCompare/src/main/java/info/codesaway/bex/matching/BEXMatcher.java

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22

33
import static info.codesaway.bex.matching.BEXGroupMatchSetting.DEFAULT;
44
import static info.codesaway.bex.matching.BEXGroupMatchSetting.STOP_WHEN_VALID;
5-
import static info.codesaway.bex.matching.BEXMatchingStateOption.MISMATCHED_DELIMITERS;
6-
import static info.codesaway.bex.matching.BEXMatchingUtilities.hasNextChar;
7-
import static info.codesaway.bex.matching.BEXMatchingUtilities.hasText;
8-
import static info.codesaway.bex.matching.BEXMatchingUtilities.isWordCharacter;
9-
import static info.codesaway.bex.matching.BEXMatchingUtilities.nextChar;
10-
import static info.codesaway.bex.matching.BEXMatchingUtilities.parseJavaTextStates;
5+
import static info.codesaway.bex.parsing.BEXParsingUtilities.hasNextChar;
6+
import static info.codesaway.bex.parsing.BEXParsingUtilities.hasText;
7+
import static info.codesaway.bex.parsing.BEXParsingUtilities.isWordCharacter;
8+
import static info.codesaway.bex.parsing.BEXParsingUtilities.nextChar;
9+
import static info.codesaway.bex.parsing.BEXParsingUtilities.parseJavaTextStates;
10+
import static info.codesaway.bex.parsing.BEXParsingState.MISMATCHED_DELIMITERS;
1111
import static info.codesaway.bex.util.BEXUtilities.entry;
1212
import static info.codesaway.bex.util.BEXUtilities.getSubstring;
1313

@@ -34,6 +34,12 @@
3434
import info.codesaway.bex.IntBEXRange;
3535
import info.codesaway.bex.IntRange;
3636
import info.codesaway.bex.MutableIntBEXPair;
37+
import info.codesaway.bex.parsing.BEXParsingLanguage;
38+
import info.codesaway.bex.parsing.BEXString;
39+
import info.codesaway.bex.parsing.ParsingDelimiterResult;
40+
import info.codesaway.bex.parsing.ParsingDelimiterState;
41+
import info.codesaway.bex.parsing.ParsingLanguage;
42+
import info.codesaway.bex.parsing.ParsingState;
3743
import info.codesaway.util.regex.Matcher;
3844
import info.codesaway.util.regex.Pattern;
3945

@@ -55,12 +61,12 @@ public final class BEXMatcher implements BEXMatchResult {
5561
private CharSequence text;
5662

5763
// TODO: should I add a public getter for language?
58-
private MatchingLanguage language;
64+
private ParsingLanguage language;
5965

6066
/**
6167
* Map from range to text state
6268
*/
63-
private ImmutableIntRangeMap<MatchingStateOption> textStateMap;
69+
private ImmutableIntRangeMap<ParsingState> textStateMap;
6470

6571
/**
6672
* Offset used when resolving indexes in textStateMap (allows sharing textStateMap such as in BEXString)
@@ -85,11 +91,11 @@ public final class BEXMatcher implements BEXMatchResult {
8591
private Map<String, List<IntBEXRange>> multipleValuesMap = Collections.emptyMap();
8692

8793
BEXMatcher(final BEXPattern parent, final CharSequence text) {
88-
this(parent, text, BEXMatchingLanguage.JAVA, parseJavaTextStates(text), 0);
94+
this(parent, text, BEXParsingLanguage.JAVA, parseJavaTextStates(text), 0);
8995
}
9096

91-
BEXMatcher(final BEXPattern parent, final CharSequence text, final MatchingLanguage language,
92-
final ImmutableIntRangeMap<MatchingStateOption> textStateMap, final int offset) {
97+
BEXMatcher(final BEXPattern parent, final CharSequence text, final ParsingLanguage language,
98+
final ImmutableIntRangeMap<ParsingState> textStateMap, final int offset) {
9399
this.parentPattern = parent;
94100
this.text = text;
95101
this.language = language;
@@ -309,7 +315,7 @@ private boolean match(final int from) {
309315
if (i == 0) {
310316
// TODO: check that state is valid
311317
int startWithOffset = matcher.start() + this.offset;
312-
Entry<IntRange, MatchingStateOption> entry = this.textStateMap.getEntry(startWithOffset);
318+
Entry<IntRange, ParsingState> entry = this.textStateMap.getEntry(startWithOffset);
313319

314320
boolean isValid;
315321
if (entry != null && startWithOffset != entry.getKey().getStart()
@@ -340,7 +346,7 @@ private boolean match(final int from) {
340346
}
341347

342348
int startWithOffset = start + this.offset;
343-
Entry<IntRange, MatchingStateOption> entry = this.textStateMap.getEntry(startWithOffset);
349+
Entry<IntRange, ParsingState> entry = this.textStateMap.getEntry(startWithOffset);
344350

345351
BEXMatchingState initialState;
346352
if (entry != null && startWithOffset != entry.getKey().getStart()
@@ -558,7 +564,7 @@ private BEXMatchingState search(final int start, final int end,
558564
// TODO: how to handle multiple levels? Currently, only get top most level
559565
// For example, JSP expression within String literal gets JSP expression, but doesn't know about String literal outside
560566

561-
MatchingStateOption stateOption = null;
567+
ParsingState stateOption = null;
562568

563569
if (state != null) {
564570
delimiters.addAll(state.getDelimiters());
@@ -568,7 +574,7 @@ private BEXMatchingState search(final int start, final int end,
568574

569575
for (int i = start; i < end; i++) {
570576
int indexWithOffset = i + this.offset;
571-
Entry<IntRange, MatchingStateOption> entry = this.textStateMap.getEntry(indexWithOffset);
577+
Entry<IntRange, ParsingState> entry = this.textStateMap.getEntry(indexWithOffset);
572578

573579
if (entry != null && !entry.getValue().isCode()) {
574580
// Has a state option
@@ -589,15 +595,15 @@ private BEXMatchingState search(final int start, final int end,
589595
delimiters.add(startDelimiter.get());
590596
i += startDelimiter.get().getLeft().length() - 1;
591597
} else {
592-
MatchingDelimiterState delimiterState = this.language.findEndDelimiter(delimiters.peekLast(),
598+
ParsingDelimiterState delimiterState = this.language.findEndDelimiter(delimiters.peekLast(),
593599
this.text, i, settings);
594-
MatchingDelimiterResult result = delimiterState.getResult();
600+
ParsingDelimiterResult result = delimiterState.getResult();
595601

596-
if (result == MatchingDelimiterResult.MISMATCHED) {
602+
if (result == ParsingDelimiterResult.MISMATCHED) {
597603
// XXX: should position be after the mismatch - so can try again at this point
598604
return new BEXMatchingState(i + delimiterState.getDelimiter().length(), delimiters,
599605
MISMATCHED_DELIMITERS);
600-
} else if (result == MatchingDelimiterResult.FOUND) {
606+
} else if (result == ParsingDelimiterResult.FOUND) {
601607
// Remove last delimiter
602608
delimiters.removeLast();
603609

@@ -770,7 +776,7 @@ public BEXMatcher reset() {
770776
*/
771777
public BEXMatcher reset(final CharSequence input) {
772778
this.text = input;
773-
this.language = BEXMatchingLanguage.JAVA;
779+
this.language = BEXParsingLanguage.JAVA;
774780
this.textStateMap = parseJavaTextStates(input);
775781
this.offset = 0;
776782
return this.reset();

BEXCodeCompare/src/main/java/info/codesaway/bex/matching/BEXMatchingState.java

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package info.codesaway.bex.matching;
22

3-
import static info.codesaway.bex.matching.BEXMatchingStateOption.MISMATCHED_DELIMITERS;
3+
import static info.codesaway.bex.parsing.BEXParsingState.MISMATCHED_DELIMITERS;
44
import static info.codesaway.bex.util.BEXUtilities.not;
55

66
import java.util.ArrayList;
@@ -11,26 +11,28 @@
1111
import java.util.Set;
1212

1313
import info.codesaway.bex.BEXPair;
14+
import info.codesaway.bex.parsing.BEXParsingState;
15+
import info.codesaway.bex.parsing.ParsingState;
1416

1517
final class BEXMatchingState {
1618
private final int position;
1719
private final Collection<BEXPair<String>> delimiters;
1820
// private final String brackets;
19-
private final Set<MatchingStateOption> options;
21+
private final Set<ParsingState> options;
2022

2123
public static final BEXMatchingState DEFAULT = new BEXMatchingState(-1, Collections.emptyList());
2224

2325
BEXMatchingState(final int position, final Collection<BEXPair<String>> delimiters,
24-
final BEXMatchingStateOption... options) {
26+
final BEXParsingState... options) {
2527
this.position = position;
2628

2729
this.delimiters = delimiters.isEmpty()
2830
? Collections.emptyList()
2931
: Collections.unmodifiableCollection(new ArrayList<>(delimiters));
3032

31-
EnumSet<BEXMatchingStateOption> optionSet = EnumSet.noneOf(BEXMatchingStateOption.class);
33+
EnumSet<BEXParsingState> optionSet = EnumSet.noneOf(BEXParsingState.class);
3234

33-
for (BEXMatchingStateOption option : options) {
35+
for (BEXParsingState option : options) {
3436
if (option != null) {
3537
optionSet.add(option);
3638
}
@@ -40,16 +42,16 @@ final class BEXMatchingState {
4042
}
4143

4244
BEXMatchingState(final int position, final Collection<BEXPair<String>> delimiters,
43-
final MatchingStateOption... options) {
45+
final ParsingState... options) {
4446
this.position = position;
4547

4648
this.delimiters = delimiters.isEmpty()
4749
? Collections.emptyList()
4850
: Collections.unmodifiableCollection(new ArrayList<>(delimiters));
4951

50-
Set<MatchingStateOption> optionSet = new HashSet<>();
52+
Set<ParsingState> optionSet = new HashSet<>();
5153

52-
for (MatchingStateOption option : options) {
54+
for (ParsingState option : options) {
5355
if (option != null) {
5456
optionSet.add(option);
5557
}
@@ -66,7 +68,7 @@ public Collection<BEXPair<String>> getDelimiters() {
6668
return this.delimiters;
6769
}
6870

69-
public Set<MatchingStateOption> getOptions() {
71+
public Set<ParsingState> getOptions() {
7072
return this.options;
7173
}
7274

@@ -90,13 +92,13 @@ public boolean isValid(final int expectedPosition) {
9092
return this.isValid(expectedPosition, Collections.emptySet());
9193
}
9294

93-
public boolean isValid(final int expectedPosition, final Set<MatchingStateOption> ignoreOptions) {
95+
public boolean isValid(final int expectedPosition, final Set<ParsingState> ignoreOptions) {
9496
return (this.position == expectedPosition || expectedPosition == -1)
9597
&& this.delimiters.isEmpty()
9698
&& this.isOptionsEmpty(ignoreOptions);
9799
}
98100

99-
private boolean isOptionsEmpty(final Set<MatchingStateOption> ignoreOptions) {
101+
private boolean isOptionsEmpty(final Set<ParsingState> ignoreOptions) {
100102
if (ignoreOptions.isEmpty() || this.options.isEmpty()) {
101103
return this.options.isEmpty();
102104
} else {

BEXCodeCompare/src/main/java/info/codesaway/bex/matching/BEXPattern.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22

33
import static info.codesaway.bex.matching.BEXGroupMatchSetting.MATCH_ANGLE_BRACKETS;
44
import static info.codesaway.bex.matching.BEXGroupMatchSetting.OPTIONAL;
5-
import static info.codesaway.bex.matching.BEXMatchingUtilities.currentChar;
6-
import static info.codesaway.bex.matching.BEXMatchingUtilities.hasNextChar;
7-
import static info.codesaway.bex.matching.BEXMatchingUtilities.hasText;
8-
import static info.codesaway.bex.matching.BEXMatchingUtilities.isWordCharacter;
9-
import static info.codesaway.bex.matching.BEXMatchingUtilities.nextChar;
10-
import static info.codesaway.bex.matching.BEXMatchingUtilities.previousChar;
11-
import static info.codesaway.bex.matching.BEXMatchingUtilities.stringChar;
5+
import static info.codesaway.bex.parsing.BEXParsingUtilities.currentChar;
6+
import static info.codesaway.bex.parsing.BEXParsingUtilities.hasNextChar;
7+
import static info.codesaway.bex.parsing.BEXParsingUtilities.hasText;
8+
import static info.codesaway.bex.parsing.BEXParsingUtilities.isWordCharacter;
9+
import static info.codesaway.bex.parsing.BEXParsingUtilities.nextChar;
10+
import static info.codesaway.bex.parsing.BEXParsingUtilities.previousChar;
11+
import static info.codesaway.bex.parsing.BEXParsingUtilities.stringChar;
1212

1313
import java.util.ArrayList;
1414
import java.util.Collections;
@@ -17,6 +17,7 @@
1717
import java.util.Map;
1818
import java.util.concurrent.ConcurrentHashMap;
1919

20+
import info.codesaway.bex.parsing.BEXString;
2021
import info.codesaway.util.regex.Pattern;
2122

2223
public final class BEXPattern {

BEXCodeCompare/src/main/java/info/codesaway/bex/matching/MatchingDelimiterResult.java

Lines changed: 0 additions & 5 deletions
This file was deleted.

BEXCodeCompare/src/main/java/info/codesaway/bex/matching/MatchingDelimiterState.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)