ANTLR4:错误的输入错误

时间:2016-02-29 16:01:38

标签: c# antlr antlr4

我正在为我正在处理的自定义脚本编写解析器。

当我在基本脚本下面提供时:

if (db.Title == 2) { }

假设匹配conditionStatement。但是当我运行它时,我会遇到错误。当我尝试输入for循环输入时,会发生同样的错误:

line 1:0 extraneous input 'if'

这是我的语法:

grammar CustomScript;

/*
 * Parser Rules
 */

prog
    :   compoundScript EOF
    ;

compoundScript
    :  ( '{' script '}' )+
    |  ( script )
    ;

script
    :   (declaration* statement*)
    |   statement*
    ;

iterationStatement
    :   'for' '(' identifier 'in' collection ')' statement
    ;

collection
    :   list|data | identifier
    ;

statement
    :   expressionStatement
    |   conditionStatement
    |   iterationStatement
    |   '{' statement '}'
    ;

conditionStatement
    :   'if' '(' expression ')' statement ('else' statement)?
    ;

expressionStatement
    :   expression ';'?
    ;

declaration
    :   constantObjectDeclaration+
    ;

constantObjectDeclaration
    :   'set' identifier 'as' constantObject ';'?
    ;

constantObject
    :   identifier '.' identifier '[' value ']'
    ;

expression
    :   assignmentExpression
    |   expression ',' assignmentExpression
    ;

assignmentExpression
    :   postfixExpression assignmentOperator=AssignmentOperator postfixExpression    
    |   conditionalExpression
    ;

conditionalExpression
    :   logicalOrExpression ('?' expression ':' conditionalExpression)?
    ;

logicalOrExpression
    :   logicalAndExpression
    |   logicalOrExpression '||' logicalAndExpression
    ;

logicalAndExpression
    :   logicalCondition
    |   logicalAndExpression '&&' logicalCondition
    ;

postfixExpression
    :   primaryExpression       
    |   postfixExpression '[' expression ']'
    |   postfixExpression '.' Advance '.' Digits '.' identifier
    |   postfixExpression '.' Main '.' Digits '.' identifier
    |   postfixExpression '.' Split '.' Digits '.' identifier       
    |   postfixExpression '++'          // Ensure only variable++
    |   postfixExpression '--'          // Ensure only variable--
    ;

primaryExpression
    :   identifier
    |   constant
    |   stringLiteral+
    |   calcExpr                        
    |   list
    |   '(' expression ')'
    ;

calcExpr 
    :   calcExpr op=(MulDivOperator | '^') calcExpr  # MulDivExpo
    |   calcExpr op=AddSubOperator calcExpr          # AddSub
    |   number                                       # IntValue
    |   data                                         # DataValue
    |   identifier                                   # IdentifierValue
    |   constant                                     # ConstantValue
    |   '(' calcExpr ')'                             # ExprWithParens
    ;

logicalCondition
    :   data instructionOption number           # LeftDataRightNumber
    |   number instructionOption data           # LeftNumberRightData
    |   data instructionOption data             # LeftDataRightData

    |   constant instructionOption DateTime     # LeftConstantRightDateTime
    |   data instructionOption DateTime         # LeftDataRightDateTime
    |   DateTime instructionOption data         # LeftDateTimeRightData 
    |   DateTime instructionOption constant     # LeftDateTimeRightConstant

    |   data instructionOption String           # LeftDataRightString
    |   String instructionOption data           # LeftStringRightData
    |   String instructionOption constant       # LeftStringRightConstant

    |   constant instructionOption constant     # LeftConstantRightConstant
    |   constant instructionOption String       # LeftConstantRightString

    |   constant instructionOption number       # LeftConstantRightNumber
    |   number instructionOption constant       # LeftNumberRightConstant

    |   constant instructionOption data         # LeftConstantRightData
    |   data instructionOption constant         # LeftDataRightConstant

    |   identifier instructionOption constant   # LeftIdentifierRightConstant
    |   constant instructionOption identifier   # LeftConstantRightIdentifier

    |   identifier instructionOption data       # LeftIdentifierRightData
    |   data instructionOption identifier       # LeftDataRightIdentifier

    |   data In list                    # LeftDataInRightList
    |   constant In list                # LeftConstantInRightList
    |   value In list                   # LeftValueInRightList
    |   identifier In list              # LeftIdentifierInRightList

    |   '(' logicalCondition ')'        # ConditionWithParens
    ;

instructionOption
    :   Keyword | Operator | AssignmentOperator | MulDivOperator | AddSubOperator
    ;

list 
    :   ( '[' ( identifierList )? ']' )
    ;


