Skip to content

Commit

Permalink
Refactor
Browse files Browse the repository at this point in the history
  • Loading branch information
f3ath committed Aug 2, 2020
1 parent 74ee6c9 commit 1d8446a
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 45 deletions.
9 changes: 9 additions & 0 deletions lib/src/ast.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,13 @@ class Node {
final children = <Node>[];

bool get isNumber => RegExp(r'^-?\d+$').hasMatch(value);

bool get isQuoted => value.startsWith("'");

String get unquoted => value
.substring(1, value.length - 1)
.replaceAll(r'\\', r'\')
.replaceAll(r"\'", r"'");

int get intValue => int.parse(value);
}
68 changes: 33 additions & 35 deletions lib/src/state.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class Ready implements State {
State process(Node node) {
switch (node.value) {
case '[':
return Ready(selector.then(_bracketSelector(node.children)));
return Ready(selector.then(brackets(node.children)));
case '.':
return AwaitingField(selector);
case '..':
Expand All @@ -39,42 +39,40 @@ class Ready implements State {
}
}

Selector _bracketSelector(List<Node> nodes) {
if (nodes.length == 1) {
final node = nodes.single;
if (node.value == '*') return AllInArray();
if (node.isNumber) return Index(int.parse(nodes.first.value));
if (node.value.startsWith("'")) {
return Field(node.value.substring(1, node.value.length - 1));
Selector brackets(List<Node> nodes) {
if (nodes.isEmpty) throw FormatException('Empty brackets');
if (nodes.length == 1) return singleValueBrackets(nodes.single);
return multiValueBrackets(nodes);
}

Slice multiValueBrackets(List<Node> nodes) {
int first;
int last;
int step;
var colons = 0;
nodes.forEach((node) {
if (node.value == ':') {
colons++;
return;
}
} else if (nodes.length > 1) {
int first;
int last;
int step;
var colons = 0;
nodes.map((_) => _.value).forEach((val) {
// if (nodes.length > 2 && nodes[1].value == ',') {
// // union. take the odd ones
// nodes.map((e) => e.value).where((element) => element != ',')
// }
if (val == ':') {
colons++;
return;
}
if (colons == 0) {
first = int.parse(val);
return;
}
if (colons == 1) {
last = int.parse(val);
return;
}
step = int.parse(val);
});
return Slice(first: first, last: last, step: step);
}
if (colons == 0) {
first = node.intValue;
return;
}
if (colons == 1) {
last = node.intValue;
return;
}
step = node.intValue;
});
return Slice(first: first, last: last, step: step);
}

throw StateError('Unexpected bracket expression');
Selector singleValueBrackets(Node node) {
if (node.value == '*') return AllInArray();
if (node.isNumber) return Index(node.intValue);
if (node.isQuoted) return Field(node.unquoted);
throw FormatException('Unexpected bracket expression');
}
}

Expand Down
16 changes: 6 additions & 10 deletions lib/src/tokenize.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,19 @@
/// Parses a JSONPath expression into a list of tokens
Iterable<String> tokenize(String expr) sync* {
var pos = 0;
var insideQuotedString = false;
while (pos < expr.length) {
var token = '';
var insideQuotedString = false;
var escapeMode = false;
while (pos < expr.length) {
final char = expr[pos];
if (char == "'") {
if (char == "'" && !escapeMode) {
insideQuotedString = !insideQuotedString;
}
escapeMode = char == r'\';
if (insideQuotedString) {
if (char == r'\') {
if (expr.length <= pos + 1) throw FormatException('Dangling escape');
token += expr[pos + 1];
pos += 2;
} else {
token += char;
pos += 1;
}
token += char;
pos += 1;
continue;
}
if (_singles.contains(char)) {
Expand Down
1 change: 1 addition & 0 deletions test/json_path_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ void main() {
test('Escape single quote', () {
final j = {r"sq'sq s\s qs\'qs": 'value'};
final path = JsonPath(r"$['sq\'sq s\\s qs\\\'qs']");
expect(path.toString(), r"$['sq\'sq s\\s qs\\\'qs']");
final select = path.select(j);
expect(select.single.value, 'value');
expect(select.single.path, r"$['sq\'sq s\\s qs\\\'qs']");
Expand Down

0 comments on commit 1d8446a

Please sign in to comment.