handles nongreedy + and * loops. rewinds properly to last good accept if we kept going and failed.
[git-p4: depot-paths = "//depot/code/antlr4/main/": change = 6828]
This commit is contained in:
parent
6b55114dd0
commit
541350bbe3
|
@ -193,6 +193,8 @@ workLoop:
|
|||
List<Integer> reach = new ArrayList<Integer>();
|
||||
int prevAcceptAddr = Integer.MAX_VALUE;
|
||||
int prevAcceptLastCharIndex = -1;
|
||||
int prevAcceptInputMarker = -1;
|
||||
int firstAcceptInputMarker = -1;
|
||||
addToClosure(closure, ip);
|
||||
do { // while more work
|
||||
c = input.LA(1);
|
||||
|
@ -238,12 +240,15 @@ processOneChar:
|
|||
// choose longest match so far regardless of rule priority
|
||||
System.out.println("replacing old best match @ "+prevAcceptAddr);
|
||||
prevAcceptAddr = ip-1;
|
||||
prevAcceptInputMarker = input.mark();
|
||||
firstAcceptInputMarker = prevAcceptInputMarker;
|
||||
}
|
||||
else if ( tokenLastCharIndex == prevAcceptLastCharIndex ) {
|
||||
// choose first rule matched if match is of same length
|
||||
if ( ip-1 < prevAcceptAddr ) { // it will see both accepts for ambig rules
|
||||
System.out.println("replacing old best match @ "+prevAcceptAddr);
|
||||
prevAcceptAddr = ip-1;
|
||||
prevAcceptInputMarker = input.mark();
|
||||
}
|
||||
}
|
||||
// if we reach accept state, toss out any addresses in rest
|
||||
|
@ -285,6 +290,11 @@ processOneChar:
|
|||
|
||||
if ( prevAcceptAddr >= code.length ) return Token.INVALID_TOKEN_TYPE;
|
||||
int ttype = getShort(code, prevAcceptAddr+1);
|
||||
System.out.println("done at index "+input.index());
|
||||
System.out.println("accept marker="+prevAcceptInputMarker);
|
||||
input.rewind(prevAcceptInputMarker); // does nothing if we accept'd at input.index() but might need to rewind
|
||||
input.release(firstAcceptInputMarker); // kill any other markers in stream we made
|
||||
System.out.println("leaving with index "+input.index());
|
||||
return ttype;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,10 @@ options {
|
|||
@header {
|
||||
package org.antlr.v4.codegen;
|
||||
import org.antlr.v4.tool.GrammarAST;
|
||||
import org.antlr.v4.tool.GrammarASTWithOptions;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -83,6 +87,10 @@ treeSpec
|
|||
;
|
||||
|
||||
ebnf
|
||||
@init {
|
||||
GrammarASTWithOptions blk = (GrammarASTWithOptions)$start.getChild(0);
|
||||
String greedyOption = blk.getOption("greedy");
|
||||
}
|
||||
: ^(astBlockSuffix block)
|
||||
| {
|
||||
SplitInstr S = new SplitInstr(2);
|
||||
|
@ -97,15 +105,16 @@ ebnf
|
|||
int start=ip;
|
||||
SplitInstr S = new SplitInstr(2);
|
||||
emit(S);
|
||||
int blk = ip;
|
||||
int blkStart = ip;
|
||||
}
|
||||
^(CLOSURE block)
|
||||
{
|
||||
JumpInstr J = new JumpInstr();
|
||||
emit(J);
|
||||
J.target = start;
|
||||
S.addrs.add(blk);
|
||||
S.addrs.add(ip); // reverse for nongreedy
|
||||
S.addrs.add(blkStart);
|
||||
S.addrs.add(ip);
|
||||
if ( greedyOption!=null && greedyOption.equals("false") ) Collections.reverse(S.addrs);
|
||||
}
|
||||
| {int start=ip;} ^(POSITIVE_CLOSURE block)
|
||||
{
|
||||
|
@ -114,6 +123,7 @@ ebnf
|
|||
int stop = ip;
|
||||
S.addrs.add(start);
|
||||
S.addrs.add(stop);
|
||||
if ( greedyOption!=null && greedyOption.equals("false") ) Collections.reverse(S.addrs);
|
||||
}
|
||||
| block
|
||||
;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue