如何编写符合要求的BNF:支持无限元素列表且append仅接受多列表
Hey there! Let's break down your original BNF and adjust it to fully meet your requirements.
Issues in the Original Grammar
- Undefined Non-Terminal:
<SNS>isn't defined—we need to explicitly distinguish atomic elements (symbols/numbers) from compound lists to enforce the append rule. - Invalid Recursion: The mutual recursion between
<LIST>and<APPEND>allows append to accept atomic symbols (since<LIST>includes<SNS>), which violates your requirement that append can't take single symbols directly. - Redundant Productions: Your
<LIST>rules for(list <SNS>),(list <LIST>), etc., can be simplified into a single production that handles any number of elements. - Misaligned
<APPEND>Definition: Including<LIST>as an alternative for<APPEND>implies an atomic symbol is a valid append expression, which doesn't fit with append being a function call.
Corrected BNF
This grammar clearly separates atomic elements from compound lists, enforces append's parameter rules, and supports lists with any combination of symbols, numbers, or other lists:
# Terminal symbols (adjust regex patterns to match your syntax needs) <SYMBOL> ::= [a-zA-Z_][a-zA-Z0-9_]* <NUMBER> ::= [0-9]+(\.[0-9]+)? # Atomic elements (symbols/numbers—these are not considered lists themselves) <ATOM> ::= <SYMBOL> | <NUMBER> # Elements allowed inside a list: atoms or other lists <LIST_ELEMENT> ::= <ATOM> | <LIST> # Literal list: empty list or list with 1+ elements <LITERAL_LIST> ::= (list) | (list <LIST_ELEMENT> <LIST_ELEMENT>*) # Append function: accepts 1+ lists as arguments (no atoms allowed) <APPEND_CALL> ::= (append <LIST> <LIST>*) # A List is either a literal list or the result of an append call <LIST> ::= <LITERAL_LIST> | <APPEND_CALL>
How This Meets Your Requirements
- List Content:
<LITERAL_LIST>can contain any number of symbols, numbers, or other lists (literal or append-derived). Examples of valid lists:(list apple 42 (list banana cherry))(append (list x) (list y z))(list (append (list 10) (list 20)) orange)
- Append Function Rules:
<APPEND_CALL>only accepts<LIST>arguments (literal lists or other append calls), so atomic symbols/numbers can't be passed directly.- Valid append calls:
(append (list a) (list b)),(append (list 1) (append (list 2) (list 3))) - Invalid append calls (rejected by the grammar):
(append a),(append 5 (list b))
- Valid append calls:
Optional Variant: Atoms as Singleton Lists
If you intended atoms to be treated as single-element lists (common in some functional languages), we can adjust the grammar to allow that while still blocking atoms in append arguments:
<SYMBOL> ::= [a-zA-Z_][a-zA-Z0-9_]* <NUMBER> ::= [0-9]+(\.[0-9]+)? <ATOM> ::= <SYMBOL> | <NUMBER> # A "list value" can be an atom (singleton) or a compound list <LIST_VALUE> ::= <ATOM> | <COMPOUND_LIST> # Elements inside compound lists can be any list value <LIST_ELEMENT> ::= <LIST_VALUE> <LITERAL_LIST> ::= (list) | (list <LIST_ELEMENT> <LIST_ELEMENT>*) # Append only accepts compound lists (no atoms directly) <APPEND_CALL> ::= (append <COMPOUND_LIST> <COMPOUND_LIST>*) # Compound lists are literal lists or append calls <COMPOUND_LIST> ::= <LITERAL_LIST> | <APPEND_CALL>
In this variant:
appleor42count as valid<LIST_VALUE>s (singleton lists)- But
(append apple)is invalid, while(append (list apple))is allowed—preserving your rule that append can't take single symbols directly.
内容的提问来源于stack exchange,提问作者Tomer
相关产品推荐
相关产品推荐

