NDL Grammar Specification
Overview
This document provides a formal grammar specification for NDL (Natural Description Language) in Extended Backus-Naur Form (EBNF).
Notation
::=- Definition|- Alternative()- Grouping[]- Optional (zero or one){}- Repetition (zero or more)""- Literal terminal<>- Non-terminal
Complete Grammar
<ndl_statement> ::= <action_chain>
<action_chain> ::= <action_element> { "->" <action_element> }
<action_element> ::= <action> [ <modifiers> ]
| <control_statement>
| <meta_statement>
<action> ::= "do" "(" <entity_ref> "," <string> ")"
| "search" "(" <string> [ "," <properties> ] ")"
| "talk" "(" <string> "," <entity_list> ")"
| "convey" "(" <string> [ "," <properties> ] ")"
| "target" "(" <entity_ref> ")"
| "result" "(" [ <string> ] ")"
| "describe" "(" ")"
| "roll" "(" <string> ")"
| "damage" "(" <integer> ")"
<control_statement> ::= "wait" "(" <string> ")"
<meta_statement> ::= "system_response" "(" <string> ")"
<modifiers> ::= <manner> [ <properties> ]
| <properties> [ <manner> ]
<manner> ::= "~" <string>
<properties> ::= <property> { "," <property> }
<property> ::= <identifier> "=" <string>
<entity_ref> ::= "$" <string>
| "$"
<entity_list> ::= <string> { "^" <string> }
<identifier> ::= "intention" | "perspective" | <custom_identifier>
<custom_identifier> ::= [a-z_][a-z0-9_]*
<string> ::= '"' <any_char>* '"'
<integer> ::= [0-9]+
<any_char> ::= /* any character except unescaped " */Production Rules Explained
Statement Level
<ndl_statement>
Top-level construct representing a complete NDL expression.
Examples:
do($"player", "attack")
do($"player", "attack") -> result("success")<action_chain>
Sequence of action elements connected by -> operator.
Examples:
action1
action1 -> action2
action1 -> action2 -> action3Action Level
<action_element>
Individual component in an action chain.
Types:
- Regular actions (
do,search,talk, etc.) - Control statements (
wait) - Meta statements (
system_response)
<action> - Primary Actions
do() Action:
"do" "(" <entity_ref> "," <string> ")"Example: do($"player", "attack with sword")
search() Action:
"search" "(" <string> [ "," <properties> ] ")"Example: search("pile of wood", intention="find weapon")
talk() Action:
"talk" "(" <string> "," <entity_list> ")"Example: talk("Mark", "John"^"Sue")
convey() Action:
"convey" "(" <string> [ "," <properties> ] ")"Example: convey("desire to explore", perspective="adventurous")
Modifiers
<manner> - How Modifier
Specifies how an action is performed.
Syntax:
"~" <string>Example: do($"player", "walk") ~ "carefully"
<properties> - Key-Value Attributes
Additional context for actions.
Syntax:
<identifier> "=" <string>Examples:
intention="intimidate"perspective="hopeful"
Entity References
<entity_ref> - Entity Specification
References to game entities.
Forms:
- Named entity:
$"entity_name" - Implicit entity:
$
Examples:
$"player"
$"goblin"
$"guard"
$<entity_list> - Multiple Entities
Multiple entities connected with ^ (conjunction).
Syntax:
<string> { "^" <string> }Example: "John"^"Sue"^"Bob"
Control Flow
<control_statement> - Wait
Introduces pause or delay.
Syntax:
"wait" "(" <string> ")"Examples:
wait("response validation")
wait("1s")
wait("player input")Meta Elements
<meta_statement> - System Response
System-level messages.
Syntax:
"system_response" "(" <string> ")"Example: system_response("something goes wrong when you try to perform this action")
Operator Precedence
From highest to lowest:
- Function/Action calls -
do(...),wait(...), etc. - Manner modifier -
~ - Property assignment -
= - Sequence -
-> - Conjunction -
^
Associativity
| Operator | Associativity |
|---|---|
-> | Left-to-right |
^ | Left-to-right |
~ | Postfix |
= | N/A (not chained) |
Grammar Examples
Simple Action
do($"player", "walk")Parse Tree:
<ndl_statement>
<action_chain>
<action_element>
<action>
do ( $"player" , "walk" )
Action with Manner
do($"player", "walk") ~ "carefully"Parse Tree:
<ndl_statement>
<action_chain>
<action_element>
<action>
do ( $"player" , "walk" )
<modifiers>
<manner>
~ "carefully"
Action with Properties
do($"player", "attack") intention="intimidate"Parse Tree:
<ndl_statement>
<action_chain>
<action_element>
<action>
do ( $"player" , "attack" )
<modifiers>
<properties>
<property>
intention = "intimidate"
Chained Actions
do($"player", "attack") -> roll("hit") -> result("success")Parse Tree:
<ndl_statement>
<action_chain>
<action_element>
<action>
do ( $"player" , "attack" )
-> <action_element>
<action>
roll ( "hit" )
-> <action_element>
<action>
result ( "success" )
Complete Complex Example
do($"you", "swing makeshift club against table's surface", intention="test club's combat readiness")
-> result("failure")
-> system_response("something goes wrong when you try to perform this action")
-> describe()Parse Tree:
<ndl_statement>
<action_chain>
<action_element>
<action>
do ( $"you" , "swing makeshift club against table's surface" )
<modifiers>
<properties>
<property>
intention = "test club's combat readiness"
-> <action_element>
<action>
result ( "failure" )
-> <action_element>
<meta_statement>
system_response ( "something goes wrong when you try to perform this action" )
-> <action_element>
<action>
describe ( )
Syntactic Constraints
1. Entity Reference Placement
Entity references ($) can appear:
- As first parameter to
do()action - In
target()action - Not in manner modifiers or property values (string literals only)
2. Manner Modifier Position
~ operator must immediately follow an action element:
✓ do($"player", "walk") ~ "carefully"
✗ ~ "carefully" do($"player", "walk")3. Property Position
Properties can appear:
- After actions
- After manner modifiers
- Not standalone
4. Sequence Operator Rules
-> connects complete action elements:
✓ action1 -> action2
✗ action1 -> -> action2 # No empty elements
✗ -> action1 # Must have left operandSyntactic Ambiguities
1. String Content
Strings can contain any character, including operators:
do($"player", "move -> next room") # -> inside string is literal2. Property Names
Property names can be:
- Reserved keywords (
intention,perspective) - Custom identifiers (user-defined)
Context determines interpretation:
intention="test" # 'intention' is property name
"intention" # 'intention' is string valueWhitespace Rules
Whitespace is not significant except:
- To separate tokens
- Within string literals (preserved)
Equivalent statements:
do($"player", "attack") -> result("success")
do($"player","attack")->result("success")
do ( $"player" , "attack" ) -> result ( "success" )Comment Syntax
Comments are not explicitly defined in the transcripts. If implemented:
# This could be a comment
do($"player", "attack") # End-of-line commentGrammar Extensions
Observed But Not Fully Specified
- Duration Literals:
wait(1s),wait(500ms) - Numeric Parameters:
damage(8) - Multiple Property Syntax: Not fully clear if comma-separated or repeated
Future Expansion
As veritasr noted, NDL vocabulary is growing:
- 43+ social actions
- 36 physical actions
- 35 mental actions
Grammar is extensible to accommodate new action types without structural changes.
Validation Rules
A valid NDL statement must:
- Start with an action, control, or meta statement
- Use
->only to connect complete action elements - Apply
~only to actions (not control/meta statements) - Use proper entity reference syntax (
$"name") - Enclose all string values in double quotes
Error Cases
Syntax Errors
❌ do() # Missing parameters
❌ do($"player") # Incomplete parameters
❌ do($"player", "walk" -> action2) # -> inside parameter
❌ ~ "carefully" # Manner without action
❌ intention="test" # Property without actionSemantic Errors (Valid Syntax, Invalid Meaning)
⚠️ wait("player") # Waiting for entity (not condition)
⚠️ do($"nonexistent", "act") # Unknown entity
⚠️ roll("invalid_stat") # Invalid stat name