Return absolute minimum capture data from OnigRegExp

This commit is contained in:
Corey Johnson & Nathan Sobo
2012-08-08 11:22:50 -06:00
parent 93f21207ab
commit 2a945838f5
3 changed files with 41 additions and 50 deletions

View File

@@ -37,37 +37,27 @@ public:
return resultArray;
}
CefRefPtr<CefV8Value> GetCaptureTree(CefRefPtr<CefV8Value> string, CefRefPtr<CefV8Value> index) {
CefRefPtr<CefV8Value> GetCaptureIndices(CefRefPtr<CefV8Value> string, CefRefPtr<CefV8Value> index) {
OnigResult *result = [m_regex search:stringFromCefV8Value(string) start:index->GetIntValue()];
if ([result count] == 0) return CefV8Value::CreateNull();
return BuildCaptureTree(result);
return BuildCaptureIndices(result);
}
CefRefPtr<CefV8Value> BuildCaptureTree(OnigResult *result) {
int index = 0;
return BuildCaptureTree(result, index);
}
CefRefPtr<CefV8Value> BuildCaptureIndices(OnigResult *result) {
CefRefPtr<CefV8Value> array = CefV8Value::CreateArray();
int i = 0;
CefRefPtr<CefV8Value> BuildCaptureTree(OnigResult *result, int &index) {
int currentIndex = index++;
int startPosition = [result locationAt:currentIndex];
int endPosition = startPosition + [result lengthAt:currentIndex];
CefRefPtr<CefV8Value> tree = CefV8Value::CreateArray();
int i = 0;
tree->SetValue(i++, CefV8Value::CreateInt(currentIndex));
tree->SetValue(i++, CefV8Value::CreateInt(startPosition));
tree->SetValue(i++, CefV8Value::CreateInt(endPosition));
while (index < [result count] && [result locationAt:index] < endPosition) {
if ([result lengthAt:index] == 0) {
index++;
} else {
tree->SetValue(i++, BuildCaptureTree(result, index));
}
int resultCount = [result count];
for (int index = 0; index < resultCount; index++) {
int captureLength = [result lengthAt:index];
if (captureLength == 0) continue;
int captureStart = [result locationAt:index];
array->SetValue(i++, CefV8Value::CreateInt(index));
array->SetValue(i++, CefV8Value::CreateInt(captureStart));
array->SetValue(i++, CefV8Value::CreateInt(captureStart + captureLength));
}
return tree;
return array;
}
CefRefPtr<CefV8Value> CaptureCount() {
@@ -91,11 +81,11 @@ bool OnigRegexpExtension::Execute(const CefString& name,
CefRefPtr<CefV8Value>& retval,
CefString& exception) {
if (name == "getCaptureTree") {
if (name == "getCaptureIndices") {
CefRefPtr<CefV8Value> string = arguments[0];
CefRefPtr<CefV8Value> index = arguments.size() > 1 ? arguments[1] : CefV8Value::CreateInt(0);
OnigRegexpUserData *userData = (OnigRegexpUserData *)object->GetUserData().get();
retval = userData->GetCaptureTree(string, index);
retval = userData->GetCaptureIndices(string, index);
return true;
}
else if (name == "buildOnigRegExp") {

View File

@@ -92,22 +92,17 @@ class Rule
regexPatternPairs
getNextTokens: (stack, line, position) ->
captureTree = @regex.getCaptureTree(line, position)
return {} unless captureTree?[2] > 0 # ignore zero-length matches
captureIndices = @regex.getCaptureIndices(line, position)
firstCapture = captureTree[3]
[firstCaptureIndex, firstCaptureStart, firstCaptureEnd] = firstCapture
return {} unless captureIndices?[2] > 0 # ignore zero-length matches
shiftCapture(captureIndices)
[firstCaptureIndex, firstCaptureStart, firstCaptureEnd] = captureIndices
pattern = @patternsByCaptureIndex[firstCaptureIndex]
@adjustCaptureTreeIndices(firstCapture, firstCaptureIndex)
nextTokens = pattern.handleMatch(stack, line, firstCapture)
nextTokens = pattern.handleMatch(stack, line, captureIndices)
{ nextTokens, tokensStartPosition: firstCaptureStart, tokensEndPosition: firstCaptureEnd }
adjustCaptureTreeIndices: (tree, startIndex) ->
tree[0] -= startIndex
for capture in tree[3..]
@adjustCaptureTreeIndices(capture, startIndex)
getNextMatch: (line, position) ->
nextMatch = null
matchedPattern = null
@@ -156,16 +151,16 @@ class Pattern
rule = @grammar.ruleForInclude(@include)
rule.getNextMatch(line, position)
else
{ match: @regex.getCaptureTree(line, position), pattern: this }
{ match: @regex.getCaptureIndices(line, position), pattern: this }
handleMatch: (stack, line, captureTree) ->
handleMatch: (stack, line, captureIndices) ->
scopes = _.pluck(stack, "scopeName")
scopes.push(@scopeName) unless @popRule
if @captures
tokens = @getTokensForCaptureTree(line, captureTree, scopes)
tokens = @getTokensForCaptureIndices(line, captureIndices, scopes)
else
[start, end] = captureTree[1..2]
[start, end] = captureIndices[1..2]
tokens = [{ value: line[start...end], scopes: scopes }]
if @pushRule
@@ -175,22 +170,24 @@ class Pattern
tokens
getTokensForCaptureTree: (line, parentCapture, scopes) ->
[parentCaptureIndex, parentCaptureStart, parentCaptureEnd, childCaptures...] = parentCapture
getTokensForCaptureIndices: (line, captureIndices, scopes, indexOffset=captureIndices[0]) ->
[parentCaptureIndex, parentCaptureStart, parentCaptureEnd] = shiftCapture(captureIndices)
relativeParentCaptureIndex = parentCaptureIndex - indexOffset
tokens = []
if scope = @captures[parentCaptureIndex]?.name
if scope = @captures[relativeParentCaptureIndex]?.name
scopes = scopes.concat(scope)
previousChildCaptureEnd = parentCaptureStart
for childCapture in childCaptures
[childCaptureIndex, childCaptureStart, childCaptureEnd] = childCapture
while captureIndices.length and captureIndices[1] < parentCaptureEnd
[childCaptureIndex, childCaptureStart, childCaptureEnd] = captureIndices
if childCaptureStart > previousChildCaptureEnd
tokens.push
value: line[previousChildCaptureEnd...childCaptureStart]
scopes: scopes
captureTokens = @getTokensForCaptureTree(line, childCapture, scopes)
captureTokens = @getTokensForCaptureIndices(line, captureIndices, scopes, indexOffset)
tokens.push(captureTokens...)
previousChildCaptureEnd = childCaptureEnd
@@ -200,3 +197,7 @@ class Pattern
scopes: scopes
tokens
shiftCapture = (captureIndices) ->
[captureIndices.shift(), captureIndices.shift(), captureIndices.shift()]

View File

@@ -1,7 +1,7 @@
(function() {
native function buildOnigRegExp(source);
native function search(string, index);
native function getCaptureTree(source, index);
native function getCaptureIndices(source, index);
native function getCaptureCount();
function OnigRegExp(source) {
@@ -13,7 +13,7 @@
}
OnigRegExp.prototype.search = search;
OnigRegExp.prototype.getCaptureTree = getCaptureTree;
OnigRegExp.prototype.getCaptureIndices = getCaptureIndices;
OnigRegExp.prototype.getCaptureCount = getCaptureCount;
this.OnigRegExp = OnigRegExp;