Skip to content

Instantly share code, notes, and snippets.

@stevewadsworth
Last active December 11, 2021 16:01
Show Gist options
  • Select an option

  • Save stevewadsworth/85ef8f63d4dd177b6da7a573558d5db2 to your computer and use it in GitHub Desktop.

Select an option

Save stevewadsworth/85ef8f63d4dd177b6da7a573558d5db2 to your computer and use it in GitHub Desktop.
Regex to match and|or with minimal match to left and maximal to right
// regex to match and|or with minimal match to left and maximal to right /^\s*(.+?)\s+(or|and)\s+(.+?)\s*$/
// foo = 192.168.0.1 or foo = 192.168.0.110 and bar = baz
// Gives "foo = 192.168.0.1", "or", "foo = 192.168.0.110 and bar = baz"
// The third match is ready to be re-input to the regex
// ...Or should it be the other way around with the maximal match on the left for correct left to right associativity?
// Not sure right now, so keep it in mind removing the ? from (.+?) will do it /^\s*(.+)\s+(or|and)\s+(.+?)\s*$/
//
// regex to match '=' /(\S+)\s*(=)\s*(\S+)/
// foo = 192.168.0.1
// Gives "foo", "=", "192.168.0.1"
const LOGICAL_OPERATORS = /^\s*(.+?)\s+(or|and)\s+(.+?)\s*$/;
const NOT_EQUALS = /^\s*(\S+)\s*(!=)\s*(\S+)\s*$/;
const GREATER_OR_EQUALS = /^\s*(\S+)\s*(>=)\s*(\S+)\s*$/;
const LESS_OR_EQUALS = /^\s*(\S+)\s*(<=)\s*(\S+)\s*$/;
const EQUALS = /^\s*(\S+)\s*(=)\s*(\S+)\s*$/;
const GREATER = /^\s*(\S+)\s*(>)\s*(\S+)\s*$/;
const LESS = /^\s*(\S+)\s*(<)\s*(\S+)\s*$/;
// The order of the operators are critical. More specific to less specific!
const operators = [
NOT_EQUALS,
GREATER_OR_EQUALS,
LESS_OR_EQUALS,
EQUALS,
GREATER,
LESS
];
export class QueryTree {
lValue: QueryTree|string;
rValue: QueryTree|string;
operator: string;
isLeaf: boolean;
isValid: boolean = false;
constructor(queryString: string) {
// First match logical operators
const match = queryString.match(LOGICAL_OPERATORS);
if (match) {
this.lValue = new QueryTree(match[1]);
this.operator = match[2];
this.rValue = new QueryTree(match[3]);
// A logical node cannot be a leaf
this.isLeaf = false;
// This node is only valid if all it's children are valid
this.isValid = this.lValue.isValid && this.rValue.isValid;
} else {
for (let i = 0; i < operators.length; i++) {
const operator = operators[i];
const match = queryString.match(operator);
if (match) {
// Got a leaf match
this.isLeaf = true;
this.isValid = true;
this.lValue = match[1];
this.operator = match[2];
this.rValue = match[3];
break;
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment