# ==========================================
# EBNF Grammar (Lark Format)
# ==========================================
# We ignore whitespace globally but carefully constrain the KWARG_VAL
# to not cross line boundaries, allowing a very clean EBNF.
WENLI_GRAMMAR = r"""
start: routine*

routine: "---" signature block -> def_routine

// ==========================================
// 1. Declarations & Signatures (Static Scope)
// ==========================================
signature: "#" IDENTIFIER input_decl? param_decl? output_decl? -> def_signature

input_decl: "##" "输入" _COLON decl_item_list -> decl_inputs
param_decl: "##" "参数" _COLON param_default_decl+ -> decl_params
output_decl: "##" "输出" _COLON decl_item_list -> decl_outputs

// Handles both inline tuples ("A、B") and bulleted blocks ("- A：类型")
decl_item_list: ( tuple_assignment | block_var_decl+ )

// L-Value Declarations
block_var_decl: "-" IDENTIFIER _COLON TYPE -> decl_var_block
param_default_decl: "-" IDENTIFIER _COLON expr -> decl_param_default


// ==========================================
// 2. Statements & Control Flow (Execution)
// ==========================================
block: statement*

statement: call_strict invocation_modifiers* -> stmt_strict_call
         | call_agent invocation_modifiers* -> stmt_agent_call
         | call_shell invocation_modifiers* -> stmt_shell_call
         | stmt_if
         | stmt_foreach
         | stmt_exception
         | code_chunk                        -> stmt_code_chunk

// The core execution calls
call_strict: "使用" IDENTIFIER "处理" expr ( _COMMA "保存为" tuple_assignment )? _FULL_STOP
call_agent: STRING ( _COMMA "保存为" tuple_assignment )? _FULL_STOP
call_shell: INLINE_CODE ( _COMMA "保存为" tuple_assignment )? _FULL_STOP

// Modifiers attached to calls
invocation_modifiers: call_kwarg | call_context
call_kwarg: "-" IDENTIFIER _COLON expr -> arg_kwarg
call_context: ">" expr -> arg_context

// Control Flow
stmt_if: "如果" condition_expr "为" BOOLEAN _COMMA "则" _COLON block ( "否则" _COLON block )? "结束判断" IDENTIFIER _FULL_STOP
stmt_foreach: "对于" expr "中的每一个" IDENTIFIER _COLON block "结束处理" IDENTIFIER _FULL_STOP

stmt_exception: "报错" expr _FULL_STOP
code_chunk: CODE_BLOCK


// ==========================================
// 3. Expressions & Values (R-Values vs L-Values)
// ==========================================

// Conditions tailored specifically for IF statements
condition_expr: eval_condition | IDENTIFIER -> cond_var
eval_condition: ( "使用" IDENTIFIER "处理" expr | STRING ) "以得到" IDENTIFIER -> cond_eval

// L-Values: Assignment Targets (Where data goes)
tuple_assignment: lvalue_annotated ( _ENUM_COMMA lvalue_annotated )*
lvalue_annotated: IDENTIFIER ( "（" TYPE "）" )?

// R-Values: Expressions (Where data comes from)
expr: list_expr | single_expr
list_expr: single_expr ( _ENUM_COMMA single_expr )+ -> expr_list

single_expr: type_cast | IDENTIFIER | literal
type_cast: ( STRING | IDENTIFIER ) "（" TYPE "）" -> expr_type_cast

literal: NUMBER -> lit_number
       | BOOLEAN -> lit_boolean
       | STRING -> lit_string


// ==========================================
// 4. Lexical Tokens
// ==========================================
TYPE: IDENTIFIER

IDENTIFIER: /(?!使用)(?:(?!为真|为假|处理|中的每一个|以得到)[a-zA-Z0-9\u4e00-\u9fa5_…])+/
NUMBER: /[0-9 ]*.?[0-9 ]*[0-9]/
BOOLEAN: "真" | "假"
STRING: /“[^”]*”/

INLINE_CODE: /`[^`]+`/
CODE_BLOCK: /[ \t]*```[ \t]*[a-zA-Z0-9_-]*[ \t]*\n[\s\S]*?\n[ \t]*```/
COMMENT: /####[^\n]*/

// --- Named Punctuation Tokens ---
_FULL_STOP: "。"
_COMMA: "，"
_ENUM_COMMA: "、"
_COLON: "："

%import common.WS
%ignore WS
%ignore COMMENT
"""