identifierList
    :   ( identifier ','? )
    |   ( (identifier ',' )+ (identifier ','? ) )+
    ;

value 
    :   number
    |   stringLiteral
    ;

constant 
    :   (('$''{') (NonDigit | DigitsNondigits) '}')
    ;

data 
    :   identifier '.' (MetaData '.')? identifier
    ;

datetime 
    :   Quote Digits '-' Digits '-' Digits Quote
    |   Quote Digits '/' Digits '/' Digits Quote
    |   Quote Digits '-' Digits '-' Digits Space Digits ':' Digits Quote
    |   Quote Digits '/' Digits '/' Digits Space Digits ':' Digits Quote
    ;

deliveryType 
    :   Advances | Mains | Splits 
    ;

number 
    :   Digits (Dot Digits)?
    ;

Keyword
    :   Else
    |   For
    |   If
    |   Before
    |   Contains
    |   After
    |   And
    |   Or
    |   In
    |   Set
    |   StartsWith
    |   EndsWith
    ;

separator 
    :   '-' | '/' | ':'
    ;

identifier 
    :   NonDigit | DigitsNondigits
    ;

NonDigit 
    :   [a-zA-Z_]+
    ;

DigitsNondigits 
    :   [a-zA-Z0-9_]+
    ;

Digits
    :   [0-9]+
    ;

stringLiteral
    :   Quote SCharSequence? Quote
    ;

Quote 
    :   ('\"'|'\'') -> channel(HIDDEN)
    ;

fragment
SCharSequence
    :   SChar+
    ;

fragment
SChar
    :   ~["\\\r\n']
    |   EscapeSequence
    ;

fragment
EscapeSequence
    :   SimpleEscapeSequence
    ;
fragment
SimpleEscapeSequence
    :   '\\' ['"?abfnrtv\\]
    ;

//fragment

AssignmentOperator
    :   '='
    |   '*='
    |   '/='
    |   '%='
    |   '+='
    |   '-='
    |   '^='
    ;

MulDivOperator
    :   '*'
    |   '/'
    ;

AddSubOperator
    :   '+'
    |   '-'
    ;

Operator
    :   '%'
    |   '&'
    |   '!'
    |   '<'
    |   '>'
    |   '=='
    |   '!='
    |   '<='
    |   '>='
    |   '&&'
    |   '||'
    |   '++'
    |   '--'
    |   ','
    ;    

/*
 * Lexer Rules
 */

Deliveries      : 'Deliveries';
Advances        : 'Advances';
Mains           : 'Mains';
Splits          : 'Splits';

Else            : 'else';
For             : 'for';
If              : 'if';
Advance         : 'Advance';
Main            : 'Main';
Split           : 'Split';
Before          : 'before';
Contains        : 'contains';
After           : 'after';
And             : 'and';
Or              : 'or';
In              : 'in';
Set             : 'Set';
StartsWith      : 'startsWith';
EndsWith        : 'endsWith';
MetaData        : 'MetaData';

//LeftParen       : '(';
//RightParen      : ')';
LeftBracket     : '[';
RightBracket    : ']';
//LeftBrace       : '{';
//RightBrace      : '}';

Less            : '<';
LessEqual       : '<=';
Greater         : '>';
GreaterEqual    : '>=';

Plus            : '+';
PlusPlus        : '++';
Minus           : '-';
MinusMinus      : '--';
Star            : '*';
Div             : '/';
Mod             : '%';

AndAnd          : '&&';
OrOr            : '||';
Caret           : '^';
Not             : '!';

Question        : '?';
Colon           : ':';
Semi            : ';';
Comma           : ',';

Assign          : '=';
StarAssign      : '*=';
ExpoAssign      : '^=';
DivAssign       : '/=';
ModAssign       : '%=';
PlusAssign      : '+=';
MinusAssign     : '-=';

Equal           : '==';
NotEqual        : '!=';
Space           : ' ' -> skip;
DoubleQuote     : '"';
Dot             : '.';

NewLine         : ('\r' '\n' ? | '\n') -> skip;
BlockComment    : '/*' .*? '*/' -> skip;

LineCommentOption1  : '//' ~[\r\n]* -> skip;
LineCommentOption2  : '#' ~[\r\n]* -> skip;

WS  :   ('\r' | '\n' | '\t') -> channel(HIDDEN);

注意

编辑:由于原始表达式输入错误问题已解决 - 具有上述语法。另请注意,赏金注释中提到的list表达式问题"No viable alternative input"也可通过以上编辑的语法解决。

1 个答案:

答案 0 :(得分:0)

  • 始终摆脱控制台输出中的警告。在你的情况下: warning(125): expr.g4:114:35: implicit definition of token 'DateTime' in parser warning(125): expr.g4:119:31: implicit definition of token 'String' in parser warning(125): expr.g4:234:14: implicit definition of token 'SCharSequence' in parser 明确定义所有标记(我将DateTime替换为datetime)。
  • 您无法在解析器规则(SCharSequence)中使用片段规则。也尝试不在另一个令牌中使用令牌。
  • 在更常见的toknes(id,digit等)之前放置关键字(if,else,for等)。
  • 尽可能避免左递归(在您的情况下为expression&amp; assignmentExpression)。并尽可能利用EBNF的力量。

因此,我的语法更正版本可以正确解析您的示例表达式:

grammar expr;

/*
 * Parser Rules
 */

prog
    :   compoundScript EOF
    ;

compoundScript
    :  ( '{' script '}' )+
    |  ( script )
    ;

script
    :   (declaration* statement*)
    |   statement*
    ;

iterationStatement
    :   'for' '(' identifier 'in' collection ')' statement
    ;

collection
    :   list|data | identifier
    ;

statement
    :   expressionStatement
    |   conditionStatement
    |   iterationStatement
    |   '{' statement? '}'
    ;

conditionStatement
    :   'if' '(' expression ')' statement ('else' statement)?
    ;

expressionStatement
    :   expression ';'?
    ;

declaration
    :   constantObjectDeclaration+
    ;

constantObjectDeclaration
    :   'set' identifier 'as' constantObject ';'?
    ;

constantObject
    :   identifier '.' identifier '[' value ']'
    ;

expression
    :   assignmentExpression (',' assignmentExpression)*
    ;

assignmentExpression
    :   postfixExpression assignmentOperator=AssignmentOperator postfixExpression    
    |   conditionalExpression
    ;

conditionalExpression
    :   logicalOrExpression ('?' expression ':' conditionalExpression)?
    ;

logicalOrExpression
    :   logicalAndExpression
    |   logicalOrExpression '||' logicalAndExpression
    ;

logicalAndExpression
    :   logicalCondition
    |   logicalAndExpression '&&' logicalCondition
    ;

postfixExpression
    :   primaryExpression       
    |   postfixExpression '[' expression ']'
    |   postfixExpression '.' Advance '.' Digits '.' identifier
    |   postfixExpression '.' Main '.' Digits '.' identifier
    |   postfixExpression '.' Split '.' Digits '.' identifier       
    |   postfixExpression '++'          // Ensure only variable++
    |   postfixExpression '--'          // Ensure only variable--
    ;

primaryExpression
    :   identifier
    |   constant
    |   StringLiteral+
    |   calcExpr                        
    |   list
    |   '(' expression ')'
    ;

calcExpr 
    :   calcExpr op=(MulDivOperator | '^') calcExpr  # MulDivExpo
    |   calcExpr op=AddSubOperator calcExpr          # AddSub
    |   number                                       # IntValue
    |   data                                         # DataValue
    |   identifier                                   # IdentifierValue
    |   constant                                     # ConstantValue
    |   '(' calcExpr ')'                             # ExprWithParens
    ;

logicalCondition
    :   data instructionOption number           # LeftDataRightNumber
    |   number instructionOption data           # LeftNumberRightData
    |   data instructionOption data             # LeftDataRightData

    |   constant instructionOption datetime     # LeftConstantRightDateTime
    |   data instructionOption datetime         # LeftDataRightDateTime
    |   datetime instructionOption data         # LeftDateTimeRightData 
    |   datetime instructionOption constant     # LeftDateTimeRightConstant

    |   data instructionOption StringLiteral           # LeftDataRightString
    |   StringLiteral instructionOption data           # LeftStringRightData
    |   StringLiteral instructionOption constant       # LeftStringRightConstant

    |   constant instructionOption constant     # LeftConstantRightConstant
    |   constant instructionOption StringLiteral       # LeftConstantRightString

    |   constant instructionOption number       # LeftConstantRightNumber
    |   number instructionOption constant       # LeftNumberRightConstant

    |   constant instructionOption data         # LeftConstantRightData
    |   data instructionOption constant         # LeftDataRightConstant

    |   identifier instructionOption constant   # LeftIdentifierRightConstant
    |   constant instructionOption identifier   # LeftConstantRightIdentifier

    |   identifier instructionOption data       # LeftIdentifierRightData
    |   data instructionOption identifier       # LeftDataRightIdentifier

    |   data In list                    # LeftDataInRightList
    |   constant In list                # LeftConstantInRightList
    |   value In list                   # LeftValueInRightList
    |   identifier In list              # LeftIdentifierInRightList

    |   '(' logicalCondition ')'        # ConditionWithParens
    ;

instructionOption
    :   keyword | Operator | AssignmentOperator | MulDivOperator | AddSubOperator
    ;

list 
    :   LeftBracket (dataList |  constantList | valueList |  identifierList)? RightBracket
    ;

dataList
    :   data ( Comma data )*
    ;

constantList
    :   constant ( Comma constant )*
    ;

valueList
    :   value ( Comma value )*
    ;

identifierList
    :   identifier ( Comma identifier )*
    ;

value 
    :   number
    |   StringLiteral
    ;

constant 
    :   (('$''{') (NonDigit | DigitsNondigits) '}')
    ;

data 
    :   identifier '.' (MetaData '.')? identifier
    ;

datetime 
    :   Quote Digits '-' Digits '-' Digits Quote
    |   Quote Digits '/' Digits '/' Digits Quote
    |   Quote Digits '-' Digits '-' Digits Space Digits ':' Digits Quote
    |   Quote Digits '/' Digits '/' Digits Space Digits ':' Digits Quote
    ;

deliveryType 
    :   Advances | Mains | Splits 
    ;

number 
    :   Digits (Dot Digits)?
    ;

keyword
    :   Else
    |   For
    |   If
    |   Before
    |   Contains
    |   After
    |   And
    |   Or
    |   In
    |   Set
    |   StartsWith
    |   EndsWith
    ;

separator 
    :   '-' | '/' | ':'
    ;

identifier 
    :   NonDigit | DigitsNondigits
    ;

//fragment

AssignmentOperator
    :   '='
    |   '*='
    |   '/='
    |   '%='
    |   '+='
    |   '-='
    |   '^='
    ;

MulDivOperator
    :   '*'
    |   '/'
    ;

AddSubOperator
    :   '+'
    |   '-'
    ;

Operator
    :   '%'
    |   '&'
    |   '!'
    |   '<'
    |   '>'
    |   '=='
    |   '!='
    |   '<='
    |   '>='
    |   '&&'
    |   '||'
    |   '++'
    |   '--'
    ;

/*
 * Lexer Rules
 */

Deliveries      : 'Deliveries';
Advances        : 'Advances';
Mains           : 'Mains';
Splits          : 'Splits';

Else            : 'else';
For             : 'for';
If              : 'if';
Advance         : 'Advance';
Main            : 'Main';
Split           : 'Split';
Before          : 'before';
Contains        : 'contains';
After           : 'after';
And             : 'and';
Or              : 'or';
In              : 'in';
Set             : 'Set';
StartsWith      : 'startsWith';
EndsWith        : 'endsWith';
MetaData        : 'MetaData';

//LeftParen       : '(';
//RightParen      : ')';
LeftBracket     : '[';
RightBracket    : ']';
//LeftBrace       : '{';
//RightBrace      : '}';

Less            : '<';
LessEqual       : '<=';
Greater         : '>';
GreaterEqual    : '>=';

Plus            : '+';
PlusPlus        : '++';
Minus           : '-';
MinusMinus      : '--';
Star            : '*';
Div             : '/';
Mod             : '%';

AndAnd          : '&&';
OrOr            : '||';
Caret           : '^';
Not             : '!';

Question        : '?';
Colon           : ':';
Semi            : ';';
Comma           : ',';

Assign          : '=';
StarAssign      : '*=';
ExpoAssign      : '^=';
DivAssign       : '/=';
ModAssign       : '%=';
PlusAssign      : '+=';
MinusAssign     : '-=';

Equal           : '==';
NotEqual        : '!=';
Space           : ' ' -> skip;
DoubleQuote     : '"';
Dot             : '.';

NewLine         : ('\r' '\n' ? | '\n') -> skip;
BlockComment    : '/*' .*? '*/' -> skip;

LineCommentOption1  : '//' ~[\r\n]* -> skip;
LineCommentOption2  : '#' ~[\r\n]* -> skip;

WS  :   ('\r' | '\n' | '\t') -> channel(HIDDEN);

NonDigit 
    :   [a-zA-Z_]+
    ;

Digits
    :   [0-9]+
    ;   

DigitsNondigits 
    :   [a-zA-Z0-9_]+
    ;

StringLiteral
    :   Quote SCharSequence? Quote
    ;

Quote 
    :   ('\"'|'\'') -> channel(HIDDEN)
    ;

fragment SCharSequence
    :   SChar+
    ;

fragment
SChar
    :   ~["\\\r\n']
    |   EscapeSequence
    ;
fragment
EscapeSequence
    :   SimpleEscapeSequence
    ;
fragment
SimpleEscapeSequence
    :   '\\' ['"?abfnrtv\\]
    ;