GrammarWML
From The Battle for Wesnoth Wiki
Revision as of 22:49, 10 August 2016 by Celtic Minstrel (talk | contribs) (Rough draft of WML grammar)
This page contains a formal grammar of the WML data language and preprocessor. It does not attempt to capture any of the ways that the Wesnoth engine may interpret a string, such as WML variable substitution. It also doesn't fully capture the potential consequences of macros, for example the use of unbalanced WML tags. The syntax used is regular-expression-like, with the following conventions:
- Literal values are enclosed in either 'single quotes' or "double quotes".
- Square brackets enclose character classes, with initial ^ inverting them
- Whitespace within an expression (unless quoted) is used only for readability or to separate non-terminals
- The meta-characters * + ? | have the same meaning as is typical in regular expressions
- The sequence <tab> represents a tab character, and <nl> represents an end-of-line character or character sequence
- Multiple definitions of a non-terminal are equivalent to alternation (ie, x:=4 and x:=7 combine to produce x:=4|7)
ws := ' ' | <tab> ws_eol := whitespace* comment? <nl> id := [a-zA-Z0-9_]+ wml_document := (preprocessor_statement | wml_attribute | wml_tag | macro_inclusion | ws* ws_eol)*
wml_attribute := ws* wml_key_sequence ws* '=' ws* wml_attribute_value ws_eol wml_key_sequence := id (ws* ',' ws* id)* wml_attribute_value := (text | ('_' ws*)? string) (ws* '+' ws_eol wml_attribute_value) text := ([^ <tab>+"]+ ws*)* string := '"' ([^"] | '""')* '"'
wml_tag := ws* '[' '+'? id ']' ws_eol wml_document ws* '[' '/' id ']' comment := '#' [^<nl>]* <nl>
preprocessor_statement := macro_definition | ifdef_block | ifhave_block | ifver_block | line_preproc line_preproc := '#undef' ws+ [^ <tab>]+ ws_eol | '#' ('warning' | 'error') ws+ [^<nl>]* ws_eol macro_definition := '#define' (ws+ [^ <tab>]+)+ ws_eol anything '#enddef' ifdef_block := '#ifdef' ws+ [^ <tab>]+ ws_eol anything ws_eol else_block? '#endif' ifhave_block := '#ifhave' ws+ [^<nl>]+ ws_eol anything ws_eol else_block? '#endif' ifver_block := '#ifver' ws+ comparison_expr ws_eol anything ws_eol else_block? '#endif' else_block := '#else' ws_eol anything
macro_inclusion := '{' anything '}'