我正在为我正在处理的自定义脚本编写解析器。
当我在基本脚本下面提供时:
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 :(得分: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)。因此,我的语法更正版本可以正确解析您的示例表达式:
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\\]
;