pdx_syntax/
script.rs

1//! # Syntax of paradox script
2//!
3//! Offenly paradox scripts are written in `.txt` format. The syntax is highly similar to JSON,
4//! however, with slight differences. Some main differences are:
5//! - `=` is used instead of `:` to separate keys and values.
6//! - There exist some other kinds of separators, including `?=` and `<=` (operators).
7//! - `,` is not used to separate key-value pairs.
8//! - Single value without key is allowed.
9//! - Keys and values are usually not enclosed in `""`, except for some special cases like 
10//! specifying file paths.
11//!
12//! Nevertheless, it is still very similar to JSON. We can define a simple syntax
13//! to parse the paradox scripts.
14//!
15use serde::{Deserialize, Serialize};
16
17use lalrpop_util::lalrpop_mod;
18lalrpop_mod!(script_syn);
19
20/// A script is a list of units.
21#[derive(Serialize, Deserialize, Debug)]
22pub struct Units(Vec<Unit>);
23
24impl core::ops::Deref for Units {
25    type Target = Vec<Unit>;
26    fn deref(&self) -> &Self::Target {
27        &self.0
28    }
29}
30
31impl core::ops::DerefMut for Units {
32    fn deref_mut(&mut self) -> &mut Self::Target {
33        &mut self.0
34    }
35}
36
37/// Unit. May be:
38/// - a key-value pair: `key = value`;
39/// - a single value: `value`;
40/// - a questioned value: `key ?= value`;
41/// - a relation: `key > value`, `key < value`, `key >= value`, `key <= value`, `key == value`.
42#[derive(Serialize, Deserialize)]
43pub enum Unit {
44    KeyValue(Key, Value),
45    SingleValue(Value),
46    Questioned(Key, Value),
47    Relation(Key, String, Value),
48}
49
50/// Entry. Can be:
51/// - an identifier: we define a name that is not enclosed in quotes is an identifier;
52/// - a raw string: a string enclosed in quotes.
53/// 
54/// Entries can appear in keys and values. Parsing the exact and specific meaning of an entry
55/// is not the job of the parser, for Paradox uses the script almost everywhere, and the 
56/// meaning of an entry depends on the context.
57#[derive(Serialize, Deserialize, Debug)]
58pub enum Entry {
59    Ident(String),
60    RawStr(String),
61}
62
63/// Key. An entry.
64#[derive(Serialize, Deserialize)]
65pub struct Key(Entry);
66
67impl core::ops::Deref for Key {
68    type Target = Entry;
69    fn deref(&self) -> &Self::Target {
70        &self.0
71    }
72}
73
74impl core::ops::DerefMut for Key {
75    fn deref_mut(&mut self) -> &mut Self::Target {
76        &mut self.0
77    }
78}
79
80/// Value. Can be:
81/// - empty: `{}`;
82/// - primitive: a single entry;
83/// - recursive: `{ <units> }`.
84#[derive(Serialize, Deserialize)]
85pub enum Value {
86    Empty,
87    Primitive(Entry),
88    Units(Box<Units>),
89}
90
91super::fn_parse_file!(Units, script_syn::UnitsParser);
92
93pub mod types {
94    //! Expose the types ([`Key`], [`Unit`], [`Value`], [`Entry`]) to the outside.
95    //! For convenience.
96    //!
97    pub use super::{Entry, Key, Unit, Units, Value};
98}
99
100/* ------------------------- impl Debug ------------------------- */
101
102impl core::fmt::Debug for Value {
103    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
104        match self {
105            Value::Empty => write!(f, "{{}}"),
106            Value::Primitive(v) => write!(f, "{:?}", v),
107            Value::Units(v) => write!(f, "{:#?}", v),
108        }
109    }
110}
111
112impl core::fmt::Debug for Unit {
113    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
114        match self {
115            Unit::KeyValue(k, v) => write!(f, "{:?} = {:?}", k.0, v),
116            Unit::SingleValue(v) => write!(f, "{:?}", v),
117            Unit::Questioned(k, v) => write!(f, "{:?} ?= {:?}", k.0, v),
118            Unit::Relation(k, r, v) => write!(f, "{:?} {} {:?}", k.0, r, v),
119        }
120    }
121}
122
123/* ------------------------ impl Display ------------------------ */
124// [`Display`] is used to dump the AST back to files.
125
126impl core::fmt::Display for Units {
127    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
128        self.recursive_write(f, 0)
129    }
130}
131
132impl Units {
133    pub fn recursive_write(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
134        for unit in &self.0 {
135            unit.recursive_write(f, level)?;
136            writeln!(f)?;
137        }
138        Ok(())
139    }
140}
141
142impl Unit {
143    fn recursive_write(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
144        write!(f, "{}", "    ".repeat(level))?;
145        match self {
146            Unit::KeyValue(k, v) => {
147                write!(f, "{} = ", k.0)?;
148                v.recursive_write(f, level + 1)
149            }
150            Unit::SingleValue(v) => v.recursive_write(f, level + 1),
151            Unit::Questioned(k, v) => {
152                write!(f, "{} ?= ", k.0)?;
153                v.recursive_write(f, level + 1)
154            }
155            Unit::Relation(k, r, v) => {
156                write!(f, "{} {} ", k.0, r)?;
157                v.recursive_write(f, level + 1)
158            }
159        }
160    }
161}
162
163impl Value {
164    fn recursive_write(&self, f: &mut std::fmt::Formatter<'_>, level: usize) -> std::fmt::Result {
165        match self {
166            Value::Empty => write!(f, "{{}}"),
167            Value::Primitive(v) => write!(f, "{}", v),
168            Value::Units(v) => {
169                writeln!(f, "{{")?;
170                v.recursive_write(f, level + 1)?;
171                write!(f, "{}}}", "    ".repeat(level.saturating_sub(1)))
172            }
173        }
174    }
175}
176
177impl core::fmt::Display for Entry {
178    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
179        match &self {
180            Entry::Ident(s) | Entry::RawStr(s) => write!(f, "{}", s),
181        }
182    }
183}