BackGround
Я пытаюсь написать простую грамматику, используя AntlrWorks, для булевых уравнений, которые проверяют наборы значений на наличие (или отсутствие таковых) указанных элементов.
Я создал комбинированную грамматику лексера / парсера, которая производит желаемые AST.
Я также написал соответствующую древовидную грамматику, которая, кажется, работает (передает функции отладки AntlrWorks).
Задача
Однако, когда я пытаюсь соединить их вместе в тестовой программе (то есть lex, parse и tree parse в одной и той же программе), я получаю сообщения об ошибках типа ...
node from line 1:5 required (...)+ loop did not match anything at input 'and'
и
node from after line 1:8 mismatched tree node: UP expecting <DOWN>
В качестве проверки работоспособности у меня была тестовая программа, выводившая результаты toStringTree()
из сгенерированного AST и toTokenTypeString()
из полученного TreeNodeStream
.
Я обнаружил, что перечисленные значения типа токена TreeNodeStream
не соответствуют перечисленным значениям типа токена в автоматически сгенерированном коде древовидной грамматики.
Пример
пример ввода: "true and false"
Вывод toStringTree () из предоставленного парсером дерева: (and true false)
Вывод toTokenTypeString()
из TreeNodeStream, содержащий вышеуказанное AST: 19 2 22 20 3 8
Этот поток токенов должен быть AND <DOWN> 'true' 'false' <UP> NEWLINE
Но TreeParser видит его как CLOSEPAREN <DOWN> OR 'false' <UP> OPENPAREN
(основанный на просмотре вывода типа токена узла и проверке его на соответствие перечислению, определенному в грамматике дерева), и выдает ошибку
1:5 required (...)+ loop did not match anything at input 'and'
Итог
Почему мой анализатор дерева не настроен для правильной идентификации моих AST?
Ниже мой источник. Я ценю любые отзывы о глупых ошибках, которые я должен был сделать:)
грамматика лексера / синтаксического анализатора
grammar INTc;
options {
output=AST;
ASTLabelType=CommonTree;
}
tokens {
OR='or';
AND='and';
NOT='not';
ALLIN='+';
PARTIN='^';
NOTIN='!';
SET;
OPENPAREN='(';
CLOSEPAREN=')';
OPENSET='{';
CLOSESET='}';
}
@header {
package INTc;
}
@lexer::header {
package INTc;
}
@members {
}
/**Begin Parser Rules*/
prog: stat+ ;
stat: expr
| NEWLINE
;
expr
: orExpr
;
orExpr returns [boolean value]
: a=andExpr(OR^ b=andExpr)*
;
andExpr returns [boolean value]
: a=notExpr (AND^ b=notExpr)*
;
notExpr returns [boolean value]
: a=atom
| '!' a=atom -> ^(NOT atom)
;
atom returns [boolean value]
: ALLIN OPENSET ((INT)(','INT)*) CLOSESET -> ^(ALLIN ^(SET INT+))
| PARTIN OPENSET ((INT)(','INT)*) CLOSESET -> ^(PARTIN ^(SET INT+))
| NOTIN OPENSET ((INT)(','INT)*) CLOSESET -> ^(NOTIN ^(SET INT+))
| TIMERANGE
| OPENPAREN! e=expr CLOSEPAREN!
| 'true'
| 'false'
;
/**Begin Lexer Rules*/
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')* ;
DIGIT : ('0'..'9');
INT : DIGIT+ ;
NEWLINE : '\r'? '\n' ;
WS : ( ' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;};
COMMENT
: '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;}
| '/*' ( options {greedy=false;} : . )* '*/' {$channel=HIDDEN;}
;
Грамматика деревьев
tree grammar INTcWalker;
options {
tokenVocab=INTc;
ASTLabelType=CommonTree;
}
@header {
package INTc;
import java.util.ArrayList;
import java.util.Arrays;
}
@members {
ArrayList<String> intSet;
boolean isFit = false;
public boolean getResult() {
return isFit;
}
public void setINTSet(ArrayList newSet) {
intSet = newSet;
isFit = false;
}
public ArrayList getINTSET(){return intSet;}
}
prog
: stat+
;
stat
: expr {
isFit = $expr.value;
//System.out.println(isFit);
}
| NEWLINE {}
;
expr returns [boolean value]
: ^(OR a=expr b=expr){}
| ^(AND a=expr b=expr){}
| ^(NOT a=expr){}
| ^(ALLIN ^(SET INT+)){}
| ^(PARTIN ^(SET INT+)){}
| ^(NOTIN ^(SET INT+)){}
| 'true' {$value = true;}
| 'false' {$value = false;}
;
Тестовая программа
public class setTest {
public static void main(String args[]) throws Exception {
INTcLexer lex = new INTcLexer(new ANTLRFileStream("input.txt"));
CommonTokenStream tokens = new CommonTokenStream(lex);
INTcParser parser = new INTcParser(tokens);
INTcParser.prog_return r = parser.prog();
CommonTree t = (CommonTree)r.getTree();
CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
INTcWalker evaluator = new INTcWalker(nodes);
System.out.println(t.toStringTree());
System.out.println(nodes.toTokenTypeString());
nodes.reset();
try {
evaluator.prog();
} catch (RecognitionException e) {
e.printStackTrace();
}
System.out.println(evaluator.getResult());
}
}