Новичок: 2.4@ принимается как поплавок. "@" - это специальный символ?

Интересно, почему выражение "setvalue(2@)" с радостью принимается лексером (и парсером) с учетом моей грамматики / посетителя. Я уверен, что делаю что-то не так.

Ниже приведен небольшой пример, который должен проиллюстрировать проблему.

Буду признателен за любую оказанную помощь.

grammar ExpressionEvaluator;

parse
 : block EOF
 ;

block
 : stat*
 ;

stat
 : assignment
 ;

assignment
: SETVALUE OPAR expr CPAR
;


expr
 : atom                       #atomExpr
 ;

atom
 : OPAR expr CPAR #parExpr
 | (INT | FLOAT)  #numberAtom
 | ID             #idAtom
 ;

OPAR : '(';
CPAR : ')';
SETVALUE : 'setvalue';

ID
 : [a-zA-Z_] [a-zA-Z_0-9]*
 ;

INT
 : [0-9]+
 ;

FLOAT
 : [0-9]+ '.' [0-9]* 
 | '.' [0-9]+
 ;


STRING
 : '"' (~["\r\n] | '""')* '"'
 ;


SPACE
 : [ \t\r\n] -> skip
 ;

Фрагмент кода:

public override object VisitParse(ExpressionEvaluatorParser.ParseContext context)
    {
        return this.Visit(context.block());
    }

    public override object VisitAssignment(ExpressionEvaluatorParser.AssignmentContext context)
    {
    // TODO - Set ID Value
        return Convert.ToDouble(this.Visit(context.expr()));
    }

    public override object VisitIdAtom(ExpressionEvaluatorParser.IdAtomContext context)
    {
        string id = context.GetText();

        // TODO - Lookup ID value
        return id;
    }


    public override object VisitNumberAtom(ExpressionEvaluatorParser.NumberAtomContext context)
    {
        return Convert.ToDouble(context.GetText());
    }

    public override object VisitParExpr(ExpressionEvaluatorParser.ParExprContext context)
    {
        return this.Visit(context.expr());
    }

1 ответ

Решение

@ персонаж на самом деле ничего не соответствует. Когда лексер достигает этого символа, происходит следующее:

  1. Лексер определяет, что ни одно правило лексера не может соответствовать @ персонаж.
  2. Лексер сообщает об ошибке относительно ошибки.
  3. Лексер зовет _input.consume() пропустить плохого персонажа.

Чтобы сообщения об ошибках были представлены как можно проще, всегда добавляйте следующее правило в качестве последнего правила в лексере.

ErrChar
  : .
  ;

Парсер сообщит об ошибке, когда достигнет ErrChar, так что вам не нужно добавлять прослушиватель ошибок в лексер.

Другие вопросы по тегам