Fixed bug #11
This commit is contained in:
parent
8ce5fce77f
commit
935c76ae34
|
|
@ -19,7 +19,7 @@ public class Example8 extends Example {
|
|||
}
|
||||
|
||||
private void test() throws MikrotikApiException, InterruptedException {
|
||||
List<Map<String, String>> res = con.execute("/ip/hotspot/user/print where uptime<00:00:01");
|
||||
List<Map<String, String>> res = con.execute("/ip/hotspot/user/print where uptime!=1");
|
||||
for (Map<String, String> r : res) {
|
||||
System.out.println(r);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,13 +82,14 @@ class Parser {
|
|||
case TEXT: {
|
||||
String name = text;
|
||||
next();
|
||||
expect(Token.EQUALS, Token.LESS, Token.MORE);
|
||||
expect(Token.EQUALS, Token.LESS, Token.MORE, Token.NOT_EQUALS);
|
||||
switch (token) {
|
||||
case EQUALS:
|
||||
eqExpr(name);
|
||||
break;
|
||||
case NOT_EQUALS :
|
||||
notExpr(name);
|
||||
break;
|
||||
case LESS:
|
||||
lessExpr(name);
|
||||
break;
|
||||
|
|
@ -106,6 +107,7 @@ class Parser {
|
|||
case AND : andExpr();
|
||||
break;
|
||||
case OR : orExpr();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,16 +13,17 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package me.legrange.mikrotik.impl;
|
||||
|
||||
/**
|
||||
* A simple scanner.
|
||||
*
|
||||
* @author gideon
|
||||
*/
|
||||
class Scanner {
|
||||
|
||||
enum Token {
|
||||
|
||||
SLASH("/"), COMMA(","), EOL(), WS, TEXT,
|
||||
LESS("<"), MORE(">"), EQUALS("="), NOT_EQUALS("!="),
|
||||
WHERE, NOT, AND, OR, RETURN;
|
||||
|
|
@ -40,79 +41,100 @@ class Scanner {
|
|||
symb = null;
|
||||
}
|
||||
|
||||
|
||||
private final String symb;
|
||||
}
|
||||
|
||||
/** create a scanner for the given line of text */
|
||||
/**
|
||||
* create a scanner for the given line of text
|
||||
*/
|
||||
Scanner(String line) {
|
||||
this.line = line;
|
||||
nextChar();
|
||||
}
|
||||
|
||||
/** return the next token from the text */
|
||||
/**
|
||||
* return the next token from the text
|
||||
*/
|
||||
Token next() throws ScanException {
|
||||
text = null;
|
||||
switch (c) {
|
||||
case '\n' : return Token.EOL;
|
||||
case ' ' :
|
||||
case '\t' :
|
||||
case '\n':
|
||||
return Token.EOL;
|
||||
case ' ':
|
||||
case '\t':
|
||||
return whiteSpace();
|
||||
case ',' :
|
||||
case ',':
|
||||
nextChar();
|
||||
return Token.COMMA;
|
||||
case '/' :
|
||||
case '/':
|
||||
nextChar();
|
||||
return Token.SLASH;
|
||||
case '<' :
|
||||
case '<':
|
||||
nextChar();
|
||||
return Token.LESS;
|
||||
case '>' :
|
||||
case '>':
|
||||
nextChar();
|
||||
return Token.MORE;
|
||||
case '=' :
|
||||
case '=':
|
||||
nextChar();
|
||||
return Token.EQUALS;
|
||||
case '!' :
|
||||
case '!':
|
||||
return notEquals();
|
||||
case '"' :
|
||||
case '"':
|
||||
return quotedText('"');
|
||||
case '\'' :
|
||||
case '\'':
|
||||
return quotedText('\'');
|
||||
default :
|
||||
default:
|
||||
return name();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** return the text associated with the last token returned */
|
||||
/**
|
||||
* return the text associated with the last token returned
|
||||
*/
|
||||
String text() {
|
||||
if (text != null) return text.toString();
|
||||
if (text != null) {
|
||||
return text.toString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/** return the position of the scanner */
|
||||
int pos() { return pos; }
|
||||
/**
|
||||
* return the position of the scanner
|
||||
*/
|
||||
int pos() {
|
||||
return pos;
|
||||
}
|
||||
|
||||
/** process 'name' tokens which could be key words or text */
|
||||
/**
|
||||
* process 'name' tokens which could be key words or text
|
||||
*/
|
||||
private Token name() throws ScanException {
|
||||
text = new StringBuilder();
|
||||
while (!in(c, "[ \t\r\n=<>]")) {
|
||||
while (!in(c, "[ \t\r\n=<>!]")) {
|
||||
text.append(c);
|
||||
nextChar();
|
||||
}
|
||||
String val = text.toString().toLowerCase();
|
||||
switch (val) {
|
||||
case "where" : return Token.WHERE;
|
||||
case "not" : return Token.NOT;
|
||||
case "and" : return Token.AND;
|
||||
case "or" : return Token.OR;
|
||||
case "return" : return Token.RETURN;
|
||||
case "where":
|
||||
return Token.WHERE;
|
||||
case "not":
|
||||
return Token.NOT;
|
||||
case "and":
|
||||
return Token.AND;
|
||||
case "or":
|
||||
return Token.OR;
|
||||
case "return":
|
||||
return Token.RETURN;
|
||||
}
|
||||
return Token.TEXT;
|
||||
}
|
||||
|
||||
/** process quoted text */
|
||||
/**
|
||||
* process quoted text
|
||||
*/
|
||||
private Token quotedText(char quote) throws ScanException {
|
||||
nextChar(); // eat the '"'
|
||||
text = new StringBuilder();
|
||||
|
|
@ -127,7 +149,9 @@ class Scanner {
|
|||
return Token.TEXT;
|
||||
}
|
||||
|
||||
/** process white space */
|
||||
/**
|
||||
* process white space
|
||||
*/
|
||||
private Token whiteSpace() {
|
||||
while ((c == ' ') || (c == '\t')) {
|
||||
nextChar();
|
||||
|
|
@ -135,27 +159,33 @@ class Scanner {
|
|||
return Token.WS;
|
||||
}
|
||||
|
||||
/** process the not equals token */
|
||||
/**
|
||||
* process the not equals token
|
||||
*/
|
||||
private Token notEquals() throws ScanException {
|
||||
nextChar(); // eat the !
|
||||
if (c != '=') {
|
||||
throw new ScanException(String.format("Expected = after !, found '%c'", c));
|
||||
}
|
||||
nextChar(); // eat the =
|
||||
return Token.NOT_EQUALS;
|
||||
}
|
||||
|
||||
/** return the next character from the line of text */
|
||||
/**
|
||||
* return the next character from the line of text
|
||||
*/
|
||||
private void nextChar() {
|
||||
if (pos < line.length()) {
|
||||
c = line.charAt(pos);
|
||||
pos ++;
|
||||
}
|
||||
else {
|
||||
pos++;
|
||||
} else {
|
||||
c = '\n';
|
||||
}
|
||||
}
|
||||
|
||||
/** check if the character matches the give expression */
|
||||
/**
|
||||
* check if the character matches the give expression
|
||||
*/
|
||||
private boolean in(char c, String cs) {
|
||||
return ("" + c).matches(cs);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue