2016-02-29 67 views
1

我正在为我正在处理的自定义脚本编写解析器。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"也可以通过上面编辑的语法解决。

+0

我打了一下与你的语法和[这里](https://开头要点。 github.com/anonymous/e4ee73d8db14dd1870c2)是一些输出(我个人不认为这是一个答案,因为你的语法肯定需要比知道更多的人做更多的工作 - 但你可能会发现这种鼓舞人心的或有趣的)。祝你好运! – vlp

+0

@vlp考虑你的增强和对它的一点改变 - 我能够做出一点点头。但是我的一些表达式产生了“没有可行的替代输入,当你提供'a = [1]'时,例子列表语法有效,但当你提供'a = [1,2,3]'时不会。”等等。如果条件语法 – Bitmap

+0

由于'list'表达式导致“没有可行的替代输入”问题可以通过编辑后的语法来解决 – Bitmap

回答

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等)之前放置关键字(如果,否则等)。
  • 尽可能地避免左递归(表达式& 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\\] 
    ; 
+0

对不起,我应该提到我的语法的编辑版本已经可以正确解析我的表达式了。 if语句和for循环,例如“if语句给出的表达式”以“错误输入”结尾 – Bitmap

+0

@Bitmap,我为你的案例修正了语法并添加了新项目 –

+0

谢谢@KvanTTT - 匹配表达式''输入如'a = 1,b = 2,c = 3'会导致'无关输入',''。你知道为什么吗?我已经尝试过'expression :assignmentExpression | expression(','assignmen t表达式) ;'仍然没有工作): – Bitmap