diff --git a/Cargo.lock b/Cargo.lock index d667956..5b807eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,194 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "proc-macro2" +version = "1.0.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3e4daa0dcf6feba26f985457cdf104d4b4256fc5a09547140f3631bb076b19a" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "rstest" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" +dependencies = [ + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" +dependencies = [ + "cfg-if", + "glob", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + [[package]] name = "vijin" version = "0.1.0" +dependencies = [ + "rstest", + "serde", + "serde_json", +] diff --git a/Cargo.toml b/Cargo.toml index bd6f95c..3137e36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,3 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] +serde = { version = "1.0.210", features = ["derive"] } +serde_json = "1.0.128" + +[dev-dependencies] +rstest = { version = "0.23.0", default-features = false } diff --git a/src/directive-predeclared.json b/src/directive-predeclared.json new file mode 100644 index 0000000..364de44 --- /dev/null +++ b/src/directive-predeclared.json @@ -0,0 +1,119 @@ +{ + "types": [ + { + "name": "text", + "doc": "Arbitrary text.", + "kind": "text" + }, + { + "name": "speech", + "doc": "Formatted speech text with emphasis, shout, and whisper markers.", + "kind": "speech" + }, + { + "name": "character", + "doc": "Name of a character in the current scene.", + "kind": "character" + }, + { + "name": "duration", + "doc": "Time duration.", + "kind": "duration" + }, + { + "name": "scene", + "doc": "Scene asset.", + "kind": "asset", + "tags": [ + "scene" + ] + }, + { + "name": "background", + "doc": "Background image or environment model.", + "kind": "asset", + "tags": [ + "background" + ] + }, + { + "name": "stage position", + "doc": "Default positions on the stage.\n- close: front and center, much zoomed in.\n- left third, right third: rule of thirds, slightly zoomed in.\n- left, center, right: middle distance, dividing the horizontal space into four.\n- far left, mid left, mid right, far right: middle distance, dividing the horizontal space into five.\n- far: center, zoomed out.", + "kind": "enum", + "enum": [ + "close", + "left third", + "right third", + "left", + "center", + "right", + "far left", + "mid left", + "mid right", + "far right", + "far" + ] + } + ], + "directives": [ + { + "name": "page", + "doc": "Prepare a new page, resetting static text, speaker, &c.\nNormally not used directly; script speech lines call this directive implicitly.", + "prefix": "page" + }, + { + "name": "set static text", + "doc": "Set the current page's text.\nNormally not used directly; script speech lines call this directive implicitly.", + "prefix": "set static text", + "prefix_arg": "speech" + }, + { + "name": "set static speaker", + "doc": "Set the current page's speaker.\nNormally not used directly; script speech lines call this directive implicitly.", + "prefix": "set static speaker", + "prefix_arg": "character" + }, + { + "name": "characters", + "doc": "Set the names of characters in the current scene.", + "prefix": "characters", + "list_arg": "text" + }, + { + "name": "scene", + "doc": "Mark the beginning of a scene.", + "prefix": "scene" + }, + { + "name": "background", + "doc": "Set the background image.", + "prefix": "background", + "prefix_arg": "background" + }, + { + "name": "enter _ stage _", + "doc": "Bring a character onto the stage at a given position.", + "prefix": "enter", + "prefix_arg": "character", + "infix": "stage", + "infix_arg": "stage position" + }, + { + "name": "enter _", + "doc": "Bring a character onto the stage at a default position.", + "prefix": "enter", + "prefix_arg": "character" + }, + { + "name": "exit _", + "doc": "Remove a character from the stage.", + "prefix": "exit", + "prefix_arg": "character" + }, + { + "name": "exeunt", + "doc": "Remove all characters from the stage.", + "prefix": "exeunt" + } + ] +} \ No newline at end of file diff --git a/src/directive.rs b/src/directive.rs new file mode 100644 index 0000000..f240197 --- /dev/null +++ b/src/directive.rs @@ -0,0 +1,81 @@ +/// The definition of a standard directive. +/// +/// Note that this type is an input to the parser, not an output. +pub struct Directive { + /// The provider's name for the directive. + name: String, + /// Description of the directive. + doc: String, + /// Fixed prefix term. + prefix: String, + /// The type of the prefix argument, if there is one. + prefix_arg: Option, + /// Fixed infix term. + /// Can only be present if the prefix argument exists. + infix: Option, + /// The type of the infix argument. + /// Can only be present if the infix term exists. + infix_arg: Option, + /// Fixed suffix term. + /// Can only be present if the infix argument exists. + /// Note that this implies directives which have two terms have a prefix + /// and an infix, not a prefix and a suffix. + suffix: Option, + /// The type of the suffix argument. + /// Can only be present if the suffix exists. + suffix_arg: Option, + /// The type of the elements of the list argument, if supported. + list_arg: Option, + // TODO(zeph): macro expansion? +} + +/// Directive parameter type. +pub enum Type { + Named { + name: String, + doc: String, + underlying: Param, + }, + Literal(Param), +} + +impl Type { + pub fn underlying(&self) -> &Param { + match self { + Self::Named { + underlying, + name: _, + doc: _, + } => underlying, + Self::Literal(underlying) => underlying, + } + } +} + +/// Types expected by directive arguments. +pub enum Param { + /// Arbitrary text. + Text, + /// Speech text, possibly containing emphasis, shout, or whisper markers. + Speech, + /// Character in the current scene. + Character, + /// Duration. + Duration, + /// Asset requiring particular tags. + Asset { tags: Vec }, + /// Enumeration of literal options. + Enum(Vec), +} + +#[cfg(test)] +mod tests { + use super::*; + use rstest::rstest; + + const DIRECTIVE_JSON: &str = r#"{ + "name": "kessoku", + "prefix": "bocchi", + "prefix_arg": + }"#; +} diff --git a/src/main.rs b/src/main.rs index e7a11a9..66c7228 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +mod directive; + fn main() { println!("Hello, world!"); }