parent
2633088303
commit
7c73559bb1
|
|
@ -1,23 +0,0 @@
|
|||
/** A Mikrotik API Command grammar */
|
||||
|
||||
grammar Command;
|
||||
line: command param* where? retrn? ;
|
||||
command: CMD ;
|
||||
param: NAME ('=' text )? ;
|
||||
text: (QUOTED|VALUE) ;
|
||||
where: 'where' expr ;
|
||||
expr: ( eqExpr | hasExpr | moreExpr | lessExpr ) binExpr? ;
|
||||
binExpr: andExpr | orExpr ;
|
||||
eqExpr: NAME '=' text ;
|
||||
hasExpr: NAME ;
|
||||
moreExpr: NAME '>' text;
|
||||
lessExpr: NAME '<' text;
|
||||
andExpr: expr 'and' expr ;
|
||||
orExpr: expr 'or' expr ;
|
||||
retrn: 'returns' NAME (',' NAME )* ;
|
||||
|
||||
NAME : ('a'..'z'|'A'..'Z'|'-')+ ;
|
||||
CMD : (('/')(NAME))+ ;
|
||||
QUOTED : ('"')(.*?)('"') ;
|
||||
VALUE : (~[ \t\r\n="])+ ;
|
||||
WS: [ \n\t\r]+ -> skip;
|
||||
|
|
@ -1,12 +1,9 @@
|
|||
package me.legrange.mikrotik.impl;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Scanner;
|
||||
import java.util.StringTokenizer;
|
||||
import me.legrange.mikrotik.impl.Scanner.Token;
|
||||
|
||||
/**
|
||||
* Parse the pseudo-command line into command objects.
|
||||
|
|
@ -14,6 +11,15 @@ import java.util.StringTokenizer;
|
|||
*/
|
||||
class Parser {
|
||||
|
||||
public static void main(String...args) throws Exception {
|
||||
/* System.out.println(parse("/system/reboot"));
|
||||
System.out.println(parse("/interface/print where type=ether"));
|
||||
System.out.println(parse("/interface/wireless/monitor .id=wlan1"));
|
||||
System.out.println(parse("/ip/firewall/filter/add action=drop chain=forward in-interface=gre1 protocol=udp dst-port=78,80"));
|
||||
System.out.println(parse("/file/print detail where name=conf.rsc"));
|
||||
System.out.println(parse("/ip/firewall/filter/add action=drop chain=forward in-interface=aps_hs protocol=udp dst-port=78,80,32")); */
|
||||
System.out.println(parse("/interface/gre/set .id=gre1 comment=\"test coment\""));
|
||||
}
|
||||
/** parse the given bit of text into a Command object */
|
||||
static Command parse(String text) throws ParseException {
|
||||
Parser parser = new Parser(text);
|
||||
|
|
@ -22,10 +28,7 @@ class Parser {
|
|||
|
||||
/** run parse on the internal data and return the command object */
|
||||
private Command parse() throws ParseException {
|
||||
next();
|
||||
expect(Token.COMMAND);
|
||||
cmd = new Command(text);
|
||||
next();
|
||||
command();
|
||||
while (!((token == Token.WHERE) || (token == Token.RETURN) || (token == Token.EOL))) {
|
||||
param();
|
||||
}
|
||||
|
|
@ -39,19 +42,35 @@ class Parser {
|
|||
return cmd;
|
||||
}
|
||||
|
||||
private void command() throws ParseException {
|
||||
StringBuilder path = new StringBuilder();
|
||||
do {
|
||||
expect(Token.SLASH);
|
||||
path.append("/");
|
||||
next();
|
||||
expect(Token.TEXT);
|
||||
path.append(text);
|
||||
next();
|
||||
} while (token == Token.SLASH);
|
||||
cmd = new Command(path.toString());
|
||||
}
|
||||
|
||||
private void param() throws ParseException {
|
||||
String name = text;
|
||||
next();
|
||||
if (token == Token.EQUALS) {
|
||||
next();
|
||||
expect(Token.NAME);
|
||||
String val = text;
|
||||
expect(Token.TEXT);
|
||||
StringBuilder val = new StringBuilder(text);
|
||||
next();
|
||||
while (token == Token.COMMA) {
|
||||
val.append(",");
|
||||
next();
|
||||
expect(Token.TEXT);
|
||||
val.append(text);
|
||||
next();
|
||||
val = val + "," + text;
|
||||
}
|
||||
cmd.addParameter(new Parameter(name, val));
|
||||
cmd.addParameter(new Parameter(name, val.toString()));
|
||||
}
|
||||
else {
|
||||
cmd.addParameter(new Parameter(name));
|
||||
|
|
@ -64,12 +83,12 @@ class Parser {
|
|||
}
|
||||
|
||||
private void expr() throws ParseException {
|
||||
expect(Token.NOT, Token.NAME);
|
||||
expect(Token.NOT, Token.TEXT);
|
||||
switch (token) {
|
||||
case NOT:
|
||||
notExpr();
|
||||
break;
|
||||
case NAME: {
|
||||
case TEXT: {
|
||||
String name = text;
|
||||
next();
|
||||
expect(Token.EQUALS, Token.LESS, Token.MORE);
|
||||
|
|
@ -116,19 +135,20 @@ class Parser {
|
|||
cmd.addQuery("?#!");
|
||||
}
|
||||
|
||||
private void eqExpr(String name) {
|
||||
private void eqExpr(String name) throws ParseException {
|
||||
next(); // eat =
|
||||
expect(Token.TEXT);
|
||||
cmd.addQuery(String.format("?%s=%s", name, text));
|
||||
next();
|
||||
}
|
||||
|
||||
private void lessExpr(String name) {
|
||||
private void lessExpr(String name) throws ScanException {
|
||||
next(); // eat <
|
||||
cmd.addQuery(String.format("?<%s=%s", name, text));
|
||||
next();
|
||||
}
|
||||
|
||||
private void moreExpr(String name) {
|
||||
private void moreExpr(String name) throws ScanException {
|
||||
next(); // eat >
|
||||
cmd.addQuery(String.format("?>%s=%s", name, text));
|
||||
next();
|
||||
|
|
@ -140,8 +160,8 @@ class Parser {
|
|||
|
||||
private void returns() throws ParseException {
|
||||
next();
|
||||
expect(Token.NAME);
|
||||
List<String> props = new LinkedList<String>();
|
||||
expect(Token.TEXT);
|
||||
List<String> props = new LinkedList<>();
|
||||
while (!(token == Token.EOL)) {
|
||||
if (token != Token.COMMA) {
|
||||
props.add(text);
|
||||
|
|
@ -158,59 +178,27 @@ class Parser {
|
|||
throw new ParseException(String.format("Expected %s but found %s", Arrays.asList(tokens), this.token));
|
||||
}
|
||||
|
||||
private void next() {
|
||||
if (!words.isEmpty()) {
|
||||
text = words.remove(0);
|
||||
if (text.startsWith("/")) {
|
||||
token = Token.COMMAND;
|
||||
} else {
|
||||
Token t = lookup.get(text);
|
||||
if (t != null) {
|
||||
token = t;
|
||||
text = "";
|
||||
} else {
|
||||
token = Token.NAME;
|
||||
private void next() throws ScanException {
|
||||
// Token was = token;
|
||||
token = scanner.next();
|
||||
// System.out.printf("'%s' => '%s'\n", was, token);
|
||||
while (token == Token.WS) {
|
||||
token = scanner.next();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
token = Token.EOL;
|
||||
text = "";
|
||||
}
|
||||
// System.out.printf("%s: %s\n", token, text);
|
||||
text = scanner.text();
|
||||
}
|
||||
|
||||
private Parser(String line) {
|
||||
private Parser(String line) throws ScanException {
|
||||
line = line.trim();
|
||||
StringTokenizer st = new StringTokenizer(line, " \t,=", true);
|
||||
boolean quote = false;
|
||||
while (st.hasMoreElements()) {
|
||||
String t = st.nextToken().trim();
|
||||
if (!t.equals("")) {
|
||||
words.add(t);
|
||||
}
|
||||
}
|
||||
scanner = new Scanner(line);
|
||||
next();
|
||||
}
|
||||
|
||||
private final List<String> words = new LinkedList<String>();
|
||||
private String text;
|
||||
|
||||
|
||||
private final Scanner scanner;
|
||||
private Token token;
|
||||
private String text;
|
||||
private Command cmd;
|
||||
private static final Map<String, Token> lookup = new HashMap<String, Token>();
|
||||
|
||||
private enum Token {
|
||||
|
||||
COMMAND, WHERE, RETURN, EOL, NOT, AND, OR, NAME, EQUALS, MORE, LESS, COMMA;
|
||||
}
|
||||
|
||||
static {
|
||||
lookup.put("where", Token.WHERE);
|
||||
lookup.put("return", Token.RETURN);
|
||||
lookup.put("not", Token.NOT);
|
||||
lookup.put("and", Token.AND);
|
||||
lookup.put("or", Token.OR);
|
||||
lookup.put("=", Token.EQUALS);
|
||||
lookup.put(">", Token.MORE);
|
||||
lookup.put("<", Token.LESS);
|
||||
lookup.put(",", Token.COMMA);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
package me.legrange.mikrotik.impl;
|
||||
|
||||
import me.legrange.mikrotik.MikrotikApiException;
|
||||
|
||||
/**
|
||||
* Exception thrown if the scanner encounters an error while scanning a command line.
|
||||
* @author GideonLeGrange
|
||||
*/
|
||||
public class ScanException extends ParseException {
|
||||
|
||||
ScanException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
ScanException(String msg, Throwable err) {
|
||||
super(msg, err);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue