ANTLR4 在输入 'do { return' 错误时没有可行的选择?

ANTLR4 no viable alternative at input 'do { return' error?

当我尝试解析输入时,此 ANTLR4 解析器语法错误 'no viable alternative'。我所知道的唯一匹配输入错误部分的规则是规则 'retblock_expr' 和 'block_expr'。我已将 'retblock_expr' 放在 'block_expr' 前面并将 'non_assign_expr' 放在 'retblock_expr' 前面,但它仍然会引发错误。

输入:

print(do { return a[3] })

完全错误:

line 1:11 no viable alternative at input '(do { return'

解析器语法:

parser grammar TestP;
options { tokenVocab=Test; }
program: (  (   block_expr | retblock_expr  ) ( wsp (   block_expr | retblock_expr  ) wsp   )* wsp  )? EOF;
retblock_expr
    : isglobal DEF wsp fcreatable wsp fcall wsp (   DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #FuncBlockA
    | FUNC wsp fcall wsp (  DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #CFuncBlockA
    | LAMBDA wsp fcall wsp (    DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #LambdaBlockA
    | SWITCH wsp atompar_option wsp (   DO wsp  )? (    LBC wsp (CASE wsp atompar_option wsp (  block_expr wsp END | LBC wsp block_expr wsp RBC )   )* (    DEFAULT wsp atompar_option wsp (    block_expr wsp END | LBC wsp block_expr wsp RBC )   )? wsp RBC | (CASE wsp atompar_option wsp ( block_expr wsp END | LBC wsp block_expr wsp RBC )   )* (    DEFAULT wsp atompar_option wsp (    block_expr wsp END | LBC wsp block_expr wsp RBC )   )? wsp END  ) #SwitchBlockA
    | DO wsp (  LBC wsp block_expr wsp RBC | block_expr wsp END ) #DoBlockA
;
non_assign_expr
    : ( iterable (  (   DOT | SUP | SIB ) iterable  )+ | index  ) #AccessExpr
    | ( call | datat | LPR non_assign_expr RPR | LBC non_assign_expr RBC | LBR non_assign_expr RBR  ) #BracketsExpr
    | ( STR | KUN   )+ indexable #UnpackExpr
    | <assoc=right>  non_assign_expr (  wsp POW wsp non_assign_expr )+ #PowExpr
    | non_assign_expr ( wsp (   INC | DEC   ) wsp non_assign_expr | INC | DEC   )+ #CrementExpr
    | ( PLS | MNS | BNT | EXC | LEN | NOT   )+ non_assign_expr #UnaryExpr
    | non_assign_expr EXC+ #FactExpr
    | non_assign_expr ( wsp (   STR | DIV | PER | FDV | CDV ) wsp non_assign_expr | PER )+ # AdvExpr
    | non_assign_expr ( wsp (   PLS | MNS   ) wsp non_assign_expr   )+ #BasicExpr
    | non_assign_expr ( wsp CON wsp non_assign_expr )+ #ConcatExpr
    | non_assign_expr ( wsp (   BLS | BRS   ) wsp non_assign_expr   )+ #ShiftExpr
    | non_assign_expr ( wsp (   LET | LTE | GRT | GTE   ) wsp non_assign_expr   )+ #CompareExpr
    | non_assign_expr ( wsp (   EQL | IS | NEQ | IS wsp NOT ) wsp non_assign_expr   )+ #EqualExpr
    | non_assign_expr ( wsp BND wsp non_assign_expr )+ #BitAnd
    | non_assign_expr ( wsp BXR wsp non_assign_expr )+ #BitXor
    | non_assign_expr ( wsp BOR wsp non_assign_expr )+ #BitOr
    | <assoc=right> non_assign_expr (   wsp (   AND | TND   ) wsp non_assign_expr wsp ( OR | TOR    ) wsp non_assign_expr   )+ #Ternary
    | non_assign_expr ( wsp (   NND | AND   ) wsp non_assign_expr   )+ #AndExpr
    | non_assign_expr ( wsp (   NXR | XOR   ) wsp non_assign_expr   )+ #XorExpr
    | non_assign_expr ( wsp (   NOR | OR    ) wsp non_assign_expr   )+ #OrExpr
    | retblock_expr #RBlockA
    | typet LPR non_assign_expr RPR #TypeCastA
    | atom #AtomNAE
;
block_expr
    : IF wsp non_assign_expr wsp (  (   THEN wsp block_expr | LBC wsp block_expr wsp RBC    ) wsp ( (   ELIF wsp non_assign_expr wsp THEN wsp block_expr | ELIF wsp non_assign_expr wsp LBC wsp block_expr wsp RBC  )* ELSE wsp (   block_expr wsp END | LBC wsp block_expr wsp RBC ) | (   ELIF wsp non_assign_expr wsp THEN wsp block_expr | ELIF wsp non_assign_expr wsp LBC wsp block_expr wsp RBC  )*? (   ELIF wsp non_assign_expr wsp THEN wsp block_expr wsp END | ELIF wsp non_assign_expr wsp LBC wsp block_expr wsp RBC  )   ) | (   THEN wsp block_expr wsp END | LBC wsp block_expr wsp RBC    )   ) #IfBlock
    | TRY wsp ( block_expr wsp (    EXCEPT (LPR wsp IDN wsp RPR)? wsp (  (  (DO wsp)? LBC wsp block_expr wsp RBC | DO wsp block_expr wsp END | block_expr   ) wsp   )? FINALLY wsp (    block_expr wsp END | LBC wsp block_expr wsp RBC ) | EXCEPT (LPR wsp IDN wsp RPR)? wsp ( block_expr wsp END | LBC wsp block_expr wsp RBC )   ) | (   block_expr wsp END | LBC wsp block_expr wsp RBC )   ) #DebugBlock
    | FOR wsp av_var wsp TOR wsp av_inc wsp CMA wsp av_inc wsp (    CMA wsp av_inc wsp  )? (    DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #RangeBlock
    | FOR wsp av_var wsp CMA wsp non_assign_expr wsp CMA wsp non_assign_expr wsp CMA wsp non_assign_expr wsp (  DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #ActionBlock
    | FOR wsp IDN wsp ( TOR wsp non_assign_expr )? (    wsp CMA wsp (   IDN wsp (   TOR wsp non_assign_expr )?  )? (    wsp CMA wsp IDN wsp TOR wsp non_assign_expr )*  )? IN wsp iterable wsp (    DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #IterationBlock
    | ( WHILE wsp non_assign_expr wsp ( DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) | DO wsp (    LBC wsp block_expr wsp RBC | block_expr ) wsp WHILE wsp non_assign_expr ) #WhileBlock
    | ( (   DO | REPEAT ) wsp ( LBC wsp block_expr wsp RBC | block_expr ) wsp UNTIL wsp non_assign_expr | UNTIL wsp non_assign_expr wsp (   DO | REPEAT ) ( LBC wsp block_expr wsp RBC | block_expr wsp END )   ) #RepeatBlock
    | isglobal DEF wsp fcreatable wsp fcall wsp (   DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #FuncBlock
    | FUNC wsp fcall wsp (  DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #CFuncBlock
    | LAMBDA wsp fcall wsp (    DO wsp  )? (    LBC wsp block_expr wsp RBC | block_expr wsp END ) #LambdaBlock
    | SWITCH wsp atompar_option wsp (   DO wsp  )? (    LBC wsp (CASE wsp atompar_option wsp (  block_expr wsp END | LBC wsp block_expr wsp RBC )   )* (    DEFAULT wsp atompar_option wsp (    block_expr wsp END | LBC wsp block_expr wsp RBC )   )? wsp RBC | (CASE wsp atompar_option wsp ( block_expr wsp END | LBC wsp block_expr wsp RBC )   )* (    DEFAULT wsp atompar_option wsp (    block_expr wsp END | LBC wsp block_expr wsp RBC )   )? wsp END  ) #SwitchBlock
    | DO wsp (  LBC wsp block_expr wsp RBC | block_expr wsp END ) #DoBlock
    | LPR block_expr RPR #EnclosedBlockA
    | LBC block_expr RBC #EnclosedBlockB
    | block #OpenBlock
;
atompar_option
    : LPR wsp atom wsp RPR
    | atom
;
isglobal: ( GLOBAL wsp  )?;
block: (    stat+ wsp (PASS | retstat)* )+ | PASS;
stat
    : expression+ wsp SMC*
    | expression* wsp SMC+
;
retstat: RETURN wsp non_assign_expr;
expression
    : <assoc=right> isglobal var_list ( wsp aop wsp expression  )+ #AssignExpr
    | exp_list #ExpListA
    | non_assign_expr #NonAssign
    | atom #AtomEXPR
    | IVC #InvalidCharacter
;
literal
    : strt
    | num
;
datat
    : listd
    | dictd
    | setd
    | tupled
;
wsp: WSP*;
listd
    : LBR wsp exp_list wsp RBR
    | EML
;
dictd
    : LBC wsp kvpair wsp
    (
        CMA
        wsp
        kvpair
        wsp
    )*
    RBC
;
setd
    : LBC wsp exp_list wsp RBC
    | EMS
;
indexable
    : ( dictd | IDN | ( (   datat | IDN | strt  )   ) LBR non_assign_expr RBR | (   datat | IDN | strt  ) ( (   DOT | SUP | SIB ) ( datat | IDN | strt  )   )+  ) fcall
    | ( (   datat | IDN | strt  )   ) LBR non_assign_expr RBR
    | ( datat | IDN | strt  ) ( (   DOT | SUP | SIB ) ( datat | IDN | strt  )   )+
    | IDN
    | datat
;
iterable
    : indexable
    | strt
;
numidn
    : num
    | IDN
;
av_numidn
    : numidn
    | av_var
;
av_inc
    : av_numidn
    | call
;
tupled: LPR wsp (exp_list | CMA) wsp RPR;
kvpair: non_assign_expr wsp TOR wsp non_assign_expr;
index
    : ( iterable    ) LBR non_assign_expr RBR
    | iterable (    (   DOT | SUP | SIB ) iterable  )+
;
var_list: ( typet wsp   )? av_var ( wsp CMA wsp (   typet wsp   )? var_list)*;
av_var
    : IDN
    | index
;
exp_list: non_assign_expr (wsp CMA wsp non_assign_expr)*;
atom
    : num
    | av_var
    | strt
    | typet
    | ckw
    | val
    | datat
;
aop
    : A_FDV // '//='
    | A_CDV // '*/='
    | A_NOR // '||='
    | A_FAC // '=!='
    | A_LTE // '=<='
    | A_GTE // '=>='
    | A_EQL // '==='
    | A_NEQ // '!=='
    | A_CON // '..='
    | A_NXR // '$$='
    | A_BRS // '>>='
    | A_NND // '&&='
    | A_BLS // '<<='
    | A_DCL // '::='
    | A_CLD // ':.='
    | A_KUN // '=**'
    | A_VUN // '=*'
    | A_DOT // '.='
    | A_POW // '^='
    | A_NOT // '=!'
    | A_BNT // '=~'
    | A_LEN // '=#'
    | A_PER // '=%'
    | A_MUL // '*='
    | A_DIV // '/='
    | A_MOD // '%='
    | A_ADD // '+='
    | A_SUB // '-='
    | A_LET // '=<'
    | A_GRT // '=>'
    | A_BND // '&='
    | A_BXR // '$='
    | A_BOR // '|='
    | A_TND // '?='
    | A_TOR // ':='
    | A_NML // '='
;
num
    : exponential
    | non_exponential
;
exponential
    : PXI
    | DXI
    | PXF
    | DXF
    | PXB
    | DXB
    | PXD
    | DXD
    | PXP
    | DXP
    | PRX
    | DEX
;
non_exponential
    : IMG
    | FLT
    | DBL
    | DCM
    | PRC
    | INT
;
fcreatable
    : dictd
    | av_var
;
callablets
    : fcreatable
    | retblock_expr
    | ckw
;
fcall
    : CLP
    | LPR arg_list RPR
;
call: callablets fcall;
arg_list: arg_type (    wsp CMA wsp arg_type    )*;
arg_type
    : u_var_list wsp aop wsp u_exp_list
    | unkeyed_var
;
unkeyed_var
    : LPR var_list RPR
    | LBR var_list RBR
    | LBC var_list RBC
    | var_list
;
u_var_list: unkeyed_var (   wsp aop wsp u_var_list  )*;
u_exp_list: unkeyed_exp (   wsp CMA wsp unkeyed_exp )*;
unkeyed_exp
    : tupled
    | listd
    | setd
    | non_assign_expr
;
litidn
    : literal
    | IDN
;
typecast: typet LPR non_assign_expr RPR;
strt
    : multi_line
    | single_line
    | char_string
;
multi_line
    : SMT
    | USM
    | NMT
    | UNM
;
single_line
    : SST
    | USS
    | NST
    | UNS
    | NAS
;
char_string
    : SCH
    | USC
    | NCH
    | UNC
    | NAC
;
typet
    : STRT
    | INTT
    | NUMT
    | DECIMALT
    | FLOATT
    | DOUBLET
    | PRECISET
    | EXPNT
    | CHART
    | IMAGT
    | REALT
    | HEXTY
    | BINTY
    | OCTTY
    | LISTD
    | SETD
    | DICTD
    | TUPLED
    | TYPET
    | BOOLT
;

bks_or_WSP
    : WSP
    | BKS
    | SPC
;
emd
    : EML
    | EMS
;
sep
    : SMC
    | CMA
    | TOR
;

kwr
    : WHILE
    | FOR
    | DO
    | DEL
    | NEW
    | IMPORT
    | EXPORT
    | DEF
    | END
    | GLOBAL
    | BREAK
    | CONTINUE
    | NOT
    | AND
    | OR
    | IN
    | CASE
    | DEFAULT
    | RETURN
    | TRY
    | EXCEPT
    | FINALLY
    | ELIF
    | IF
    | ELSE
    | AS
    | CONST
    | REPEAT
    | UNTIL
    | THEN
    | GOTO
    | LABEL
    | USING
    | PUBLIC
    | PROTECTED
    | PRIVATE
    | SELF
    | FROM
    | XOR
    | IMAGT
    | REALT
    | WHERE
    | PASS
    | G_G
    | L_L
    | MAP
    | IS
;
ckw
    : OPN
    | OUT
    | OUTF
    | PRINT
    | PRINTF
    | LAMBDA
    | FUNC
    | ERR
    | ERRF
    | ASSERT
    | ASSERTF
    | FORMAT
    | SWITCH
    | ABS
    | ASCII
    | CALLABLE
    | CHR
    | DIR
    | EVAL
    | EXEC
    | FILTER
    | GET
    | HASH
    | ID
    | INST
    | SUB
    | SUPER
    | MAX
    | MIN
    | OBJ
    | ORD
    | POWF
    | REV
    | REPR
    | ROUND
    | FLOOR
    | CEIL
    | MUL
    | SORT
    | ADD
    | ZIP
    | WAIT
    | SECS
    | MILS
    | BENCHMARK
;

val
    : RMH // 'inf'
    | IMH // 'infi'
    | NAN // 'nan'
    | IND // 'ind'
    | UND // 'und'
    | NIL // 'nil'
    | NON // 'none'
    | TRU // 'true'
    | FLS // 'false'
;

opr
    : NND // '&&'
    | NXR // '$$'
    | NOR // '||'
    | CLP // '()'
    | SUP // '::'
    | SIB // ':.'
    | KUN // '**'
    | INC // '++'
    | DEC // '+-'
    | FDV // '//'
    | CDV // '* /'
    | CON // '..'
    | BLS // '<<'
    | BRS // '>>'
    | LTE // '<='
    | GTE // '>='
    | EQL // '=='
    | NEQ // '!='
    | LPR // '('
    | RPR // ')'
    | LBR // '['
    | RBR // ']'
    | LBC // '{'
    | RBC // '}'
    | STR // '*'
    | POW // '^'
    | PLS // '+'
    | MNS // '-'
    | BNT // '~'
    | EXC // '!'
    | LEN // '#'
    | PER // '%'
    | DIV // '/'
    | LET // '<'
    | GRT // '>'
    | BND // '&'
    | BXR // '$'
    | BOR // '|'
    | TND // '?'
    | TOR // ':'
    | DOT // '.'
;

inl
    : strt
    | num
    | ckw
    | kwr
    | val
    | IDN
    | bks_or_WSP
    | sep
    | emd
    | aop
    | opr
    | typet
    | IVC
;

您的 PRINT 令牌只能通过此路径与 blk_expr 规则匹配:

retblock_expr 无法识别以 PRINT 标记开头的任何内容。

因此,您的顺序是 elk_expr 还是 retblock_expr

您的语法中没有匹配 PRINT 标记后跟 LPR 标记的解析器规则。 block_exprprogram 规则匹配,它只匹配(忽略 wsp)block_exprretblock_expr。这些都没有以 LPR 标记开头的替代项,因此 ANTLR 无法匹配该标记。

print(...) 通常会作为接受 0 个或多个逗号分隔参数的函数调用表达式进行匹配。您不确定 rule/alternative 的定义。 (我 猜测 它应该是 retblock_exprblock_expr

的替代方案

这是此错误的直接原因。 ANTLR 确实没有任何 rule/alternative 可以在这个位置接受 LPR 令牌。