Новичок: 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 ответ
Решение
@
персонаж на самом деле ничего не соответствует. Когда лексер достигает этого символа, происходит следующее:
- Лексер определяет, что ни одно правило лексера не может соответствовать
@
персонаж. - Лексер сообщает об ошибке относительно ошибки.
- Лексер зовет
_input.consume()
пропустить плохого персонажа.
Чтобы сообщения об ошибках были представлены как можно проще, всегда добавляйте следующее правило в качестве последнего правила в лексере.
ErrChar
: .
;
Парсер сообщит об ошибке, когда достигнет ErrChar
, так что вам не нужно добавлять прослушиватель ошибок в лексер.