2016-02-29 62 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