Skip to content

Commit

Permalink
Make doing 2,3 and 3 steps Next/Prev more efficient
Browse files Browse the repository at this point in the history
  • Loading branch information
nielsbasjes committed Nov 20, 2017
1 parent f822bce commit a2ccf33
Show file tree
Hide file tree
Showing 5 changed files with 211 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,5 @@ v3.2
- New matching language feature: Is this value present in a predefined set of values?
- New matching language feature: Basic String concatenation
- New matching language feature: Variables
- Make doing 2,3 and 3 steps Next/Prev more efficient

Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,13 @@ VALUE : DOUBLEQUOTE ( '\\' [btnfr"'\\] | ~[\\"] )* DOUBLEQUOTE ;

UP : '^' ;
NEXT : '>' ;
NEXT2 : '>>' ;
NEXT3 : '>>>' ;
NEXT4 : '>>>>' ;
PREV : '<' ;
PREV2 : '<<' ;
PREV3 : '<<<' ;
PREV4 : '<<<<' ;
DOT : '.' ;
MINUS : '-' ;
STAR : '*' ;
Expand Down Expand Up @@ -77,7 +83,13 @@ basePath : value=VALUE #pathFixedValue
path : DOT numberRange name=VALUENAME (nextStep=path)? #stepDown
| UP (nextStep=path)? #stepUp
| NEXT (nextStep=path)? #stepNext
| NEXT2 (nextStep=path)? #stepNext2
| NEXT3 (nextStep=path)? #stepNext3
| NEXT4 (nextStep=path)? #stepNext4
| PREV (nextStep=path)? #stepPrev
| PREV2 (nextStep=path)? #stepPrev2
| PREV3 (nextStep=path)? #stepPrev3
| PREV4 (nextStep=path)? #stepPrev4
| EQUALS value=VALUE (nextStep=path)? #stepEqualsValue
| NOTEQUALS value=VALUE (nextStep=path)? #stepNotEqualsValue
| STARTSWITH value=VALUE (nextStep=path)? #stepStartsWithValue
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,9 @@
import nl.basjes.parse.useragent.analyze.treewalker.steps.value.StepWordRange;
import nl.basjes.parse.useragent.analyze.treewalker.steps.walk.StepDown;
import nl.basjes.parse.useragent.analyze.treewalker.steps.walk.StepNext;
import nl.basjes.parse.useragent.analyze.treewalker.steps.walk.StepNextN;
import nl.basjes.parse.useragent.analyze.treewalker.steps.walk.StepPrev;
import nl.basjes.parse.useragent.analyze.treewalker.steps.walk.StepPrevN;
import nl.basjes.parse.useragent.analyze.treewalker.steps.walk.StepUp;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerBaseVisitor;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser;
Expand All @@ -58,8 +60,14 @@
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepDownContext;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepEndsWithValueContext;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepEqualsValueContext;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepNext2Context;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepNext3Context;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepNext4Context;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepNextContext;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepNotEqualsValueContext;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepPrev2Context;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepPrev3Context;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepPrev4Context;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepPrevContext;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepStartsWithValueContext;
import nl.basjes.parse.useragent.parser.UserAgentTreeWalkerParser.StepUpContext;
Expand Down Expand Up @@ -330,6 +338,7 @@ public Void visitStepUp(StepUpContext ctx) {
return null; // Void
}

