Angex 语法规范(钓法表达式)
本文由 AI 生成
本文档以 AngexParser 的实际实现为准,是 Angex 的权威语法规范,面向高级用户与开发者。 本文明确不包含正则解析器的语法。
下文描述的是当前解析器能够接受的语法。如需扩展语法,请先修改此规范,再修改解析器。
记号说明
- 采用 EBNF 风格。
WS表示可选空白;解析器在多数位置会跳过空白。- 终结符用字面量表示,如
"平钓"或">"。 - 某些规则由解析器自定义逻辑实现,以下以文字说明。
词法 / 符号
空白
- 空白可出现在大多数标记之间,解析器会跳过它们。
- 括号内容中的空白会保留,并在列表项级别进行
Trim。
等价符号
- 阶段分隔符:
>与》 - 游动饵标记:
<与《 - 段分隔符:
;与; - 咬饵标记:
!与! - 括号对:
[]、【】、(),( ) - 天气括号仅允许
()或( )
列表分隔符
- 目标/天气列表分隔符:
、或|| - 修饰词列表分隔符:
、、|| - 注意:单个
|保留给name|id的IdOrName语法。
排除前缀
- 支持全角
?与半角?。
备注
//开始备注,直到文本结尾。
关键字
模式
平钓 | 大鱼 | 耐心 | nm | bf | pt
咬饵类型
全部 | all | ! | !! | !!!(! 数量为 1-3)
提钩类型
强力 | 精准 | 双重 | 双提 | 三重 | 三提 | 华丽 | pw | pc | dh | th | sh
阶段 1 的内联特殊
拍水 | 拍 | ss | 专一 | 专 | ic
嵌套关键字
阶段 | stg | stage | 鱼识 | int | 拍水后 | pss | 专一后 | pic | 拍水 | 拍 | ss | 专一 | 专 | ic
修饰词(全局参数)
不撒饵/nochum, 收藏品/coll, 不收集/nocoll, 钓组/snag, 大尺寸/large, 攒鱼计/aa, 套娃/mooch-loop, 梭哈/all-in, 等待专一/waitic, 大鱼知识/bfg, 引诱/lure, 雄心/a-lure, 谦逊/m-lure, 重随/re-roll, 鱼影/shadow, 多提/mhs, 加钩/mh, 回收/recy, 鱼眼/fe, 鱼篓/sh, 鱼篓专一/sh-ic, 多提回退/mhs-back, 允许溢出/overflow, 等待华丽/wait-sh, 跳阶段/skipstg, 强制预备/force-prep, 银星/silver, 无强心剂/nocord, 无恩宠/nofavor
补充:引诱/雄心/谦逊/鱼影/重随 可在末尾追加正整数以限制引诱叠层上限(按当前身上引诱 buff 层数判断),例如 引诱2、a-lure3。当存在 鱼影 或 重随 修饰词时,该限制不生效。
语法(EBNF)
Expression ::= WS* Mode WS* BaitOpt WS* WindowOpt WS* Arrow WS* Phase1
(WS* Arrow WS* Phase)* WS* GlobalParamsOpt WS* NestedExprsOpt WS* RemarkOpt WS* ;
Mode ::= "平钓" | "大鱼" | "耐心" | "nm" | "bf" | "pt" ;
Arrow ::= ">" | "》" ;
BaitOpt ::= BracketedId | ε ;
BracketedId ::= Brackets IdOrName ;
Brackets ::= "[" "]" | "【" "】" | "(" ")" | "(" ")" ;
WindowOpt ::= "@" WS* EtRangeOpt WS* WeatherOpt | ε ;
EtRangeOpt ::= EtRange | ε ;
EtRange ::= EtTime WS* ("-" | "~") WS* EtTime ;
EtTime ::= Digit Digit Digit Digit ;
WeatherOpt ::= WeatherBracket | ε ;
WindowArrow ::= "=" WS* Arrow ;
WeatherBracket ::= ("(" | "(") WeatherInner (")" | ")") ;
WeatherInner ::= WeatherList (WS* WindowArrow WS* WeatherList)? ;
WeatherList ::= IdOrName (WS* ListSep WS* IdOrName)* ;
Phase1 ::= Phase InlineSpecialsOpt ;
Phase ::= ExtraBiteOpt WS* BiteTimeOpt WS* BiteTypes WS* HooksetOpt
WS* SwimbaitOpt WS* TargetsOpt ;
ExtraBiteOpt ::= ("(" | "(") ExtraBiteToken (")" | ")") | ε ;
BiteTimeOpt ::= BiteTimeRange | ε ;
BiteTimeRange ::= RangeStartMax | RangeMin RangeMaxReq ;
RangeStartMax ::= ("-" | "~") Number ("+" Number)? ;
RangeMin ::= Number ("+" Number)? ;
RangeMaxReq ::= RangeMax | RangeOpenEnd ;
RangeMax ::= ("-" | "~") Number ("+" Number)? ;
RangeOpenEnd ::= ("-" | "~") ;
Number ::= Digit+ ("." Digit+)? ;
BiteTypes ::= AllBite | BangToken (WS* "+" WS* BangToken)* ;
AllBite ::= "全部" | "all" ;
BangToken ::= ("!" | "!"){1,3} ;
Bang1to3 ::= ("!" | "!"){1,3} ;
ExtraBiteToken ::= AllBite | Bang1to3 ;
HooksetOpt ::= Hookset Digit? | ε ;
Hookset ::= "强力" | "精准" | "双重" | "双提" | "三重" | "三提" | "华丽"
| "pw" | "pc" | "dh" | "th" | "sh" ;
InlineSpecialsOpt ::= (WS* "@" WS* InlineSpecial)+ | ε ;
InlineSpecial ::= InlineSlap | InlineExclusive ;
InlineSlap ::= ("拍水" | "ss")? WS* InlineSlapBody ;
InlineExclusive ::= ("专一" | "ic") WS* InlineExclusiveBody ;
InlineSlapBody ::= BiteTimeOpt WS* BiteTypesOpt WS* HooksetOpt WS* InlineTarget ;
BiteTypesOpt ::= BiteTypes | ε ;
InlineExclusiveBody ::= TargetSet WS* HooksetOpt ;
InlineTarget ::= SwimbaitTarget | TargetSet ;
SwimbaitOpt ::= SwimbaitTarget | SwimbaitPlaceholder | ε ;
SwimbaitTarget ::= ("<" | "《") WS* TargetSet ;
SwimbaitPlaceholder ::= ("<" | "《") ;
TargetsOpt ::= TargetSet | ε ;
TargetSet ::= Brackets TargetList ;
TargetList ::= TargetToken (WS* ListSep WS* TargetToken)* ;
ListSep ::= "、" | "||" ;
TargetToken ::= ExclusionPrefix? TargetAtom ;
ExclusionPrefix ::= "?" | "?" ;
TargetAtom ::= "any" | "任何" | "占位" | "ph" | "《" | IdOrName ;
IdOrName ::= NAME ("|" UINT)? | UINT ;
GlobalParamsOpt ::= "=" WS* GlobalSeg (WS* SegmentSep WS* GlobalSeg)* WS* SegmentSep | ε ;
SegmentSep ::= ";" | ";" ;
GlobalSeg ::= CounterOrTerm | ModifierList ;
CounterOrTerm ::= UINT? WS* TargetSet ;
ModifierList ::= ModifierToken (WS* ModifierSep WS* ModifierToken)* ;
ModifierSep ::= "、" | "||" ;
ModifierToken ::= <见上文修饰词列表> ;
NestedExprsOpt ::= (WS* NestedExpr)* | ε ;
NestedExpr ::= "@" WS* NestedKind WS* "=" WS* Arrow WS* Expression StageCloseOpt ;
NestedKind ::= "阶段" | "stg" | "stage"
| "鱼识" | "int"
| "拍水后" | "pss"
| "专一后" | "pic"
| "拍水" | "ss"
| "专一" | "ic" ;
StageCloseOpt ::= (WS* ("<" | "《") WS* "=") | ε ;
RemarkOpt ::= "//" RemarkText | ε ;
RemarkText ::= <任意字符直到结尾> ;
WS ::= <空白> ;
Digit ::= "0".."9" ;
UINT ::= Digit+ ;
NAME ::= <不包含列表分隔符的非空文本> ;补充:RangeMin 后仅出现 - 或 ~ 表示“以上”(无上限)。
语义约束与解析说明
窗口期 (
@) 至少包含以下之一:- ET 时间段,或
- 天气集合。 否则报错“窗口期为空”。
- 双段天气必须写在同一组括号内,例如
(晴朗=>阴云)或(晴朗=》阴云)。
ET 时间为 4 位数字(0000-2359),
2400被视为0000。咬饵类型:
- 每个阶段必须存在。
全部/all不能与!混用。
咬饵时间:
- 仅提供一组数值时,必须显式包含
-或~(前置或后置)。
- 仅提供一组数值时,必须显式包含
阶段目标:
- 游动饵目标与普通目标不可同时存在。
额外咬饵类型:
- 支持
全部/all或 1-3 个!。 - 若无效,解析会回退并在后续以“缺少咬饵类型”等错误结束。
- 支持
提钩类型:
- 如果给出多重提钩数量,则必须给出提钩类型。
内联特殊(仅阶段 1):
- 内联拍水必须有目标(
<[...]或[...])。 - 内联专一必须有目标(
[...])。 - 若内联拍水未给咬饵类型,则使用阶段 1 的咬饵类型与咬饵时间。
- 允许出现在阶段 1 目标之前或之后(用于兼容旧写法与序列化输出)。
- 序列化输出时会固定放在阶段 1 目标之前。
- 内联拍水必须有目标(
嵌套表达式:
- 只能出现在全局参数之后。
@阶段=》...必须闭合< =或《 =。@鱼识=》...会尽可能吞掉其后的内容,直到备注开始(//)。- 其他嵌套关键字会消费到下一个嵌套表达式起始或备注起始(允许连续书写多个嵌套表达式)。
- 若存在全局参数,嵌套表达式前必须以分号结束全局参数段。
鱼识 / 拍水后 / 专一后(同级互斥):
- 同一层级最多出现一个(
@鱼识/@拍水后/@专一后),否则报错。 - 不同层级互不影响(例如外层
@鱼识,内层@专一后允许)。
- 全局参数:
=开始全局参数。- 以
;或;分隔多个段。 - 全局参数最后一段必须以
;或;结束(即使后面是嵌套表达式或备注)。 - 没有数量的目标段若位于第一个位置,则视为“终止目标”。
- 计数器必须有数量。
- 修饰词使用
、或||连接,解析器允许仅修饰词而无目标段。 - 引诱相关修饰词尾随数字表示“引诱最多叠到 X 层”,但在
鱼影或重随手法下会被忽略。
- 目标项:
any/任何表示“匹配任何”。占位/ph表示“不匹配任何”。《作为目标项表示鱼篓标记。?/?前缀表示排除模式。
- 天气项:
- 仅支持
IdOrName,不支持排除或占位等特殊项。
- 游动饵占位:
- 单独出现的游动饵操作符(如
《》中的《)会被视为“鱼篓标志”,等价于游动饵目标包含《。
最小示例
平钓》全部
nm > all
耐心【青花鱼块|36593】@1355-1600(晴朗|2)》6.1+10.3~!》!!!《【占位】