ANTLR: правило Lexer, принимающее строго одну букву и токен нескольких символов вместо одного (Java) - PullRequest
1 голос
/ 10 января 2011

Я написал следующую грамматику для синтаксического анализатора ANTLR и лексера для построения деревьев для логических формул, и у меня есть пара вопросов, если кто-то может помочь:

class AntlrFormulaParser extends Parser;

options {
    buildAST = true;
}

biconexpr : impexpr (BICONDITIONAL^ impexpr)*;

impexpr : orexpr (IMPLICATION^ orexpr)*;

orexpr : andexpr (DISJUNCTION^ andexpr)*;

andexpr : notexpr (CONJUNCTION^ notexpr)*;

notexpr : (NEGATION^)? formula;

formula 
    : atom
    | LEFT_PAREN! biconexpr RIGHT_PAREN!
    ;

atom
    : CHAR
    | TRUTH
    | FALSITY
    ;


class AntlrFormulaLexer extends Lexer;

// Atoms
CHAR: 'a'..'z';
TRUTH: ('\u22A4' | 'T');
FALSITY: ('\u22A5' | 'F');

// Grouping
LEFT_PAREN: '(';
RIGHT_PAREN: ')';
NEGATION: ('\u00AC' | '~' | '!');
CONJUNCTION: ('\u2227' | '&' | '^');
DISJUNCTION: ('\u2228' | '|' | 'V');
IMPLICATION: ('\u2192' | "->");
BICONDITIONAL: ('\u2194' | "<->");

WHITESPACE : (' ' | '\t' | '\r' | '\n') { $setType(Token.SKIP); };

Грамматика дерева:

tree grammar AntlrFormulaTreeParser;

options {
    tokenVocab=AntlrFormula;
    ASTLabelType=CommonTree;
}

expr returns [Formula f]
    : ^(BICONDITIONAL f1=expr f2=expr) {
        $f = new Biconditional(f1, f2);
    }
    | ^(IMPLICATION f1=expr f2=expr) {
        $f = new Implication(f1, f2);
    }
    | ^(DISJUNCTION f1=expr f2=expr) {
        $f = new Disjunction(f1, f2);
    }
    | ^(CONJUNCTION f1=expr f2=expr) {
        $f = new Conjunction(f1, f2);
    }
    | ^(NEGATION f1=expr) {
        $f = new Negation(f1);
    }
    | CHAR {
        $f = new Atom($CHAR.getText());
    }
    | TRUTH {
        $f = Atom.TRUTH;
    }
    | FALSITY {
        $f = Atom.FALSITY;
    }
    ;

Проблемы с вышеуказанной грамматикой следующие:

  1. Токены, IMPLICATION и BICONDITIONAL, в java-коде для AntlrFormulaLexer, похоже, проверяют только соответствие их первого первого символа (то есть '-' и '<') токену вместо всей строки как указано в грамматике. </p>

  2. При тестировании Java-кода для AntlrFormulaParser, если я передаю строку, например "~ ab", она возвращает дерево "(~ a)" (а строка "ab & c" возвращает просто "a") когда он действительно должен возвращать ошибку / исключение, поскольку атом может иметь только одну букву в соответствии с приведенной выше грамматикой. Это не дает никаких ошибок / исключений вообще с этими примерами строк.

Я бы очень признателен, если бы кто-нибудь мог помочь мне решить эти пару проблем. Спасибо:)

1 Ответ

1 голос
/ 10 января 2011

Я бы изменил следующие определения как:

IMPLICATION: ('\u2192' | '->');
BICONDITIONAL: ('\u2194' | '<->');

note "->" vs '->'

И чтобы решить проблему с ошибкой:

formula 
    : (
         atom
       | LEFT_PAREN! biconexpr RIGHT_PAREN! 
      ) EOF
    ;

отсюда: http://www.antlr.org/wiki/pages/viewpage.action?pageId=4554943

Исправлена ​​грамматика для компиляции с antlr 3.3 (сохранить как AntlrFormula.g):

grammar AntlrFormula;

options {
    output = AST; 
}


program : formula ;

formula : atom | LEFT_PAREN! biconexpr RIGHT_PAREN! ;

biconexpr : impexpr (BICONDITIONAL^ impexpr)*;

impexpr : orexpr (IMPLICATION^ orexpr)*;

orexpr : andexpr (DISJUNCTION^ andexpr)*;

andexpr : notexpr (CONJUNCTION^ notexpr)*;

notexpr : (NEGATION^)? formula;


atom
    : CHAR
    | TRUTH
    | FALSITY
    ;


// Atoms
CHAR: 'a'..'z';
TRUTH: ('\u22A4' | 'T');
FALSITY: ('\u22A5' | 'F');

// Grouping
LEFT_PAREN: '(';
RIGHT_PAREN: ')';
NEGATION: ('\u00AC' | '~' | '!');
CONJUNCTION: ('\u2227' | '&' | '^');
DISJUNCTION: ('\u2228' | '|' | 'V');
IMPLICATION: ('\u2192' | '->');
BICONDITIONAL: ('\u2194' | '<->');

WHITESPACE : (' ' | '\t' | '\r' | '\n') { $channel = HIDDEN; };

Ссылка на двоичный файл antlr 3.3: http://www.antlr.org/download/antlr-3.3-complete.jar

вам нужно будет попытаться найти соответствие правилу программы, чтобы он соответствовал полному файлу.

тестируется с этим классом:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) {
        AntlrFormulaLexer lexer = new AntlrFormulaLexer(new ANTLRStringStream("(~ab)"));
        AntlrFormulaParser p = new AntlrFormulaParser(new CommonTokenStream(lexer));

        try {
            p.program();
            if ( p.failed() || p.getNumberOfSyntaxErrors() != 0) {
                System.out.println("failed");
            }
        } catch (RecognitionException e) {
            e.printStackTrace();
        }
    }
}
...