//----
@Override
public Void visitStepNext(StepNextContext ctx) {
fromHereItCannotBeInHashMapAnymore();
Expand All @@ -338,6 +347,29 @@ public Void visitStepNext(StepNextContext ctx) {
return null; // Void
}

private Void doStepNextN(PathContext nextStep, int nextSteps) {
fromHereItCannotBeInHashMapAnymore();
add(new StepNextN(nextSteps));
visitNext(nextStep);
return null; // Void
}

@Override
public Void visitStepNext2(StepNext2Context ctx) {
return doStepNextN(ctx.nextStep, 2);
}

@Override
public Void visitStepNext3(StepNext3Context ctx) {
return doStepNextN(ctx.nextStep, 3);
}

@Override
public Void visitStepNext4(StepNext4Context ctx) {
return doStepNextN(ctx.nextStep, 4);
}

//----
@Override
public Void visitStepPrev(StepPrevContext ctx) {
fromHereItCannotBeInHashMapAnymore();
Expand All @@ -346,6 +378,29 @@ public Void visitStepPrev(StepPrevContext ctx) {
return null; // Void
}

private Void doStepPrevN(PathContext nextStep, int prevSteps) {
fromHereItCannotBeInHashMapAnymore();
add(new StepPrevN(prevSteps));
visitNext(nextStep);
return null; // Void
}

@Override
public Void visitStepPrev2(StepPrev2Context ctx) {
return doStepPrevN(ctx.nextStep, 2);
}

@Override
public Void visitStepPrev3(StepPrev3Context ctx) {
return doStepPrevN(ctx.nextStep, 3);
}

@Override
public Void visitStepPrev4(StepPrev4Context ctx) {
return doStepPrevN(ctx.nextStep, 4);
}

//----
@Override
public Void visitStepEqualsValue(StepEqualsValueContext ctx) {
add(new StepEquals(ctx.value.getText()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* Yet Another UserAgent Analyzer
* Copyright (C) 2013-2017 Niels Basjes
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package nl.basjes.parse.useragent.analyze.treewalker.steps.walk;

import nl.basjes.parse.useragent.analyze.treewalker.steps.Step;
import nl.basjes.parse.useragent.analyze.treewalker.steps.WalkList.WalkResult;
import org.antlr.v4.runtime.tree.ParseTree;

public class StepNextN extends Step {

private int steps = 1;

public StepNextN(int steps) {
this.steps = steps;
}

private ParseTree next(ParseTree tree) {
ParseTree parent = up(tree);
ParseTree child;
boolean foundCurrent = false;
int stepsToDo = steps;
for (int i = 0; i < parent.getChildCount(); i++) {
child = parent.getChild(i);
if (foundCurrent) {
if (treeIsSeparator(child)) {
continue;
}
stepsToDo--;
if (stepsToDo == 0) {
return child;
}
}

if (child == tree) {
foundCurrent = true;
}
}
return null; // There is no next
}

@Override
public WalkResult walk(ParseTree tree, String value) {
ParseTree nextTree = next(tree);
if (nextTree == null) {
return null;
}

return walkNextStep(nextTree, null);
}

@Override
public String toString() {
return "Next("+steps+")";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* Yet Another UserAgent Analyzer
* Copyright (C) 2013-2017 Niels Basjes
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package nl.basjes.parse.useragent.analyze.treewalker.steps.walk;

import nl.basjes.parse.useragent.analyze.treewalker.steps.Step;
import nl.basjes.parse.useragent.analyze.treewalker.steps.WalkList.WalkResult;
import org.antlr.v4.runtime.tree.ParseTree;

public class StepPrevN extends Step {

private static final int SIZE = 20;
ParseTree[] children = new ParseTree[SIZE];

private int steps = 1;

public StepPrevN(int steps) {
this.steps = steps;
}

private ParseTree prev(ParseTree tree) {
ParseTree parent = up(tree);

int lastChildIndex = -1;
ParseTree child = null;
int i;
for (i = 0; i < parent.getChildCount(); i++) {
if (!treeIsSeparator(child)) {
lastChildIndex++;
children[lastChildIndex] = child;
}
child = parent.getChild(i);
if (child == tree) {
if (lastChildIndex < steps) {
return null;
}
return children[lastChildIndex-steps+1];
}
}
return null; // There is no previous
}

@Override
public WalkResult walk(ParseTree tree, String value) {
ParseTree nextTree = prev(tree);
if (nextTree == null) {
return null;
}

return walkNextStep(nextTree, null);
}

@Override
public String toString() {
return "Prev()";
}

}

0 comments on commit a2ccf33

Please sign in to comment.