forked from jasder/antlr
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>();
|
List<Integer> reach = new ArrayList<Integer>();
|
||||||
int prevAcceptAddr = Integer.MAX_VALUE;
|
int prevAcceptAddr = Integer.MAX_VALUE;
|
||||||
int prevAcceptLastCharIndex = -1;
|
int prevAcceptLastCharIndex = -1;
|
||||||
|
int prevAcceptInputMarker = -1;
|
||||||
|
int firstAcceptInputMarker = -1;
|
||||||
addToClosure(closure, ip);
|
addToClosure(closure, ip);
|
||||||
do { // while more work
|
do { // while more work
|
||||||
c = input.LA(1);
|
c = input.LA(1);
|
||||||
|
@ -238,12 +240,15 @@ processOneChar:
|
||||||
// choose longest match so far regardless of rule priority
|
// choose longest match so far regardless of rule priority
|
||||||
System.out.println("replacing old best match @ "+prevAcceptAddr);
|
System.out.println("replacing old best match @ "+prevAcceptAddr);
|
||||||
prevAcceptAddr = ip-1;
|
prevAcceptAddr = ip-1;
|
||||||
|
prevAcceptInputMarker = input.mark();
|
||||||
|
firstAcceptInputMarker = prevAcceptInputMarker;
|
||||||
}
|
}
|
||||||
else if ( tokenLastCharIndex == prevAcceptLastCharIndex ) {
|
else if ( tokenLastCharIndex == prevAcceptLastCharIndex ) {
|
||||||
// choose first rule matched if match is of same length
|
// choose first rule matched if match is of same length
|
||||||
if ( ip-1 < prevAcceptAddr ) { // it will see both accepts for ambig rules
|
if ( ip-1 < prevAcceptAddr ) { // it will see both accepts for ambig rules
|
||||||
System.out.println("replacing old best match @ "+prevAcceptAddr);
|
System.out.println("replacing old best match @ "+prevAcceptAddr);
|
||||||
prevAcceptAddr = ip-1;
|
prevAcceptAddr = ip-1;
|
||||||
|
prevAcceptInputMarker = input.mark();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if we reach accept state, toss out any addresses in rest
|
// 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;
|
if ( prevAcceptAddr >= code.length ) return Token.INVALID_TOKEN_TYPE;
|
||||||
int ttype = getShort(code, prevAcceptAddr+1);
|
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;
|
return ttype;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,10 @@ options {
|
||||||
@header {
|
@header {
|
||||||
package org.antlr.v4.codegen;
|
package org.antlr.v4.codegen;
|
||||||
import org.antlr.v4.tool.GrammarAST;
|
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
|
ebnf
|
||||||
|
@init {
|
||||||
|
GrammarASTWithOptions blk = (GrammarASTWithOptions)$start.getChild(0);
|
||||||
|
String greedyOption = blk.getOption("greedy");
|
||||||
|
}
|
||||||
: ^(astBlockSuffix block)
|
: ^(astBlockSuffix block)
|
||||||
| {
|
| {
|
||||||
SplitInstr S = new SplitInstr(2);
|
SplitInstr S = new SplitInstr(2);
|
||||||
|
@ -97,15 +105,16 @@ ebnf
|
||||||
int start=ip;
|
int start=ip;
|
||||||
SplitInstr S = new SplitInstr(2);
|
SplitInstr S = new SplitInstr(2);
|
||||||
emit(S);
|
emit(S);
|
||||||
int blk = ip;
|
int blkStart = ip;
|
||||||
}
|
}
|
||||||
^(CLOSURE block)
|
^(CLOSURE block)
|
||||||
{
|
{
|
||||||
JumpInstr J = new JumpInstr();
|
JumpInstr J = new JumpInstr();
|
||||||
emit(J);
|
emit(J);
|
||||||
J.target = start;
|
J.target = start;
|
||||||
S.addrs.add(blk);
|
S.addrs.add(blkStart);
|
||||||
S.addrs.add(ip); // reverse for nongreedy
|
S.addrs.add(ip);
|
||||||
|
if ( greedyOption!=null && greedyOption.equals("false") ) Collections.reverse(S.addrs);
|
||||||
}
|
}
|
||||||
| {int start=ip;} ^(POSITIVE_CLOSURE block)
|
| {int start=ip;} ^(POSITIVE_CLOSURE block)
|
||||||
{
|
{
|
||||||
|
@ -114,6 +123,7 @@ ebnf
|
||||||
int stop = ip;
|
int stop = ip;
|
||||||
S.addrs.add(start);
|
S.addrs.add(start);
|
||||||
S.addrs.add(stop);
|
S.addrs.add(stop);
|
||||||
|
if ( greedyOption!=null && greedyOption.equals("false") ) Collections.reverse(S.addrs);
|
||||||
}
|
}
|
||||||
| block
|
| block
|
||||||
;
|
;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue