From a7f5762fa82e041549d91cd79335aabcb61001b0 Mon Sep 17 00:00:00 2001 From: Jon Manning Date: Thu, 10 Dec 2020 14:37:45 +1100 Subject: [PATCH 01/39] Add Yarn Spec Originally written by @McJones, and copied from his Gist here: https://gist.github.com/McJones/d9a9570cd4dcbb23746c23903d8bfe59 --- Documentation/Yarn-Spec.md | 636 +++++++++++++++++++++++++++++++++++++ 1 file changed, 636 insertions(+) create mode 100644 Documentation/Yarn-Spec.md diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md new file mode 100644 index 000000000..7924e1847 --- /dev/null +++ b/Documentation/Yarn-Spec.md @@ -0,0 +1,636 @@ +# Yarn Spec + +This document describes the specification of the Yarn Script format version 2 and guidance and rules for implementing programs who wish to process Yarn scripts. + +## Introduction + +Yarn is a language for representing branching and linear interactive fiction in games. +Yarn was created for the game Night in the Woods and was inspired by the Twine language. +Its focus is on flexibility and writer ease, the goal of the language is to have clear syntax when necessary but to otherwise be as close to just writing text as possible. +For writers there should be minimal friction in creating the language and for programmers minimal annoyance when interfacing with it. + +During development of Night in the Woods Yarn Spinner was created as an open source side project and had no affiliation to Night in the Woods at the time. +Yarn Spinner could read and understand Yarn files but had several advantages over the Yarn interpreter in Night in the Woods so the decision was made to use Yarn Spinner for the game. +This made Yarn Spinner the de facto Yarn interpreter and had the side effect of giving it control over the specification of the language. +Yarn essentially became and was always defined in terms of what Yarn Spinner could understand. + +As Night in the Woods was developed additional features and work was done on Yarn Spinner for the game the set of features and syntax exploded and became difficult to understand or reimplement. +Post Night in the Woods Yarn Spinner continued as its own thing with version 0.9 being released which was mostly a polish of the version used in Night in the Woods. +Later version 1.0 of Yarn Spinner, and as such the language, came out with improved syntax and was the first significant release that wasn't tied to Night in the Woods +Neither Yarn Spinner 0.9 or 1.0 however came with complete specifications of the Yarn language and had a great deal of legacy elements. + +A concerted effort was made to clean up the Yarn language in 2020 for Yarn Spinner 2.0 into something hopefully more understandable but also more flexible. +A component of this is the creation of this specification guide so implementations beyond Yarn Spinner can have something to base decisions on that isn't "do what Yarn Spinner does". + +Despite this being the first version of the Yarn language to ever exist it is version 2 of the Yarn language. +This is because despite Yarn and Yarn Spinner being separate elements attempting to not stay, at least initially, in version lock with the de facto implementation is just asking for trouble, hence version 2 of Yarn. + +### Coverage + +This document covers the elements of a Yarn script that are required to be considered a valid yarn script as well as the rules necessary for an implementing program to be able to conform to this spec. + +An *implementing program* is a program that accepts yarn files as inputs and understands them based on the rules in this document. +This document does not cover how a yarn file is to be transformed or handled internally by an implementing program. + +This document does note when behaviours are *unspecified*. +The implementing program may choose how to handle any unspecified behaviour, often unspecified behaviours have no good solution and should result in an error to the user. +An example of unspecified behaviour are required tags on Nodes. +Only the `Title` tag is required, an implementation may choose to make other tags required or banned. + +### Assumptions + +There is one large assumption in this document and about the language itself. +That is it that it is intended to be embedded into a larger game project. + +As such details like how lines are views, how selections are made, how directions get used, or how functions are handled are all assumed to be passed off onto the larger game to handle. +This is not technically necessary but does explain what would otherwise be gaps in the language. +If your project does not have a game to offload certain tasks to these elements will have to be handled by the implementing program itself. + +### Reading This Specification + +`monofont` terms are to be taken as literals. +As an example the `Title` tag would be written as a string literal `"Title"` in C#. + +*italics* terms are terms which are reused throughout the document. +They are presented in italics the first time they are defined. + +_Must_ is a hard requirement. +_Should_ is a recommendation, albeit a strong one. + +Dates, spelling, and numbers are to be in Australian English. + +### Modifying This Specification + +Once this specification is complete it is set and unchanging. +Modifications beyond clarifications won't be allowed. +To make changes to the language specification a new version of the language will need to be created. + +This is to ensure implementing programs can conform to a language version and not have to worry about it changing after the fact. + +## File Format + +Yarn files must be a UTF-8 text file without BOM set. +File extension should be `.yarn`. + +### Lines + +The *line* is the common unit that comprises all elements in a yarn file. +A line is a series of characters terminated by the *new line* symbol. +The new line symbol should be the `\n` character. +The new line must be the same throughout the project. + +The following Yarn file contains four lines (in order); one header tag line, one header delimiter line, one body dialogue line, one body delimiter line. +```yarn +Title:Start +--- +This is some text +=== +``` + +### Whitespace + +*Whitespace* is any non-visible character with a width greater than 0. +Common whitespace encountered include the space and the tab. + +### Project + +The yarn *project* is all yarn files that are intended to be associated with one another. +While there is nothing stopping a writer from placing all nodes into one big file (or even making one giant node) it is common to break them up over multiple files. +The project is all of these files collected and processed by the implementing program together. + +### Comments + +A comment is a line that starts with the `\\` symbol. +All text from the start of the comment to the end of the line must be ignored. +A comment starting in the middle of another line ends that line at the point the `\\` symbol is encountered. +That line is assumed to have finished at that point as if the comment was not there. +Comments must not impact the rest of the lines or have any impact on the resulting yarn program. + +## Yarn Structure + +A Yarn script file is yarn file that contains one or more nodes and zero or more file tags. + +### File Tags + +_File tags_ are file level metadata that is relevant for all nodes in the file. +A common use for file tags is for versioning the file. +File tags must go at the start of a file before any nodes begin. +File tags must have the `#` symbol at the start of them but are syntactically identical otherwise to the Header Tags of nodes. + +### Nodes + +A *node* is the single story element of a yarn file. +Nodes are the story structural building blocks for yarn. +Nodes are designed to contain pieces of a story and then have these story pieces linked together. +This is not a requirement, everything could be done in a single node, this would just be unwieldy. +A node must be comprised of a single header and a single body in that order. + +### Headers + +A header is comprised of one or more header tags. +The header is finished when encountering a line that only contains the *header delimiter* `---`. +After encountering the header delimiter the body of the node is entered. + +#### Header Tags + +A *header tag* is a line broken up into three components, in order; the tag name, the separator, and the tag text. +The *tag name* can be any combination of the characters `A` - `Z`, `a` - `z`, `0` - `9`. +The *tag separator* is the character `:`. +The *tag text* can be any combination of the characters `A` - `Z`, `a` - `z`, `0` - `9`. +Header tags are commonly used as node specific metadata but using them in this manner is not required. + +The amount of allowed whitespace between the tag name, the seperator, and the tag text is unspecified. +An example of a header tag is the title tag: `Title:start`. + +Every node must have a title tag. +Required or banned header tags beyond title are unspecified. +The order of header tags is unspecified. + +#### Title Tag + +The *title tag* is a specific header tag that uniquely identifies the node. +The tag name for the title tag must be `Title`. +The tag text for the title tag must be unique within the file. +The tag text for the title tag should be unique within the project. + +The behaviour of the program when a title tag's text is not unique across the project is unspecified. +The program could either flag this as an error and abort, choose which node will be the canonical one with that title, or some other form of name conflict resolution. + +### Body + +A body is comprised of multiple statements. +A *statement* is a line that is one of the following: + +- dialogue +- commands +- options + +A statement may have optional hashtags. +A body must have at least one statement. + +The body ends when encountering a line that contains the *body delimter* `===`. +The body delimiter ends both the current node and the body of that node. +The end of file must not be used in place of a body delimiter. + +#### Hashtags + +*Hashtags* are metadata associated with the statement they are a part of. +Hashtags must go at the end of the statement. +The other components of the statement must end at the hashtag, the hashtag operates effectively as the newline terminator for the statement. + +A hashtag starts with the `#` symbol and contain any text up to the newline or another hashtag. +`#lineID:a10be2` is an example of a hashtag. +Multiple hashtags must be separated by the `,` symbol. +`#lineID:a10be2, #return` is an example of multiple hashtags on a line. + +### Dialogue Statement + +A dialogue statement is a statement that represents a single line of text in the yarn story. +In most cases dialogue will be the bulk of the content of a node's body. +Dialogue lines can be interpolated dialogue or raw dialogue. + +An *interpolated dialogue* is one where there are in-line expressions in the line. +Expressions are encapsulated within the `{` and `}` symbols and it is the presence of these symbols that determine if a line is an interpolated one or not. +The expression inside the `{}` symbols must be a valid expression. +The result of the expression must be inserted into the dialogue. +Other than replacing expressions dialogue statments must not be modified by the implementing program, and provided to the game as written. + +A *raw dialogue* is a dialogue statement where there are no expressions. + +A dialogue statement can contain any characters except for the `#` character. + +`{$name}, you are a bold one.` is an example of an interpolated dialogue. +`General Kenobi, you are a bold one.` is an example of a raw dialogue. + +When resolving ambiguity of statements inside the body the dialogue statement must be considered the lowest priority by the implementing program. +For example `<>` could be read as a command or a dialogue statement, it is to be considered a command by the program. + +#### White space + +It is normal for dialogue to have leading or trailing white space. +The handling or trimming of trailing white space in dialogue is unspecified. +The handling or trimming of leading white space in dialogue is unspecified except in the case of options where it must obey the rules for options. + +### Commands + +Commands are special statements that have no specific output to be shown but are used for passing messages and directions to other parts of the program and to control the flow of the story. + +The possible types of commands are: + +- flow control +- jump +- directions +- stop +- set + +All commands must start with the `<<` symbol and end with the `>>` symbol. +Additional required command are unspecified. + +#### Directions + +_Directions_ are commands for sending messages from the yarn to the rest of the program. +Implementing programs must not modify the flow of the yarn based on the direction. + +Directions can have any text except for the `#`, `{`, or `}` symbols inside of them. + +Directions can also have expressions inside of them, however as with dialogue these must be encapsulated by using the `{` and `}` symbols. +Any expressions inside of a directions command without being encapsulated must be ignored and treated instead as regular text. + +```yarn +<> +<> +<> +``` +are examples of directions. + +#### Jump + +The _jump_ command is how a yarn program can move from one node to another. +The jump has two components: the keyword and destination. +The _keyword_ is the text `jump` and comes first in the command. + +The _destination_ is the name of the node to load. +The destination may be any text but must map to the `Title` of a node somewhere else in the project. +The destination text may be created using the result of an expression, however this must be wrapped inside `{` `}` symbols. +The expression must resolve to a string value and must be a string that matches the structure of node names. + +The behaviour of an implementing program is unspecified when asked to jump to a destination that doesn't match a title in the project. + +Once the jump command has been completed the current node must no longer be used, this means any dialogue, options or commands below the jump are to be ignored. +From that point on the destination nodes contents must instead be run. + +`<>` is an example of a jump command, `<>` is an example of a jump command using an expression to determine the destination node. + +#### Stop + +The _stop_ command is for halting all progress on the story. +Once the stop command is reached all processing on the project must halt, no additional nodes are to be loaded and run, no additional dialogue or commands are to processed. +The stop command has only one component, the _keyword_ `stop`. +The stop command should reset any variable or internal state back to their initial states. + +`<>` is the example of the stop command. + +#### Set + +The _set_ command allows variables to be given values. +The set command has four components: the keyword, the variable, the operator and the value and must be presented in that order. + +The _keyword_ is the text `set`. +The _variable_ is the name of the variable which is to have its value changed. +The _operator_ must be the text `to`. +The _expression_ is any expression. + +The following is an example of two set commands: +```yarn +<> +<> +``` + +The set command must follow all the rules for variable naming and expressions. +The set command must not allow setting a variable to an expression who's value is different from the type of that variable. + +### Flow control + +Flow control is a collection of commands that allow the writer to control the flow of the story. +There are four commands which work in conjunction to support flow control: + +- if +- else +- elseif +- endif + +The order of these commands is always the same and must be followed: + +1. if +1. elseif +1. else +1. endif + +The if and endif must be present, the elseif and else must be optional. +While each of these commands are their own statement they should be considered to be part of a larger flow control statement which spans multiple lines. + +#### if + +The _if_ command is the opening command of flow control and is broken up into two parts, the keyword and the expression and must be in that order. +The _keyword_ is the text `if`. +The _expression_ is an expression. +The expression must resolve to a boolean. + +`< 1>>` is an example of an if command, `<>` is an example of an invalid if, it is invalid because the expression does not resolve to a boolean. + +#### elseif + +The _elseif_ command is an optional component of flow control and allows for additional flow to be expressed. +The command works in a fashion very similar to the if command. +The command is broken up into two parts, the keyword and the expression and must be presented in that order. +The _keyword_ is the text `elseif`. +The _expression_ is an expression. +The expression must resolve to a boolean. + +The minimum mumber of required elseif commands must be zero. +The maximum number of allowed elseif commands is unspecified but should be greater than zero. +An elseif command must not exist without an if command and must go after the if command. + +#### else + +The _else_ command is an optional component of flow control and allows for additional flow to be expressed. +The command only has a single component, the keyword `else`. + +There must only be a single else command (if any) per flow control. +The else command must go after the if and any elseif commands. +The else must not exist without an if command. + +The example of the else command is `<>`. + +#### endif + +The _endif_ command is the final element of flow control and is comprised solely of the keyword `endif`. +The endif must be present whenever there is flow control and must go after the if and any elseif or else commands. +The endif exists to allow the implementing program know when the scope of the other elements in the flow control has ended. +`<>` is the example of the endif command. + +#### Scope and Blocks + +For the flow control to be useful there needs to be yarn statements which are run only when their appropriate expression evaluates to true. +Flow control allows for blocks of statements to be scoped to their commands. +A _block_ is a collection of statements that are scoped to a particular part of the flow control. + +The _scope_ of a block is determined by the flow control commands and associates each block with a command. +The if, elseif, and else commands all have a block associated with them. +The block of statements for a command start from the first statement after the command up until the next command in the flow control. +When dealing with nested flow control the deepest set of flow control commands are to be the ones that can first assume another command closes their scope. + +While it is common for writers to indent their blocks relative to their scope it must not be used by the implementing program to determine scope. + +#### Handling + +The implementing program must process all statements within the active blocks scope. +The _active block_ is the block of yarn who's command expression evaluates to `true`. +The block associated with the else command, if present, must only be determined as the active block if all other blocks expressions evaluate to false. + +An implementing program must not process any statements inside a block that is not the active block. +An implementing program must only have, at most, one active block. +If no blocks expression evaluates to true then no block must be processed. + +#### Ambiguity + +Because the flow control commands allow for potentially multiple commands and their blocks to be the true one, the implementing program must select them in a top down approach when there is conflicting flow. +For example take the following flow control: + +```yarn +<> + if-scope +<> + elseif-1-scope +<> + elseif-2-scope +<> + else-scope +<> +``` + +Both of the elseif commands expressions evaluate to true, so either ones attached block could be run and seen to be correct. +However because one is above the other the block with `elseif-1-scope` dialogue inside would be the selected one. +The implementing program should attempt to identify these scenarios however and alert the writer. + +### Options + +_Options_ are the means by which Yarn can present dialogue choices to the game and much as with flow control are an element that spans multiple lines. +Options are comprised of one or more option lines. +An _option line_ represents a single choice in an option, and are comprised of three parts: the keyword, the dialogue, the conditional in that order. + +The _keyword_ is how the implementing program can tell a line is part of an option instead of dialogue and is the symbols `->`. +There must be at least one whitespace between the keyword and the next element, the dialogue. +The _dialogue_ is a normal line of dialogue following all rules associated with that. + +The _conditional_ is a command which controls the specifics of the validity of the option. +The conditional allows for additional data about the option to be bundled along with the line. +The intent of the conditional is for the game to know which lines are currently valid for selection and which are not without forcing the writer to duplicate options inside of a control flow. +The conditional's syntax is identical to the if command and follows all rules there, but as it is not part of flow control must not have an accompanying endif or attached block. +The conditional must be an optional component of the option line. + +As the intention of options is to provide choice when options are encountered the implementing program must halt further progress through the node until an option has been selected. +Each option must be provided in the order they are written in the node. +The mechanism by which an option line is chosen is unspecified. +Only a single option line must be chosen. + +As the conditional controls the validity of the option for selection this information must be provided by implementing program to the parts of the game that makes the selections. +The implementing program must not restrict the selection of invalid options. +It is the responsibility of the other components of the game to control how invalid options are to be handled. + +#### Blocks + +Much like with flow control options may have blocks of statements which are triggered should that option line be chosen. +Each option line may optionally have a block of statements associated with that option line. +Similar again to the flow control, if an option line is selected its associated block of must be processed by the implementing program +If an option isn't chosen the associated block must not be processed. + +Unlike the flow control however there is no clear way to tell apart different blocks and options from other parts of the yarn, instead indentation is used to determine blocks and the end of the options. +The rules for this must be followed: + +The first option line in the options determines the base indentation for the options statement, this is determined by counting the number of whitespace elements before the `->` symbol. +Any statements following the option line at a greater level of indentation counts as part of the block for that option line. +Any other options lines with the same indentation is considered a new option line and closes the block for that option. + +These rules are repeated for each option line until a non-option line with the same, or less indentation than the base indentation is encountered which closes the block and the option statement entirely. + +Options can be nested inside options. +Not every option line needs to have blocks. + +##### Tabs vs Space + +The choice to require either tabs or spaces over the other is unspecified. +Tabs and spaces shouldn't be mixed. +Should there be a need to convert between them the conversion rate must be the same at all points in the project. +The rate of conversion between tabs to spaces, and spaces to tabs, is unspecified. +If there is a need to choose one, tabs should be preferred due to their improved accessibility over spaces. + +## Expressions + +_Expressions_ are mathematical chains of variables, values, functions, expressions, and operators that produce a single value as output. + +Expressions are not a statement but are a component of various statements and must only be used as part of a statement, they cannot exist in isolation. +This means if you do want to show the result of an expression it will have to be wrapped inside an interpolated line. +For example a line that is just `$numberOfCoins + 1` is invalid, but `{$numberOfCoins + 1}` is valid. + +Expressions are mostly used to control the flow of the if statement. + +### Values + +A _Value_ is a single concrete form of one of the supported types. +All expressions, subexpressions, variables and functions, must resolve down into a value before it can be used. +Examples of values include `1`, `true`, `"General Kenobi"`. + +### Types + +Yarn supports the following types and these must be supported by an implementing program: + +- number +- boolean +- string + +The precision, storage, and form of the number internally is unspecified, however it must support decimals. +As an example of this in C# the `Decimal`, `Complex`, and `float` formats are valid (though some make more sense than others) but `int` is not. +Numbers in expressions can be written as either integers or as decimals, but decimal numbers must use the `.` symbol as the decimal seperator of the the number. + +Strings must be capable of holding utf-8 values as this is what the yarn language is written in, but the internals of this is unspecified provided all valid utf-8 characters are supported. +Strings in expressions must be encapsulated between `"` and `"` symbols. + +Booleans must be capable of representing the boolean logic values of `true` and `false`, however the specific implementation is undefined. +Booleans must not be exposed as `1` and `0` to expressions even if they are represented this way internally by the implementing program. +Booleans in expressions must be written as `true` for true and `false` for false. + +Additional types supported are unspecified. + +### Variables + +_Variables_ are a means of associating a value with a name so that it can be more easily used and changed in multiple places. +Variables can only be used inside of expressions. + +#### Naming and scope + +All variables must start with the `$` symbol followed immediately by any combination of `a`-`z`, `A` - `Z`, and `0-9`. +Arbitrary symbol variable names are allowed by wrapping the symbols after the `$` inside backtick symbols \`. +Any symbols except another backtick are allowed in an arbitrary sybmol variable name. +This is useful to allow writers to create semantic connections between variables. +The minimum and maximum length of a variable name is unspecified. + +Variable names must be unique throughout their scope. +The _scope_ of the variable is what defines for how long a variable exists. +Once a variable leaves its scope it is no longer valid and implementing programs must not support accessing variables outside of their scope. +The scope of variables is undefined, however implementing programs should err on the side of the smallest possible scope for a variable. + +`$name` is an example of a standard variable name, `$`\``character.name`\` is an example of an arbitrary sybmol variable name. + +#### Types + +Variables have a type which represents which of the supported type' values it can hold. +Once a variable has its type determined either by declaration or inference it cannot change. +The implementing program must not allow variables to hold values of types different from its own. + +### Operations + +_Operations_ are mathematical functions that take operands and an operator and result in a new value. +Operations can have one or two operands depending on the specific operation. +_Operators_ are the symbol used to define which operation is being called. +_Operands_ are the elements that used in the operation. +Operands must be a value, a variable, an expression, or a function. +Most operations are binary operations and have two operands, these go either side of the operator, and are called the l-value and r-value for the left and right side respectively. + +The following binary operations and their operator must be supported. +Some of these have multiple operators, these must work identically and exist for people who prefer to use words instead of symbols: + +- addition `+` +- subtraction `-` +- multiplication `*` +- division `\` +- truncating remainder division (modulo) `%` +- equality `==` or `eq` +- inequality `!=` or `neq` +- greater-than `>` or `gt` +- less-than `<` or `lt` +- great-than-or-equal `>=` or `gte` +- less-than-or-equal `<=` or `let` +- boolean OR `||` +- boolean AND `&&` + +The amount of whitespace between operands and operators in binary operations is unspecified. + +There are two unary operations that have only a single operand. +The operator always goes to the left side of the operand and the must be no whitespace between the operator and operand. +The unary operations are: + +- minus `-` +- boolean NOT `!` + +Parentheses are a special form of operation. +They are for bundling up elements of an expression into a subexpression. +Parentheses must be treated as if they are a single operand in other operations. +Parentheses start with the open bracket symbol `(` and can have any expression inside of them before being closed with the closing bracket symbol `)`. +`2 * (3 + $coins)` is an example of an expression with a parentheses operation, in this case the `3 + $coins` component must be resolved into a value before being able to be multiplied by two. + +The `+` operator when operating on strings is not addition in the mathematical sense but concatenation. + +#### Supported types in operations + +The following table shows the compatible types for each binary operation and must be supported: + +| | + | - | * | / | % | == | != | gt | lt | gte | lte | \|\| | && | +|----------|---|---|---|---|---|----|----|----|----|-----|-----|------|----| +| numbers | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| strings | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| booleans | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | + +The following table shows the compatible types for each unary operation and must be supported: + +| | ! | - | +|----------|---|---| +| numbers | ❌ | ✅ | +| strings | ❌ | ❌ | +| booleans | ✅ | ❌ | + +Operations between different or incompatible types is unspecified but should not be supported due to the potential confusion. +If however they are supported existing behaviour around transitivity, commutativity, and symmetry of operations should be respected. +For example if `"hello" < 5` is `true` then `5 > "hello"` should also be `true`. +Likewise `("hello" + 2) < 5` resulted in `true` then `(2 + "hello") < 5` should also be `true`. +This taken to the extreme should mean that `1 + "hello" == "hello + 1` should evaluate to `true` which is confusing to most people, hence the recommendation against supporting operations between disparate types. + +#### Operation Output + +The following table shows the expected output type of each operation based on its operand type: + +| | + | - | * | / | % | == | != | gt | lt | gte | lte | \|\| | && | ! | unary minus | +|---------|--------|--------|--------|--------|--------|---------|---------|---------|---------|---------|---------|---------|---------|---------|-------------| +| number | number | number | number | number | number | boolean | boolean | boolean | boolean | boolean | boolean | boolean | boolean | | number | +| string | string | | | | | boolean | boolean | | | | | | | | | +| boolean | | | | | | boolean | boolean | | | | | boolean | boolean | boolean | | + +#### Order of Operations + +The order of operations is as follows: + +1. `()` +1. `!`, `unary minus` +1. `*`, `/`, `%` +1. `-`, `+` +1. `==`, `!=`, `lt`, `gt`, `lte`, `gte` +1. `||`, `&&` + +If there are any equal priority operations in an expression they are resolved left to right as encountered in the expression. + +### Functions + +_Functions_ are an alternate way of getting values into expressions. +Functions are intended to be used to allow more complex code be bundled and called in a different environment, such as in the game itself. +Functions must return a value. + +#### Structure + +Functions are comprised of a name, parentheses, and parameters. + +The _function name_ can be any combination of the characters `a` - `z`, `A` - `Z`, and `0` - `9`, but must not start with a number. +The minimum and maximum length of function names is unspecified. + +The parentheses go after the function name and there must be no whitespace between the opening parentheses `(` and the function name. +The closing parethensis `)` finishes the function. + +_Parameters_ go in between the opening `(` and closing `)` parentheses. +Parameters must be expressions, functions, values, or variables. +Functions can have multiple parameters, these must be separated by the comma `,` symbol. + +Whitespace between parameters and the separator is undefined. hmm this allows for newlines is that ok? +The maximum and minimum number of allowed parameters a function can have is undefined. + +Examples of functions include the following; + +```yarn +getPlayerName() +DetermineCurrentRoom($playerName, $target, 2) +rad2Deg(1.5707963268) +``` + +#### Handling + +The handling of functions by the implementing program is unspecified, however the output type of a function must not change at runtime between calls. +The implementing program should allow external parts of the game to provide the return value of the function. +If given the same input parameters multiple invocations of the same functions should return the same value each time. From 7467347c497a81c974c2ad13934fa852556b4565 Mon Sep 17 00:00:00 2001 From: McJones Date: Mon, 18 Jan 2021 15:34:43 +1100 Subject: [PATCH 02/39] updated spec based on feedback. Options section still needs work --- Documentation/Yarn-Spec.md | 136 ++++++++++++++++++++++++++++--------- 1 file changed, 104 insertions(+), 32 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 7924e1847..82b3f7e5a 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -16,7 +16,7 @@ Yarn essentially became and was always defined in terms of what Yarn Spinner cou As Night in the Woods was developed additional features and work was done on Yarn Spinner for the game the set of features and syntax exploded and became difficult to understand or reimplement. Post Night in the Woods Yarn Spinner continued as its own thing with version 0.9 being released which was mostly a polish of the version used in Night in the Woods. -Later version 1.0 of Yarn Spinner, and as such the language, came out with improved syntax and was the first significant release that wasn't tied to Night in the Woods +Later version 1.0 of Yarn Spinner, and as such the language, came out with improved syntax and was the first significant release that wasn't tied to Night in the Woods. Neither Yarn Spinner 0.9 or 1.0 however came with complete specifications of the Yarn language and had a great deal of legacy elements. A concerted effort was made to clean up the Yarn language in 2020 for Yarn Spinner 2.0 into something hopefully more understandable but also more flexible. @@ -33,7 +33,7 @@ An *implementing program* is a program that accepts yarn files as inputs and und This document does not cover how a yarn file is to be transformed or handled internally by an implementing program. This document does note when behaviours are *unspecified*. -The implementing program may choose how to handle any unspecified behaviour, often unspecified behaviours have no good solution and should result in an error to the user. +The implementing program may choose how to handle any unspecified behaviour, often unspecified behaviours have no good solution and should result in an error. An example of unspecified behaviour are required tags on Nodes. Only the `Title` tag is required, an implementation may choose to make other tags required or banned. @@ -42,7 +42,7 @@ Only the `Title` tag is required, an implementation may choose to make other tag There is one large assumption in this document and about the language itself. That is it that it is intended to be embedded into a larger game project. -As such details like how lines are views, how selections are made, how directions get used, or how functions are handled are all assumed to be passed off onto the larger game to handle. +As such details like how lines are viewed, how selections of options are made, how directions get used, or how functions are handled are all assumed to be passed off onto the larger game to handle. This is not technically necessary but does explain what would otherwise be gaps in the language. If your project does not have a game to offload certain tasks to these elements will have to be handled by the implementing program itself. @@ -57,6 +57,11 @@ They are presented in italics the first time they are defined. _Must_ is a hard requirement. _Should_ is a recommendation, albeit a strong one. +_Errors_ are mentioned multiple times and represent situations that are unrecoverable. +Errors are intended to allow the implementing program to let the user or other parts of the game know that an unrecoverable situation has occured. +The implementing program must abort progress on the Yarn after creating an error. +The precise handling of errors will be specific to the implementing program but should use whatever error mechanisms exist already, for example Yarn Spinner throws normal C# exceptions for its errors. + Dates, spelling, and numbers are to be in Australian English. ### Modifying This Specification @@ -77,9 +82,9 @@ File extension should be `.yarn`. The *line* is the common unit that comprises all elements in a yarn file. A line is a series of characters terminated by the *new line* symbol. The new line symbol should be the `\n` character. -The new line must be the same throughout the project. +The new line must be the same throughout the project regardless of the chosen new line symbol. -The following Yarn file contains four lines (in order); one header tag line, one header delimiter line, one body dialogue line, one body delimiter line. +The following Yarn file contains four lines (in order); one header tag line, one header delimiter lione, one body dialogue line, one body delimiter line. ```yarn Title:Start --- @@ -92,6 +97,8 @@ This is some text *Whitespace* is any non-visible character with a width greater than 0. Common whitespace encountered include the space and the tab. +Whitespace for lines of dialogue plays no role but has significant syntactic important for Options. + ### Project The yarn *project* is all yarn files that are intended to be associated with one another. @@ -100,9 +107,9 @@ The project is all of these files collected and processed by the implementing pr ### Comments -A comment is a line that starts with the `\\` symbol. +A comment is a line that starts with the `//` symbol. All text from the start of the comment to the end of the line must be ignored. -A comment starting in the middle of another line ends that line at the point the `\\` symbol is encountered. +A comment starting in the middle of another line ends that line at the point the `//` symbol is encountered. That line is assumed to have finished at that point as if the comment was not there. Comments must not impact the rest of the lines or have any impact on the resulting yarn program. @@ -127,7 +134,7 @@ A node must be comprised of a single header and a single body in that order. ### Headers -A header is comprised of one or more header tags. +A *header* is comprised of one or more header tags. The header is finished when encountering a line that only contains the *header delimiter* `---`. After encountering the header delimiter the body of the node is entered. @@ -137,7 +144,7 @@ A *header tag* is a line broken up into three components, in order; the tag name The *tag name* can be any combination of the characters `A` - `Z`, `a` - `z`, `0` - `9`. The *tag separator* is the character `:`. The *tag text* can be any combination of the characters `A` - `Z`, `a` - `z`, `0` - `9`. -Header tags are commonly used as node specific metadata but using them in this manner is not required. +Header tags are commonly used as node specific metadata but using them in this manner is not required, beyond the title tag. The amount of allowed whitespace between the tag name, the seperator, and the tag text is unspecified. An example of a header tag is the title tag: `Title:start`. @@ -154,7 +161,7 @@ The tag text for the title tag must be unique within the file. The tag text for the title tag should be unique within the project. The behaviour of the program when a title tag's text is not unique across the project is unspecified. -The program could either flag this as an error and abort, choose which node will be the canonical one with that title, or some other form of name conflict resolution. +The program should flag this as an error. ### Body @@ -182,6 +189,7 @@ A hashtag starts with the `#` symbol and contain any text up to the newline or a `#lineID:a10be2` is an example of a hashtag. Multiple hashtags must be separated by the `,` symbol. `#lineID:a10be2, #return` is an example of multiple hashtags on a line. +`General Kenobi: Why hello there #lineID:a10be2, #return` is an example of a line of dialogue with multiple hashtags. ### Dialogue Statement @@ -203,13 +211,16 @@ A dialogue statement can contain any characters except for the `#` character. `General Kenobi, you are a bold one.` is an example of a raw dialogue. When resolving ambiguity of statements inside the body the dialogue statement must be considered the lowest priority by the implementing program. -For example `<>` could be read as a command or a dialogue statement, it is to be considered a command by the program. +For example `<>` could be read as a command or a dialogue statement, it must be considered a command by the implementing program. -#### White space +#### Escaping Text -It is normal for dialogue to have leading or trailing white space. -The handling or trimming of trailing white space in dialogue is unspecified. -The handling or trimming of leading white space in dialogue is unspecified except in the case of options where it must obey the rules for options. +There are going to be times in dialogue that the writer will need to use symbols that are reserved. +To use reserved symbols in dialogue preface any reserved symbol with the escape symbol `\`, this allows the following symbol to escape being understood as a reserved character. +Any character following the escape must be presented in the dialogue as-is and must not be parsed as a special character. +As an example `\{$name\}, you are a bold one.` would be presented as `{$name}, you are a bold one.` to the game. + +Escaping text must be supported in both normal and interpolated dialogue lines as well as in the dialogue component of options. ### Commands @@ -217,11 +228,12 @@ Commands are special statements that have no specific output to be shown but are The possible types of commands are: -- flow control -- jump - directions +- jump - stop - set +- declare +- flow control All commands must start with the `<<` symbol and end with the `>>` symbol. Additional required command are unspecified. @@ -249,21 +261,22 @@ The _jump_ command is how a yarn program can move from one node to another. The jump has two components: the keyword and destination. The _keyword_ is the text `jump` and comes first in the command. -The _destination_ is the name of the node to load. -The destination may be any text but must map to the `Title` of a node somewhere else in the project. +The _destination_ is the name of the node to move to. +The destination may be any text but must map to the `Title` of a node in the project. The destination text may be created using the result of an expression, however this must be wrapped inside `{` `}` symbols. -The expression must resolve to a string value and must be a string that matches the structure of node names. +The expression must resolve to a string value and must be a string that matches a node title in the project. The behaviour of an implementing program is unspecified when asked to jump to a destination that doesn't match a title in the project. +The implementing program should flag this as an error. -Once the jump command has been completed the current node must no longer be used, this means any dialogue, options or commands below the jump are to be ignored. +Once the jump command has been completed the current node must be exited immediately, this means any dialogue, options or commands below the jump are to be ignored. From that point on the destination nodes contents must instead be run. `<>` is an example of a jump command, `<>` is an example of a jump command using an expression to determine the destination node. #### Stop -The _stop_ command is for halting all progress on the story. +The _stop_ command is for halting all progress on the project. Once the stop command is reached all processing on the project must halt, no additional nodes are to be loaded and run, no additional dialogue or commands are to processed. The stop command has only one component, the _keyword_ `stop`. The stop command should reset any variable or internal state back to their initial states. @@ -278,7 +291,7 @@ The set command has four components: the keyword, the variable, the operator and The _keyword_ is the text `set`. The _variable_ is the name of the variable which is to have its value changed. The _operator_ must be the text `to`. -The _expression_ is any expression. +The _expression_ is any expression, unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. The following is an example of two set commands: ```yarn @@ -287,7 +300,45 @@ The following is an example of two set commands: ``` The set command must follow all the rules for variable naming and expressions. -The set command must not allow setting a variable to an expression who's value is different from the type of that variable. +The set command must not allow setting a variable to an expression whose value is different from the type of that variable. + +#### Declare + +Variables in Yarn should be declared to let the implementing program know the type of values they hold. +The intent of this is to allow the implementing program to set up memory and to provide guidance as to the usage of a variable directly from the writer. +The declare command has four components: the keyword, the variable, the operator and the value, and must be presented in that order. + +The _keyword_ is the text `declare`. +The _variable_ is the name of the variable which is to have its value changed. +The _operator_ must be the text `=`. +The _expression_ is any expression, unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. + +The resulting value of the expression is used determine what type the value has been declared as, so if expression results in a boolean for example then the variable is declared as a boolean. + +The following is an example of two declaration commands: +```yarn +<> +<> +``` + +In these examples we have declared two new variables `$name` and `$boldness`. +The value of the expression is used determine what type the value is to be declared as, so in the above examples `$name` is typed as a string because the expression value of `"General Kenobi"` is a string. + +The implementing program must not allow the variable declared to ever have a value set which is not of the declared type. +If this does occur the implementing program must flag this as an error. +The handling of encountering variables which have not been declared is unspecified but should generate an error. + +##### Explicit Typing + +It is assumed that most of the time variable type will be determined implicitly via the initial expression's type the value can explicitely set. +Syntactically this works identically to the implicit type declaration. +The type of the expression must match the suported types + +- `Number` +- `Bool` +- `String` + +If additional types are in use by the implementing program the keywords for their explicit definition are unspecified, but they must be consistent across all declarations. ### Flow control @@ -308,6 +359,20 @@ The order of these commands is always the same and must be followed: The if and endif must be present, the elseif and else must be optional. While each of these commands are their own statement they should be considered to be part of a larger flow control statement which spans multiple lines. +Each of these, except the `endif`, have an attached block. + +The following is an example of flow control, the dialogue line to be shown will depend on the value of `$var`. +If `$var` is `1`, the line `if-scope` will be presented, if it is `2` then the `elseif-scope` line will be shown. +If neither of those are the case then the `else-scope` line will be shown. +```yarn +<> + if-scope +<> + elseif-scope +<> + else-scope +<> +``` #### if @@ -327,6 +392,8 @@ The _keyword_ is the text `elseif`. The _expression_ is an expression. The expression must resolve to a boolean. +The elseif will run only if the `if` component, and any other `elseif`'s evaluated to false, and if its own expression evaluates to true. + The minimum mumber of required elseif commands must be zero. The maximum number of allowed elseif commands is unspecified but should be greater than zero. An elseif command must not exist without an if command and must go after the if command. @@ -340,6 +407,8 @@ There must only be a single else command (if any) per flow control. The else command must go after the if and any elseif commands. The else must not exist without an if command. +The else's block will run only if the `if` and any `elseif` components all evaluated to false. + The example of the else command is `<>`. #### endif @@ -451,9 +520,9 @@ _Expressions_ are mathematical chains of variables, values, functions, expressio Expressions are not a statement but are a component of various statements and must only be used as part of a statement, they cannot exist in isolation. This means if you do want to show the result of an expression it will have to be wrapped inside an interpolated line. -For example a line that is just `$numberOfCoins + 1` is invalid, but `{$numberOfCoins + 1}` is valid. +For example a line that is just `$numberOfCoins + 1` is and invalid line despite containing a valid expression, but `{$numberOfCoins + 1}` is valid. -Expressions are mostly used to control the flow of the if statement. +Expressions are mostly used to control the flow of the if statement, although they are also used as part of set statements, and in interpolated dialogue. ### Values @@ -461,7 +530,7 @@ A _Value_ is a single concrete form of one of the supported types. All expressions, subexpressions, variables and functions, must resolve down into a value before it can be used. Examples of values include `1`, `true`, `"General Kenobi"`. -### Types +### Supported Types Yarn supports the following types and these must be supported by an implementing program: @@ -469,7 +538,7 @@ Yarn supports the following types and these must be supported by an implementing - boolean - string -The precision, storage, and form of the number internally is unspecified, however it must support decimals. +The precision, storage, and form of the number internally by the implementing program is unspecified, however it must support decimals. As an example of this in C# the `Decimal`, `Complex`, and `float` formats are valid (though some make more sense than others) but `int` is not. Numbers in expressions can be written as either integers or as decimals, but decimal numbers must use the `.` symbol as the decimal seperator of the the number. @@ -480,7 +549,7 @@ Booleans must be capable of representing the boolean logic values of `true` and Booleans must not be exposed as `1` and `0` to expressions even if they are represented this way internally by the implementing program. Booleans in expressions must be written as `true` for true and `false` for false. -Additional types supported are unspecified. +Additional types supported are unspecified but should not be used. ### Variables @@ -498,16 +567,19 @@ The minimum and maximum length of a variable name is unspecified. Variable names must be unique throughout their scope. The _scope_ of the variable is what defines for how long a variable exists. Once a variable leaves its scope it is no longer valid and implementing programs must not support accessing variables outside of their scope. -The scope of variables is undefined, however implementing programs should err on the side of the smallest possible scope for a variable. +The scope of variables is undefined, however implementing programs should err on the side of variables being global in scope. `$name` is an example of a standard variable name, `$`\``character.name`\` is an example of an arbitrary sybmol variable name. #### Types -Variables have a type which represents which of the supported type' values it can hold. +Yarn is a statically typed language, in the context of Yarn this means variables have a type which represents which of the supported type's values it can hold. Once a variable has its type determined either by declaration or inference it cannot change. The implementing program must not allow variables to hold values of types different from its own. +Due to the nature of elements of Yarn being outside of the control of Yarn, notably functions, its possible for this requirement to be breached due to no fault of the implementing program or the Yarn script. +However In these circumstances the implementing program must generate an error. + ### Operations _Operations_ are mathematical functions that take operands and an operator and result in a new value. @@ -525,7 +597,7 @@ Some of these have multiple operators, these must work identically and exist for - multiplication `*` - division `\` - truncating remainder division (modulo) `%` -- equality `==` or `eq` +- equality `==` or `eq` or `is` - inequality `!=` or `neq` - greater-than `>` or `gt` - less-than `<` or `lt` From 0e820dae3bcd484009dc3d9fd3eb5717f3bc28e6 Mon Sep 17 00:00:00 2001 From: McJones Date: Mon, 18 Jan 2021 16:40:28 +1100 Subject: [PATCH 03/39] added a bunch of stuff to options --- Documentation/Yarn-Spec.md | 87 ++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 9 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 82b3f7e5a..57c38e305 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -468,22 +468,24 @@ _Options_ are the means by which Yarn can present dialogue choices to the game a Options are comprised of one or more option lines. An _option line_ represents a single choice in an option, and are comprised of three parts: the keyword, the dialogue, the conditional in that order. -The _keyword_ is how the implementing program can tell a line is part of an option instead of dialogue and is the symbols `->`. +The _keyword_ is how the implementing program can tell a line is part of an option instead of dialogue and is the symbol `->`. There must be at least one whitespace between the keyword and the next element, the dialogue. The _dialogue_ is a normal line of dialogue following all rules associated with that. -The _conditional_ is a command which controls the specifics of the validity of the option. -The conditional allows for additional data about the option to be bundled along with the line. -The intent of the conditional is for the game to know which lines are currently valid for selection and which are not without forcing the writer to duplicate options inside of a control flow. -The conditional's syntax is identical to the if command and follows all rules there, but as it is not part of flow control must not have an accompanying endif or attached block. -The conditional must be an optional component of the option line. - -As the intention of options is to provide choice when options are encountered the implementing program must halt further progress through the node until an option has been selected. +As the intention of options is to provide choice to the player when options are encountered the implementing program must halt further progress through the node until an option has been selected. Each option must be provided in the order they are written in the node. The mechanism by which an option line is chosen is unspecified. Only a single option line must be chosen. -As the conditional controls the validity of the option for selection this information must be provided by implementing program to the parts of the game that makes the selections. +#### Conditional + +The _conditional_ is a command which provides addtional data about the validity of the option. +The intent of the conditional is to allow the writer to give the game more information about the option. +The conditional's syntax is identical to the if command and follows all rules there, but as it is not part of flow control must not have an accompanying endif or attached block. +The conditional must be an optional component of the option line. +As the conditional is optional any option line without a conditional must be assumed to be `true`. + +The implementing program must process the results of the conditional expression and provide the resulting boolean value to the other parts of the game that makes the selection. The implementing program must not restrict the selection of invalid options. It is the responsibility of the other components of the game to control how invalid options are to be handled. @@ -505,6 +507,7 @@ These rules are repeated for each option line until a non-option line with the s Options can be nested inside options. Not every option line needs to have blocks. +The maximum number of supported indentation of options inside a block is unspecified. ##### Tabs vs Space @@ -514,6 +517,72 @@ Should there be a need to convert between them the conversion rate must be the s The rate of conversion between tabs to spaces, and spaces to tabs, is unspecified. If there is a need to choose one, tabs should be preferred due to their improved accessibility over spaces. +#### Examples + +``` +-> Hi +-> Hi {$name} +``` + +The above is an example of an option with two choices for the player to make. +The first is a regular lines of dialogue, the second is an interpolated line of dialogue. + +``` +-> Hi +-> Hi Fred < 3>> +``` + +The above is an example of an option with two choices for the player to make. +Both have regular lines of dialogue. +The second has a conditional component, the validity of the second option line will be `true`. + +``` +-> Hi + So, are we doing this? + Yes, lets. +-> Hi Fred + What's the plan? + We're doing it. +Alright! +``` + +The above is an example of an option with two choices and another line of dialogue after the option. +Both are a regular lines of dialogue and both have an attached block. +If the first option was selected then the lines to be presented would be as follows: +``` +So, are we doing this? +Yes, lets. +Alright! +``` + +``` +-> Hi Fred + What's the plan? + We're doing it. + -> Alright! + Yep + -> Ok. +-> Hi +``` + +The above is an example of an option with nested options in its block. +The `Alright` and `Ok` option lines are inside the `Hi Fred` option line's block. +The `Yep` line would only ever be presented if the `Hi Fred` option was selected and then the `Alright` option was selected after that. + +``` +-> Hi +-> Hi Fred < 3>> + what's the plan? + We're doing it. + -> Alright! + Yep + -> Ok +-> Hello {$name} < 2 >> +-> Hi {$name} +``` + +The above is an example of an option with multiple option lines, conditionals, interpolated dialogue, nested options, and blocks. + ## Expressions _Expressions_ are mathematical chains of variables, values, functions, expressions, and operators that produce a single value as output. From ca482bbbd50031d800cc62fe37781352c71146fb Mon Sep 17 00:00:00 2001 From: McJones Date: Tue, 19 Jan 2021 11:06:01 +1100 Subject: [PATCH 04/39] cleaned up operators section. Removed some barely used aliases. Added some more common aliases. --- Documentation/Yarn-Spec.md | 46 +++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 57c38e305..5a07e7218 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -661,19 +661,19 @@ Most operations are binary operations and have two operands, these go either sid The following binary operations and their operator must be supported. Some of these have multiple operators, these must work identically and exist for people who prefer to use words instead of symbols: -- addition `+` -- subtraction `-` -- multiplication `*` -- division `\` -- truncating remainder division (modulo) `%` -- equality `==` or `eq` or `is` -- inequality `!=` or `neq` -- greater-than `>` or `gt` -- less-than `<` or `lt` -- great-than-or-equal `>=` or `gte` -- less-than-or-equal `<=` or `let` -- boolean OR `||` -- boolean AND `&&` +- addition: `+` +- subtraction: `-` +- multiplication: `*` +- division: `/` +- truncating remainder division (modulo): `%` +- equality: `==` or `is` +- inequality: `!=` +- greater-than: `>` +- less-than: `<` +- greater-than-or-equal: `>=` +- less-than-or-equal: `<=` +- boolean OR: `||` or `or` +- boolean AND: `&&` or `and` The amount of whitespace between operands and operators in binary operations is unspecified. @@ -681,8 +681,8 @@ There are two unary operations that have only a single operand. The operator always goes to the left side of the operand and the must be no whitespace between the operator and operand. The unary operations are: -- minus `-` -- boolean NOT `!` +- minus: `-` +- boolean NOT: `!` Parentheses are a special form of operation. They are for bundling up elements of an expression into a subexpression. @@ -696,7 +696,7 @@ The `+` operator when operating on strings is not addition in the mathematical s The following table shows the compatible types for each binary operation and must be supported: -| | + | - | * | / | % | == | != | gt | lt | gte | lte | \|\| | && | +| | + | - | * | / | % | == | != | > | < | >= | <= | \|\| | && | |----------|---|---|---|---|---|----|----|----|----|-----|-----|------|----| | numbers | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | | strings | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | @@ -720,7 +720,7 @@ This taken to the extreme should mean that `1 + "hello" == "hello + 1` should ev The following table shows the expected output type of each operation based on its operand type: -| | + | - | * | / | % | == | != | gt | lt | gte | lte | \|\| | && | ! | unary minus | +| | + | - | * | / | % | == | != | > | < | >= | <= | \|\| | && | ! | unary minus | |---------|--------|--------|--------|--------|--------|---------|---------|---------|---------|---------|---------|---------|---------|---------|-------------| | number | number | number | number | number | number | boolean | boolean | boolean | boolean | boolean | boolean | boolean | boolean | | number | | string | string | | | | | boolean | boolean | | | | | | | | | @@ -730,12 +730,12 @@ The following table shows the expected output type of each operation based on it The order of operations is as follows: -1. `()` -1. `!`, `unary minus` -1. `*`, `/`, `%` -1. `-`, `+` -1. `==`, `!=`, `lt`, `gt`, `lte`, `gte` -1. `||`, `&&` +1. parentheses (`()`) +1. boolean NOT (`!`), unary minus (`-`) +1. multiplication (`*`), division (`/`), truncating remainder division (`%`) +1. subtraction (`-`), addition (`+`) +1. equality (`==` or `is`), inequality (`!=`), less-than (`<`), greater-than (`>`), less-than-or-equal (`<=`), greater-than-or-equal (`>=`) +1. boolean OR (`||` or `or`), boolean AND (`&&` or `and`) If there are any equal priority operations in an expression they are resolved left to right as encountered in the expression. From 421103e3b75a5d5e86adcc8f375e3c49897e274c Mon Sep 17 00:00:00 2001 From: McJones Date: Tue, 19 Jan 2021 11:48:06 +1100 Subject: [PATCH 05/39] added xor into operators --- Documentation/Yarn-Spec.md | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 5a07e7218..ae4498fa1 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -674,6 +674,7 @@ Some of these have multiple operators, these must work identically and exist for - less-than-or-equal: `<=` - boolean OR: `||` or `or` - boolean AND: `&&` or `and` +- boolean XOR: `^` or `xor` The amount of whitespace between operands and operators in binary operations is unspecified. @@ -696,11 +697,11 @@ The `+` operator when operating on strings is not addition in the mathematical s The following table shows the compatible types for each binary operation and must be supported: -| | + | - | * | / | % | == | != | > | < | >= | <= | \|\| | && | -|----------|---|---|---|---|---|----|----|----|----|-----|-----|------|----| -| numbers | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | -| strings | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | -| booleans | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | +| | + | - | * | / | % | == | != | > | < | >= | <= | \|\| | && | ^ | +|----------|---|---|---|---|---|----|----|----|----|-----|-----|------|----|---| +| numbers | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | +| strings | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | +| booleans | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | The following table shows the compatible types for each unary operation and must be supported: @@ -720,11 +721,11 @@ This taken to the extreme should mean that `1 + "hello" == "hello + 1` should ev The following table shows the expected output type of each operation based on its operand type: -| | + | - | * | / | % | == | != | > | < | >= | <= | \|\| | && | ! | unary minus | -|---------|--------|--------|--------|--------|--------|---------|---------|---------|---------|---------|---------|---------|---------|---------|-------------| -| number | number | number | number | number | number | boolean | boolean | boolean | boolean | boolean | boolean | boolean | boolean | | number | -| string | string | | | | | boolean | boolean | | | | | | | | | -| boolean | | | | | | boolean | boolean | | | | | boolean | boolean | boolean | | +| | + | - | * | / | % | == | != | > | < | >= | <= | \|\| | && | ! | unary minus | ^ | +|---------|--------|--------|--------|--------|--------|---------|---------|---------|---------|---------|---------|---------|---------|---------|-------------|---------| +| number | number | number | number | number | number | boolean | boolean | boolean | boolean | boolean | boolean | boolean | boolean | | number | | +| string | string | | | | | boolean | boolean | | | | | | | | | | +| boolean | | | | | | boolean | boolean | | | | | boolean | boolean | boolean | | boolean | #### Order of Operations @@ -735,7 +736,7 @@ The order of operations is as follows: 1. multiplication (`*`), division (`/`), truncating remainder division (`%`) 1. subtraction (`-`), addition (`+`) 1. equality (`==` or `is`), inequality (`!=`), less-than (`<`), greater-than (`>`), less-than-or-equal (`<=`), greater-than-or-equal (`>=`) -1. boolean OR (`||` or `or`), boolean AND (`&&` or `and`) +1. boolean OR (`||` or `or`), boolean AND (`&&` or `and`), boolean XOR (`^` or `xor`) If there are any equal priority operations in an expression they are resolved left to right as encountered in the expression. From a67d8b959cdd59b924c1788831f05d326e6777f7 Mon Sep 17 00:00:00 2001 From: McJones Date: Tue, 19 Jan 2021 11:48:20 +1100 Subject: [PATCH 06/39] cleaned up section on declaring vars --- Documentation/Yarn-Spec.md | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index ae4498fa1..ccffd3deb 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -84,7 +84,7 @@ A line is a series of characters terminated by the *new line* symbol. The new line symbol should be the `\n` character. The new line must be the same throughout the project regardless of the chosen new line symbol. -The following Yarn file contains four lines (in order); one header tag line, one header delimiter lione, one body dialogue line, one body delimiter line. +The following Yarn file contains four lines (in order); one header tag line, one header delimiter line, one body dialogue line, one body delimiter line. ```yarn Title:Start --- @@ -290,7 +290,7 @@ The set command has four components: the keyword, the variable, the operator and The _keyword_ is the text `set`. The _variable_ is the name of the variable which is to have its value changed. -The _operator_ must be the text `to`. +The _operator_ must be the text `to` or `=`. The _expression_ is any expression, unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. The following is an example of two set commands: @@ -310,7 +310,7 @@ The declare command has four components: the keyword, the variable, the operator The _keyword_ is the text `declare`. The _variable_ is the name of the variable which is to have its value changed. -The _operator_ must be the text `=`. +The _operator_ must be the text `=` or `to`. The _expression_ is any expression, unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. The resulting value of the expression is used determine what type the value has been declared as, so if expression results in a boolean for example then the variable is declared as a boolean. @@ -330,13 +330,17 @@ The handling of encountering variables which have not been declared is unspecifi ##### Explicit Typing -It is assumed that most of the time variable type will be determined implicitly via the initial expression's type the value can explicitely set. -Syntactically this works identically to the implicit type declaration. -The type of the expression must match the suported types +It is assumed that most of the time a variable's type will be determined implicitly via the initial expression, however the type can also be explicitly set. +Syntactically this works identically to the implicit type declaration with two additional elements at the end of the command, the `as` keyword and a type. +The type of the expression must match one of the suported types keywords: -- `Number` -- `Bool` -- `String` +- `Number` for Numbers +- `Bool` for Booleans +- `String` for Strings + +`<>` is an example of an explicitly typed declaration. +Explicitly typed declarations will most likely be used when getting intial values from functions where the type is undefined but they can be used anywhere. +The default value's type given in a an explictly typed declaration must match the type, for example `<>` is an invalid declaration because `General Kenobi` isn't a `Number`. If additional types are in use by the implementing program the keywords for their explicit definition are unspecified, but they must be consistent across all declarations. @@ -629,7 +633,7 @@ Variables can only be used inside of expressions. All variables must start with the `$` symbol followed immediately by any combination of `a`-`z`, `A` - `Z`, and `0-9`. Arbitrary symbol variable names are allowed by wrapping the symbols after the `$` inside backtick symbols \`. -Any symbols except another backtick are allowed in an arbitrary sybmol variable name. +Any symbols except another backtick are allowed in an arbitrary symbol variable name. This is useful to allow writers to create semantic connections between variables. The minimum and maximum length of a variable name is unspecified. From 45a4eb563d18a8f2f252e4120df838d646f3c24b Mon Sep 17 00:00:00 2001 From: McJones Date: Tue, 9 Feb 2021 09:35:33 +1100 Subject: [PATCH 07/39] updating identifier rules --- Documentation/Yarn-Spec.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index ccffd3deb..ffa72eb3d 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -113,6 +113,15 @@ A comment starting in the middle of another line ends that line at the point the That line is assumed to have finished at that point as if the comment was not there. Comments must not impact the rest of the lines or have any impact on the resulting yarn program. +### Identifiers + +Throughout various points in this document identifiers are mentioned, the rules for these are shared across all stages of the Yarn project. + +An *identifier* is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a noncombining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. +After the first character digits, a period (`.`), and combining Unicode characters are also allowed. +But not another `$` symbol. +The minimum and maximum length of identifiers is unspecified. + ## Yarn Structure A Yarn script file is yarn file that contains one or more nodes and zero or more file tags. @@ -141,9 +150,9 @@ After encountering the header delimiter the body of the node is entered. #### Header Tags A *header tag* is a line broken up into three components, in order; the tag name, the separator, and the tag text. -The *tag name* can be any combination of the characters `A` - `Z`, `a` - `z`, `0` - `9`. +The *tag name* is an identifier. The *tag separator* is the character `:`. -The *tag text* can be any combination of the characters `A` - `Z`, `a` - `z`, `0` - `9`. +The *tag text* is all text up until the end of line. Header tags are commonly used as node specific metadata but using them in this manner is not required, beyond the title tag. The amount of allowed whitespace between the tag name, the seperator, and the tag text is unspecified. @@ -159,6 +168,7 @@ The *title tag* is a specific header tag that uniquely identifies the node. The tag name for the title tag must be `Title`. The tag text for the title tag must be unique within the file. The tag text for the title tag should be unique within the project. +The tag text must follow the rules of identifiers. The behaviour of the program when a title tag's text is not unique across the project is unspecified. The program should flag this as an error. @@ -631,18 +641,16 @@ Variables can only be used inside of expressions. #### Naming and scope -All variables must start with the `$` symbol followed immediately by any combination of `a`-`z`, `A` - `Z`, and `0-9`. -Arbitrary symbol variable names are allowed by wrapping the symbols after the `$` inside backtick symbols \`. -Any symbols except another backtick are allowed in an arbitrary symbol variable name. -This is useful to allow writers to create semantic connections between variables. -The minimum and maximum length of a variable name is unspecified. +All variables are a variant on identifiers. +Variables are an identifier that start with a `$` symbol and otherwise follow all other identifier rules. +The minimum and maximum length of a variable name is unspecified but must be at least one character after the `$` symbol. Variable names must be unique throughout their scope. The _scope_ of the variable is what defines for how long a variable exists. Once a variable leaves its scope it is no longer valid and implementing programs must not support accessing variables outside of their scope. The scope of variables is undefined, however implementing programs should err on the side of variables being global in scope. -`$name` is an example of a standard variable name, `$`\``character.name`\` is an example of an arbitrary sybmol variable name. +`$name` is an example of a variable name, `$𐃩` is another example of a variable name. #### Types From c13c19d13f4f6e005f8e76556722b7679dc3de88 Mon Sep 17 00:00:00 2001 From: McJones Date: Tue, 9 Feb 2021 09:36:05 +1100 Subject: [PATCH 08/39] modified how hashtags work --- Documentation/Yarn-Spec.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index ffa72eb3d..d6b8e60c4 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -197,9 +197,9 @@ The other components of the statement must end at the hashtag, the hashtag opera A hashtag starts with the `#` symbol and contain any text up to the newline or another hashtag. `#lineID:a10be2` is an example of a hashtag. -Multiple hashtags must be separated by the `,` symbol. -`#lineID:a10be2, #return` is an example of multiple hashtags on a line. -`General Kenobi: Why hello there #lineID:a10be2, #return` is an example of a line of dialogue with multiple hashtags. +Multiple hashtags can exist on a single line. +`#lineID:a10be2 #return` is an example of multiple hashtags on a line. +`General Kenobi: Why hello there #lineID:a10be2 #return` is an example of a line of dialogue with multiple hashtags. ### Dialogue Statement From a94a1bc951bc438d3fcb4b69a0604920838eea31 Mon Sep 17 00:00:00 2001 From: McJones Date: Tue, 9 Feb 2021 09:50:27 +1100 Subject: [PATCH 09/39] updated file tag rules to be more permissive --- Documentation/Yarn-Spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index d6b8e60c4..951704b08 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -131,7 +131,7 @@ A Yarn script file is yarn file that contains one or more nodes and zero or more _File tags_ are file level metadata that is relevant for all nodes in the file. A common use for file tags is for versioning the file. File tags must go at the start of a file before any nodes begin. -File tags must have the `#` symbol at the start of them but are syntactically identical otherwise to the Header Tags of nodes. +File tags must have the `#` symbol at the start of them and then contain all text up until the end of the line. ### Nodes From 8339a09f89076c4c46e178d7caf378a0f4f1d904 Mon Sep 17 00:00:00 2001 From: McJones Date: Tue, 9 Feb 2021 09:51:00 +1100 Subject: [PATCH 10/39] functions now follow identifier rules --- Documentation/Yarn-Spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 951704b08..621e89ec7 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -762,7 +762,7 @@ Functions must return a value. Functions are comprised of a name, parentheses, and parameters. -The _function name_ can be any combination of the characters `a` - `z`, `A` - `Z`, and `0` - `9`, but must not start with a number. +The _function name_ is an identifier. The minimum and maximum length of function names is unspecified. The parentheses go after the function name and there must be no whitespace between the opening parentheses `(` and the function name. From aa1e08cee9cb975d1d02895d7098aac9b4e7489c Mon Sep 17 00:00:00 2001 From: McJones Date: Sun, 7 Mar 2021 14:32:39 +1100 Subject: [PATCH 11/39] added some clarification around the spec and duplicate header tags --- Documentation/Yarn-Spec.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 621e89ec7..a8a7edf79 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -173,6 +173,13 @@ The tag text must follow the rules of identifiers. The behaviour of the program when a title tag's text is not unique across the project is unspecified. The program should flag this as an error. + +#### Duplicate Tags + +Duplicate header tags within a node is invalid. +The implementing program must either throw an error when encountering a duplicate tag or ignore all but the first duplicate tag. +If the implementing program is ignoring later duplicates then the user should still be informed as the existence of duplicate tags. + ### Body A body is comprised of multiple statements. From e74ea2119b8dd1aa1bc2d4d98bd07785bd94baea Mon Sep 17 00:00:00 2001 From: McJones Date: Sun, 7 Mar 2021 14:34:57 +1100 Subject: [PATCH 12/39] added clarification around handling of duplicate file tags --- Documentation/Yarn-Spec.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index a8a7edf79..f3ba18f4c 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -133,6 +133,12 @@ A common use for file tags is for versioning the file. File tags must go at the start of a file before any nodes begin. File tags must have the `#` symbol at the start of them and then contain all text up until the end of the line. +#### Duplicate Tags + +Duplicate file tags within a file is invalid. +The implementing program must either throw an error when encountering a duplicate file tag or ignore all but the first duplicate file tag. +If the implementing program is ignoring later duplicates then the user should still be informed as the existence of duplicate file tags. + ### Nodes A *node* is the single story element of a yarn file. From 8b81e4d0c245cfa6319e334b52e7c5036ce2d20a Mon Sep 17 00:00:00 2001 From: McJones Date: Sun, 7 Mar 2021 15:00:00 +1100 Subject: [PATCH 13/39] renamed directions to generic commands --- Documentation/Yarn-Spec.md | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index f3ba18f4c..652c51a5c 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -42,7 +42,7 @@ Only the `Title` tag is required, an implementation may choose to make other tag There is one large assumption in this document and about the language itself. That is it that it is intended to be embedded into a larger game project. -As such details like how lines are viewed, how selections of options are made, how directions get used, or how functions are handled are all assumed to be passed off onto the larger game to handle. +As such details like how lines are viewed, how selections of options are made, how generic commands get used, or how functions are handled are all assumed to be passed off onto the larger game to handle. This is not technically necessary but does explain what would otherwise be gaps in the language. If your project does not have a game to offload certain tasks to these elements will have to be handled by the implementing program itself. @@ -179,7 +179,6 @@ The tag text must follow the rules of identifiers. The behaviour of the program when a title tag's text is not unique across the project is unspecified. The program should flag this as an error. - #### Duplicate Tags Duplicate header tags within a node is invalid. @@ -251,7 +250,7 @@ Commands are special statements that have no specific output to be shown but are The possible types of commands are: -- directions +- generic commands - jump - stop - set @@ -261,22 +260,24 @@ The possible types of commands are: All commands must start with the `<<` symbol and end with the `>>` symbol. Additional required command are unspecified. -#### Directions +#### Generic Commands -_Directions_ are commands for sending messages from the yarn to the rest of the program. -Implementing programs must not modify the flow of the yarn based on the direction. +_Generic Commands_ are commands for sending messages from the yarn to the rest of the program. +Unlike the other commands generic commands don't impact the dialogue. +They can be thought of as lines of dialogue that aren't to be shown in the game. +Implementing programs must not modify the flow of the yarn based on the command. -Directions can have any text except for the `#`, `{`, or `}` symbols inside of them. +Generic commands can have any text except for the `#`, `{`, or `}` symbols inside of them. -Directions can also have expressions inside of them, however as with dialogue these must be encapsulated by using the `{` and `}` symbols. -Any expressions inside of a directions command without being encapsulated must be ignored and treated instead as regular text. +Generic commands can also have expressions inside of them, however as with dialogue these must be encapsulated by using the `{` and `}` symbols. +Any expressions inside of a generic command without being encapsulated must be ignored and treated instead as regular text. ```yarn <> <> <> ``` -are examples of directions. +are examples of generic commands. #### Jump From 736c7985c7f178394b1cea75d4cda837191973d3 Mon Sep 17 00:00:00 2001 From: McJones Date: Sun, 7 Mar 2021 15:32:44 +1100 Subject: [PATCH 14/39] improved description of how numbers are represented --- Documentation/Yarn-Spec.md | 39 +++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 652c51a5c..62e22a752 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -635,9 +635,22 @@ Yarn supports the following types and these must be supported by an implementing - boolean - string +There are two types of numbers, *positive* and *negative*. +Positive Numbers are broken up into three components: the *integer part*, the *decimal seperator*, and the *fractional part*. + +The integer part consists of one or more characters `0` - `9`. +The decimal seperator is optional and consists solely of the `.` symbol. +The fractional part is optional and consists of one or more chracters `0` - `9`. + +The decimal seperator must not exists without a fractional part also existing. +The decimal seperator and fractional part must not exist without an integer part. + +Negative numbers follow all the same rules as positive numbers but begin with the *negation indicator* `-`. +The negation indicator must go hard up against the integer part, there must not be whitespace between them. + The precision, storage, and form of the number internally by the implementing program is unspecified, however it must support decimals. As an example of this in C# the `Decimal`, `Complex`, and `float` formats are valid (though some make more sense than others) but `int` is not. -Numbers in expressions can be written as either integers or as decimals, but decimal numbers must use the `.` symbol as the decimal seperator of the the number. +If a number is beyond the precision supported by the implementing program, the program must report this as an error. Strings must be capable of holding utf-8 values as this is what the yarn language is written in, but the internals of this is unspecified provided all valid utf-8 characters are supported. Strings in expressions must be encapsulated between `"` and `"` symbols. @@ -648,6 +661,30 @@ Booleans in expressions must be written as `true` for true and `false` for false Additional types supported are unspecified but should not be used. +#### Numeric Examples + +The following are examples of valid numbers in Yarn: + +``` +1 +0.5 +-1 +3.14159 +-1.414 +``` + +The following are examples of invalid numbers in Yarn: + +``` +.5 +1. +- 1 +``` + +The first of these is invalid because it does not have an integer part to the number. +The second is invalid because it has a decimal seperator but doesn't have a fractional part. +The third is invalid because it has a space between the negation indicator and the integer part. + ### Variables _Variables_ are a means of associating a value with a name so that it can be more easily used and changed in multiple places. From dc9af2eeb8adc8336edd404cd52469d32459b794 Mon Sep 17 00:00:00 2001 From: McJones Date: Sun, 7 Mar 2021 15:47:01 +1100 Subject: [PATCH 15/39] added further explanation as to the handling of functions --- Documentation/Yarn-Spec.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 62e22a752..0c4700067 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -836,6 +836,9 @@ rad2Deg(1.5707963268) #### Handling -The handling of functions by the implementing program is unspecified, however the output type of a function must not change at runtime between calls. +The handling of functions by the implementing program is unspecified, however the output type of a function must always return the same type of value between calls at runtime. +The Yarn language makes no promises as to the order in which, or number of times an implementing program may call functions. + The implementing program should allow external parts of the game to provide the return value of the function. If given the same input parameters multiple invocations of the same functions should return the same value each time. +In general, and while not a specific requirement, implementing programs should err on the side of treating functions in Yarn as if they are [pure functions](https://en.wikipedia.org/wiki/Pure_function). From 32e679b9cff6f3718715764b22c8bb22573b5f75 Mon Sep 17 00:00:00 2001 From: McJones Date: Sun, 7 Mar 2021 16:21:53 +1100 Subject: [PATCH 16/39] minor tweaks --- Documentation/Yarn-Spec.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 0c4700067..2f4a842b0 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -420,10 +420,10 @@ The _keyword_ is the text `elseif`. The _expression_ is an expression. The expression must resolve to a boolean. -The elseif will run only if the `if` component, and any other `elseif`'s evaluated to false, and if its own expression evaluates to true. +The elseif will run only if the `if` component, and any other `elseif`'s before it evaluated to false, and if its own expression evaluates to true. The minimum mumber of required elseif commands must be zero. -The maximum number of allowed elseif commands is unspecified but should be greater than zero. +The maximum number of allowed elseif commands in a flow control statement is unspecified but must be greater than zero. An elseif command must not exist without an if command and must go after the if command. #### else @@ -617,7 +617,7 @@ _Expressions_ are mathematical chains of variables, values, functions, expressio Expressions are not a statement but are a component of various statements and must only be used as part of a statement, they cannot exist in isolation. This means if you do want to show the result of an expression it will have to be wrapped inside an interpolated line. -For example a line that is just `$numberOfCoins + 1` is and invalid line despite containing a valid expression, but `{$numberOfCoins + 1}` is valid. +For example a line that is just `$numberOfCoins + 1` while a valid line of dialogue is not going to give the result of the expression, but `{$numberOfCoins + 1}` is a valid line of dialogue that will present the result of that expression. Expressions are mostly used to control the flow of the if statement, although they are also used as part of set statements, and in interpolated dialogue. @@ -644,6 +644,7 @@ The fractional part is optional and consists of one or more chracters `0` - `9`. The decimal seperator must not exists without a fractional part also existing. The decimal seperator and fractional part must not exist without an integer part. +There must be no whitespace between any of the three parts of the number. Negative numbers follow all the same rules as positive numbers but begin with the *negation indicator* `-`. The negation indicator must go hard up against the integer part, there must not be whitespace between them. @@ -652,7 +653,7 @@ The precision, storage, and form of the number internally by the implementing pr As an example of this in C# the `Decimal`, `Complex`, and `float` formats are valid (though some make more sense than others) but `int` is not. If a number is beyond the precision supported by the implementing program, the program must report this as an error. -Strings must be capable of holding utf-8 values as this is what the yarn language is written in, but the internals of this is unspecified provided all valid utf-8 characters are supported. +Strings must be capable of holding UTF-8 values as this is what the yarn language is written in, but the internals of this is unspecified provided all valid UTF-8 characters are supported. Strings in expressions must be encapsulated between `"` and `"` symbols. Booleans must be capable of representing the boolean logic values of `true` and `false`, however the specific implementation is undefined. @@ -679,11 +680,13 @@ The following are examples of invalid numbers in Yarn: .5 1. - 1 +1. 414 ``` The first of these is invalid because it does not have an integer part to the number. The second is invalid because it has a decimal seperator but doesn't have a fractional part. The third is invalid because it has a space between the negation indicator and the integer part. +The forth is invalid because it has a space between the decimal seperator and the fractional part. ### Variables From 333ade76f01e55c52fc99662e70f476270a1d8b2 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Fri, 17 Sep 2021 15:34:18 +1000 Subject: [PATCH 17/39] Lots of little changes to the spec In particular linked everything (I think) that should be linked. Clarified various elements. Reordered numerous sections to better flow. --- Documentation/Yarn-Spec.md | 300 +++++++++++++++++++++---------------- 1 file changed, 169 insertions(+), 131 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 2f4a842b0..b77410631 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -19,7 +19,7 @@ Post Night in the Woods Yarn Spinner continued as its own thing with version 0.9 Later version 1.0 of Yarn Spinner, and as such the language, came out with improved syntax and was the first significant release that wasn't tied to Night in the Woods. Neither Yarn Spinner 0.9 or 1.0 however came with complete specifications of the Yarn language and had a great deal of legacy elements. -A concerted effort was made to clean up the Yarn language in 2020 for Yarn Spinner 2.0 into something hopefully more understandable but also more flexible. +A concerted effort was made to clean up the Yarn language for Yarn Spinner 2.0 into something hopefully more understandable but also more flexible. A component of this is the creation of this specification guide so implementations beyond Yarn Spinner can have something to base decisions on that isn't "do what Yarn Spinner does". Despite this being the first version of the Yarn language to ever exist it is version 2 of the Yarn language. @@ -35,7 +35,7 @@ This document does not cover how a yarn file is to be transformed or handled int This document does note when behaviours are *unspecified*. The implementing program may choose how to handle any unspecified behaviour, often unspecified behaviours have no good solution and should result in an error. An example of unspecified behaviour are required tags on Nodes. -Only the `Title` tag is required, an implementation may choose to make other tags required or banned. +Only the `title` tag is required, an implementation may choose to make other tags required or banned. ### Assumptions @@ -49,7 +49,7 @@ If your project does not have a game to offload certain tasks to these elements ### Reading This Specification `monofont` terms are to be taken as literals. -As an example the `Title` tag would be written as a string literal `"Title"` in C#. +As an example the `title` tag would be written as a string literal `"title"` in C#. *italics* terms are terms which are reused throughout the document. They are presented in italics the first time they are defined. @@ -58,6 +58,7 @@ _Must_ is a hard requirement. _Should_ is a recommendation, albeit a strong one. _Errors_ are mentioned multiple times and represent situations that are unrecoverable. +A goal of Yarn is to have all errors known and handled at creation time instead of runtime but this isn't always possible. Errors are intended to allow the implementing program to let the user or other parts of the game know that an unrecoverable situation has occured. The implementing program must abort progress on the Yarn after creating an error. The precise handling of errors will be specific to the implementing program but should use whatever error mechanisms exist already, for example Yarn Spinner throws normal C# exceptions for its errors. @@ -74,9 +75,15 @@ This is to ensure implementing programs can conform to a language version and no ## File Format -Yarn files must be a UTF-8 text file without BOM set. +Yarn files must be a UTF-8 text file and should not have the BOM set. File extension should be `.yarn`. +### Project + +The yarn *project* is all yarn files that are intended to be associated with one another. +While there is nothing stopping a writer from placing all nodes into one big file (or even making one giant node) it is common to break them up over multiple files. +The project is all of these files collected and processed by the implementing program together. + ### Lines The *line* is the common unit that comprises all elements in a yarn file. @@ -86,7 +93,7 @@ The new line must be the same throughout the project regardless of the chosen ne The following Yarn file contains four lines (in order); one header tag line, one header delimiter line, one body dialogue line, one body delimiter line. ```yarn -Title:Start +title:Start --- This is some text === @@ -97,13 +104,7 @@ This is some text *Whitespace* is any non-visible character with a width greater than 0. Common whitespace encountered include the space and the tab. -Whitespace for lines of dialogue plays no role but has significant syntactic important for Options. - -### Project - -The yarn *project* is all yarn files that are intended to be associated with one another. -While there is nothing stopping a writer from placing all nodes into one big file (or even making one giant node) it is common to break them up over multiple files. -The project is all of these files collected and processed by the implementing program together. +Whitespace for the most part plays no role for the majority of Yarn, but has significant syntactic impact for [Options](#options). ### Comments @@ -119,12 +120,12 @@ Throughout various points in this document identifiers are mentioned, the rules An *identifier* is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a noncombining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. After the first character digits, a period (`.`), and combining Unicode characters are also allowed. -But not another `$` symbol. +The `$` symbol must not be part of an identifier. The minimum and maximum length of identifiers is unspecified. ## Yarn Structure -A Yarn script file is yarn file that contains one or more nodes and zero or more file tags. +The basic structure of a yarn file is zero or more file tags and one or more yarn nodes. ### File Tags @@ -133,12 +134,6 @@ A common use for file tags is for versioning the file. File tags must go at the start of a file before any nodes begin. File tags must have the `#` symbol at the start of them and then contain all text up until the end of the line. -#### Duplicate Tags - -Duplicate file tags within a file is invalid. -The implementing program must either throw an error when encountering a duplicate file tag or ignore all but the first duplicate file tag. -If the implementing program is ignoring later duplicates then the user should still be informed as the existence of duplicate file tags. - ### Nodes A *node* is the single story element of a yarn file. @@ -159,10 +154,10 @@ A *header tag* is a line broken up into three components, in order; the tag name The *tag name* is an identifier. The *tag separator* is the character `:`. The *tag text* is all text up until the end of line. -Header tags are commonly used as node specific metadata but using them in this manner is not required, beyond the title tag. +Header tags are commonly used as node specific metadata but using them in this manner is not required, beyond the [title tag](#title-tag). -The amount of allowed whitespace between the tag name, the seperator, and the tag text is unspecified. -An example of a header tag is the title tag: `Title:start`. +The amount of allowed whitespace between the tag name, the separator, and the tag text is unspecified. +An example of a header tag is the title tag: `title:start`. Every node must have a title tag. Required or banned header tags beyond title are unspecified. @@ -171,10 +166,10 @@ The order of header tags is unspecified. #### Title Tag The *title tag* is a specific header tag that uniquely identifies the node. -The tag name for the title tag must be `Title`. +The tag name for the title tag must be `title`. The tag text for the title tag must be unique within the file. The tag text for the title tag should be unique within the project. -The tag text must follow the rules of identifiers. +The tag text must follow the rules of [identifiers](#identifiers). The behaviour of the program when a title tag's text is not unique across the project is unspecified. The program should flag this as an error. @@ -182,22 +177,22 @@ The program should flag this as an error. #### Duplicate Tags Duplicate header tags within a node is invalid. -The implementing program must either throw an error when encountering a duplicate tag or ignore all but the first duplicate tag. +The implementing program must either throw an error when encountering a duplicate tag or ignore all but the first instance of a tag. If the implementing program is ignoring later duplicates then the user should still be informed as the existence of duplicate tags. ### Body -A body is comprised of multiple statements. +A *body* is the part of the node that contains the story and all flow that impacts the story, and is comprised of multiple statements. A *statement* is a line that is one of the following: -- dialogue -- commands -- options +- [dialogue](#dialogue-statement) +- [commands](#commands) +- [options](#options) -A statement may have optional hashtags. +A statement may have optional [hashtags](#hashtags). A body must have at least one statement. -The body ends when encountering a line that contains the *body delimter* `===`. +The body ends when encountering a line that consists entirely of the *body delimter* `===`. The body delimiter ends both the current node and the body of that node. The end of file must not be used in place of a body delimiter. @@ -209,58 +204,69 @@ The other components of the statement must end at the hashtag, the hashtag opera A hashtag starts with the `#` symbol and contain any text up to the newline or another hashtag. `#lineID:a10be2` is an example of a hashtag. + Multiple hashtags can exist on a single line. `#lineID:a10be2 #return` is an example of multiple hashtags on a line. `General Kenobi: Why hello there #lineID:a10be2 #return` is an example of a line of dialogue with multiple hashtags. -### Dialogue Statement +## Dialogue Statement -A dialogue statement is a statement that represents a single line of text in the yarn story. +A dialogue statement is a statement that represents a single line of text in the yarn body. In most cases dialogue will be the bulk of the content of a node's body. -Dialogue lines can be interpolated dialogue or raw dialogue. +Dialogue statements can be [interpolated](#interpolated-dialogue) dialogue or [raw](#raw-dialogue) dialogue. +A dialogue statement can contain any characters except for the `#` character. -An *interpolated dialogue* is one where there are in-line expressions in the line. +`{$name}, you are a bold one.` is an example of an interpolated dialogue statement. +`General Kenobi, you are a bold one.` is an example of a raw dialogue statement. + +### Interpolated Dialogue + +An *interpolated dialogue* is dialogue where there are [expressions](#expressions) in the line. Expressions are encapsulated within the `{` and `}` symbols and it is the presence of these symbols that determine if a line is an interpolated one or not. The expression inside the `{}` symbols must be a valid expression. The result of the expression must be inserted into the dialogue. Other than replacing expressions dialogue statments must not be modified by the implementing program, and provided to the game as written. +The encapsulated expression can go anywhere inside the statement or even be the entire dialogue statement by itself. -A *raw dialogue* is a dialogue statement where there are no expressions. +### Raw Dialogue -A dialogue statement can contain any characters except for the `#` character. - -`{$name}, you are a bold one.` is an example of an interpolated dialogue. -`General Kenobi, you are a bold one.` is an example of a raw dialogue. - -When resolving ambiguity of statements inside the body the dialogue statement must be considered the lowest priority by the implementing program. -For example `<>` could be read as a command or a dialogue statement, it must be considered a command by the implementing program. +A *raw dialogue* is a dialogue statement where there are no expressions. -#### Escaping Text +### Escaping Text There are going to be times in dialogue that the writer will need to use symbols that are reserved. To use reserved symbols in dialogue preface any reserved symbol with the escape symbol `\`, this allows the following symbol to escape being understood as a reserved character. Any character following the escape must be presented in the dialogue as-is and must not be parsed as a special character. As an example `\{$name\}, you are a bold one.` would be presented as `{$name}, you are a bold one.` to the game. -Escaping text must be supported in both normal and interpolated dialogue lines as well as in the dialogue component of options. +Escaping text must be supported in both normal and interpolated dialogue lines as well as in the dialogue component of [Options](#options). + +### Statement Ambiguity + +Because the dialogue statement allows a great deal of flexibility in allowed characters every other statement inside the body could be considered to also be a valid dialogue statement. +This creates an ambiguity when parsing a yarn file, as such the dialogue statement must be considered the lowest priority by the implementing program. -### Commands +For example `<>` could be read as a [command](#commands) or a dialogue statement, it must be considered a command by the implementing program. +This does create a potential conflict between writer intent and yarn's requirements, however it is unavoidable. +To continue the earlier example if the writer intended `<>` to be a dialogue statement they would have to escape the reserved characters first, so `\<>` which would present as `<>` to the game. + +## Commands Commands are special statements that have no specific output to be shown but are used for passing messages and directions to other parts of the program and to control the flow of the story. The possible types of commands are: -- generic commands -- jump -- stop -- set -- declare -- flow control +- [generic commands](#generic-commands) +- [jump](#jump) +- [stop](#stop) +- [set](#set) +- [declare](#declare) +- [flow control](#flow-control) All commands must start with the `<<` symbol and end with the `>>` symbol. Additional required command are unspecified. -#### Generic Commands +### Generic Commands _Generic Commands_ are commands for sending messages from the yarn to the rest of the program. Unlike the other commands generic commands don't impact the dialogue. @@ -269,7 +275,7 @@ Implementing programs must not modify the flow of the yarn based on the command. Generic commands can have any text except for the `#`, `{`, or `}` symbols inside of them. -Generic commands can also have expressions inside of them, however as with dialogue these must be encapsulated by using the `{` and `}` symbols. +Generic commands can also have [expressions](#expressions) inside of them, however as with [dialogue](#interpolated-dialogue) these must be encapsulated by using the `{` and `}` symbols. Any expressions inside of a generic command without being encapsulated must be ignored and treated instead as regular text. ```yarn @@ -279,16 +285,16 @@ Any expressions inside of a generic command without being encapsulated must be i ``` are examples of generic commands. -#### Jump +### Jump -The _jump_ command is how a yarn program can move from one node to another. -The jump has two components: the keyword and destination. +The _jump_ command is how a yarn program can move from one [node](#nodes) to another. +The jump has two components: the keyword and the destination and these are separated by one or more whitespace. The _keyword_ is the text `jump` and comes first in the command. The _destination_ is the name of the node to move to. -The destination may be any text but must map to the `Title` of a node in the project. -The destination text may be created using the result of an expression, however this must be wrapped inside `{` `}` symbols. -The expression must resolve to a string value and must be a string that matches a node title in the project. +The destination may be any text but must map to the [`title`](#title-tag) of a node in the [project](#project). +The destination text may be created using the result of an [expression](#expressions), however this must be wrapped inside `{` `}` symbols. +The expression must resolve to a [string value](#supported-types) and must be a string that matches a node title in the project. The behaviour of an implementing program is unspecified when asked to jump to a destination that doesn't match a title in the project. The implementing program should flag this as an error. @@ -298,24 +304,25 @@ From that point on the destination nodes contents must instead be run. `<>` is an example of a jump command, `<>` is an example of a jump command using an expression to determine the destination node. -#### Stop +### Stop -The _stop_ command is for halting all progress on the project. -Once the stop command is reached all processing on the project must halt, no additional nodes are to be loaded and run, no additional dialogue or commands are to processed. +The _stop_ command is for halting all progress on the [project](#project). +Once the stop command is reached all processing on the project must halt, no additional [nodes](#nodes) are to be loaded and run, no additional [dialogue](#dialogue-statement) or [commands](#commands) are to processed. The stop command has only one component, the _keyword_ `stop`. -The stop command should reset any variable or internal state back to their initial states. +The stop command should reset any [variable](#variables) or internal state back to their initial states. `<>` is the example of the stop command. -#### Set +### Set -The _set_ command allows variables to be given values. +The _set_ command allows [variables](#variables) to be given [values](#values). The set command has four components: the keyword, the variable, the operator and the value and must be presented in that order. +Each component must be separated by one or more whitespace characters. The _keyword_ is the text `set`. The _variable_ is the name of the variable which is to have its value changed. The _operator_ must be the text `to` or `=`. -The _expression_ is any expression, unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. +The _value_ is any [expression](#expressions), unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. The following is an example of two set commands: ```yarn @@ -323,21 +330,22 @@ The following is an example of two set commands: <> ``` -The set command must follow all the rules for variable naming and expressions. -The set command must not allow setting a variable to an expression whose value is different from the type of that variable. +The set command must follow all the rules for [variable naming](#naming-and-scope) and expressions. +The set command must not allow setting a variable to an expression whose value is different from the [type](#supported-types) of that variable. -#### Declare +### Declare -Variables in Yarn should be declared to let the implementing program know the type of values they hold. +[Variables](#variables) in Yarn should be declared to let the implementing program know the [type](#supported-types) of values they hold. The intent of this is to allow the implementing program to set up memory and to provide guidance as to the usage of a variable directly from the writer. The declare command has four components: the keyword, the variable, the operator and the value, and must be presented in that order. +Each component must be separated by one or more whitespace characters. The _keyword_ is the text `declare`. -The _variable_ is the name of the variable which is to have its value changed. +The _variable_ is the name of the variable which is to have its type declared. The _operator_ must be the text `=` or `to`. -The _expression_ is any expression, unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. +The _value_ is any [expression](#expressions), unlike other uses of expressions this one must not be wrapped inside the `{` and `}` symbols. -The resulting value of the expression is used determine what type the value has been declared as, so if expression results in a boolean for example then the variable is declared as a boolean. +The resulting value of the expression is used determine what type the value has been declared as, so for example if the expression results in a boolean value then the variable is declared as a boolean. The following is an example of two declaration commands: ```yarn @@ -352,25 +360,27 @@ The implementing program must not allow the variable declared to ever have a val If this does occur the implementing program must flag this as an error. The handling of encountering variables which have not been declared is unspecified but should generate an error. -##### Explicit Typing +#### Explicit Typing It is assumed that most of the time a variable's type will be determined implicitly via the initial expression, however the type can also be explicitly set. Syntactically this works identically to the implicit type declaration with two additional elements at the end of the command, the `as` keyword and a type. -The type of the expression must match one of the suported types keywords: +The type of the expression must match one of the [suported types](#supported-types) keywords: - `Number` for Numbers - `Bool` for Booleans - `String` for Strings `<>` is an example of an explicitly typed declaration. -Explicitly typed declarations will most likely be used when getting intial values from functions where the type is undefined but they can be used anywhere. +Explicitly typed declarations will most likely be used when getting intial values from [functions](#functions) who's type is undefined. The default value's type given in a an explictly typed declaration must match the type, for example `<>` is an invalid declaration because `General Kenobi` isn't a `Number`. If additional types are in use by the implementing program the keywords for their explicit definition are unspecified, but they must be consistent across all declarations. ### Flow control -Flow control is a collection of commands that allow the writer to control the flow of the story. +_Flow control_ is a collection of commands that allow the writer to control the flow of the story. +The purpose of these commands is to limit and select which pieces of a story are presented. +Flow control in combination with [options](#options) and [jumps](#jump) are what make Yarn a non-linear narrative language. There are four commands which work in conjunction to support flow control: - if @@ -387,7 +397,7 @@ The order of these commands is always the same and must be followed: The if and endif must be present, the elseif and else must be optional. While each of these commands are their own statement they should be considered to be part of a larger flow control statement which spans multiple lines. -Each of these, except the `endif`, have an attached block. +Each of these, except the `endif`, have an attached [block](#scope-and-blocks). The following is an example of flow control, the dialogue line to be shown will depend on the value of `$var`. If `$var` is `1`, the line `if-scope` will be presented, if it is `2` then the `elseif-scope` line will be shown. @@ -406,7 +416,7 @@ If neither of those are the case then the `else-scope` line will be shown. The _if_ command is the opening command of flow control and is broken up into two parts, the keyword and the expression and must be in that order. The _keyword_ is the text `if`. -The _expression_ is an expression. +The _expression_ is an [expression](#expressions). The expression must resolve to a boolean. `< 1>>` is an example of an if command, `<>` is an example of an invalid if, it is invalid because the expression does not resolve to a boolean. @@ -417,7 +427,7 @@ The _elseif_ command is an optional component of flow control and allows for add The command works in a fashion very similar to the if command. The command is broken up into two parts, the keyword and the expression and must be presented in that order. The _keyword_ is the text `elseif`. -The _expression_ is an expression. +The _expression_ is an [expression](#expressions). The expression must resolve to a boolean. The elseif will run only if the `if` component, and any other `elseif`'s before it evaluated to false, and if its own expression evaluates to true. @@ -451,6 +461,8 @@ The endif exists to allow the implementing program know when the scope of the ot For the flow control to be useful there needs to be yarn statements which are run only when their appropriate expression evaluates to true. Flow control allows for blocks of statements to be scoped to their commands. A _block_ is a collection of statements that are scoped to a particular part of the flow control. +The block must be one or more statements. +These can be any statements allowed inside a node's [body](#body), including additional flow control statements. The _scope_ of a block is determined by the flow control commands and associates each block with a command. The if, elseif, and else commands all have a block associated with them. @@ -490,54 +502,65 @@ Both of the elseif commands expressions evaluate to true, so either ones attache However because one is above the other the block with `elseif-1-scope` dialogue inside would be the selected one. The implementing program should attempt to identify these scenarios however and alert the writer. -### Options +### Command Ambiguity + +Generic commands support all the same characters as the other commands, as such this creates an ambiguity between commands, with every more specialised command also being a valid [generic command](#generic-commands). +To resolve this ambiguity all other commands take priority over the generic command. +As an example `<>` is a valid generic command but also a valid [jump](#jump) command, it must be assumed to be a jump command. + +This gets more complex in that `<>` is not a a valid [set](#set) command but is a valid generic command. +Supporting overloading of commands in this manner is invalid and must not be allowed by the implementing program. +If a command begins with the keyword of another command the implementing program must assume the statement to be one of that command regardless of the validity of the rest of the command. +In the above `<>` example the implementing program must consider this is a malformed set and not a generic command. + +## Options _Options_ are the means by which Yarn can present dialogue choices to the game and much as with flow control are an element that spans multiple lines. Options are comprised of one or more option lines. -An _option line_ represents a single choice in an option, and are comprised of three parts: the keyword, the dialogue, the conditional in that order. +An _option line_ represents a single choice in an option, and are comprised of three parts: the keyword, the dialogue, the [conditional](#conditional) in that order. The _keyword_ is how the implementing program can tell a line is part of an option instead of dialogue and is the symbol `->`. There must be at least one whitespace between the keyword and the next element, the dialogue. -The _dialogue_ is a normal line of dialogue following all rules associated with that. +The _dialogue_ is a normal line of [dialogue](#dialogue-statement) following all rules associated with that. As the intention of options is to provide choice to the player when options are encountered the implementing program must halt further progress through the node until an option has been selected. Each option must be provided in the order they are written in the node. The mechanism by which an option line is chosen is unspecified. Only a single option line must be chosen. -#### Conditional +### Conditional The _conditional_ is a command which provides addtional data about the validity of the option. The intent of the conditional is to allow the writer to give the game more information about the option. -The conditional's syntax is identical to the if command and follows all rules there, but as it is not part of flow control must not have an accompanying endif or attached block. -The conditional must be an optional component of the option line. +The conditional's syntax is identical to the [if command](#if) and follows all rules there, but as it is not part of flow control must not have an accompanying [endif](#endif) or attached block. +The conditional must be an optional component of the line. As the conditional is optional any option line without a conditional must be assumed to be `true`. The implementing program must process the results of the conditional expression and provide the resulting boolean value to the other parts of the game that makes the selection. The implementing program must not restrict the selection of invalid options. It is the responsibility of the other components of the game to control how invalid options are to be handled. -#### Blocks +### Blocks -Much like with flow control options may have blocks of statements which are triggered should that option line be chosen. +Much like with flow control options may have [blocks of statements](#scope-and-blocks) which are triggered should that option line be chosen. Each option line may optionally have a block of statements associated with that option line. -Similar again to the flow control, if an option line is selected its associated block of must be processed by the implementing program +Similar again to the flow control, if an option line is selected its associated block of must be processed by the implementing program. If an option isn't chosen the associated block must not be processed. Unlike the flow control however there is no clear way to tell apart different blocks and options from other parts of the yarn, instead indentation is used to determine blocks and the end of the options. The rules for this must be followed: -The first option line in the options determines the base indentation for the options statement, this is determined by counting the number of whitespace elements before the `->` symbol. +The first option line in the options determines the base indentation for the options statement, this is determined by counting the number of [whitespace](#whitespace) elements before the `->` symbol. Any statements following the option line at a greater level of indentation counts as part of the block for that option line. -Any other options lines with the same indentation is considered a new option line and closes the block for that option. +Any other options lines with the same indentation is considered a new option line and closes the block for the preceeding option. These rules are repeated for each option line until a non-option line with the same, or less indentation than the base indentation is encountered which closes the block and the option statement entirely. -Options can be nested inside options. +Options can be nested inside option blocks. Not every option line needs to have blocks. The maximum number of supported indentation of options inside a block is unspecified. -##### Tabs vs Space +#### Tabs vs Space The choice to require either tabs or spaces over the other is unspecified. Tabs and spaces shouldn't be mixed. @@ -545,7 +568,7 @@ Should there be a need to convert between them the conversion rate must be the s The rate of conversion between tabs to spaces, and spaces to tabs, is unspecified. If there is a need to choose one, tabs should be preferred due to their improved accessibility over spaces. -#### Examples +### Examples ``` -> Hi @@ -613,13 +636,13 @@ The above is an example of an option with multiple option lines, conditionals, i ## Expressions -_Expressions_ are mathematical chains of variables, values, functions, expressions, and operators that produce a single value as output. +_Expressions_ are mathematical chains of values, variables, functions, expressions, and operators that produce a single value as output. Expressions are not a statement but are a component of various statements and must only be used as part of a statement, they cannot exist in isolation. -This means if you do want to show the result of an expression it will have to be wrapped inside an interpolated line. -For example a line that is just `$numberOfCoins + 1` while a valid line of dialogue is not going to give the result of the expression, but `{$numberOfCoins + 1}` is a valid line of dialogue that will present the result of that expression. +This means if you do want to show the result of an expression it will have to be wrapped inside an interpolated dialogue statement. +For example a line that is just `$numberOfCoins + 1` while a valid line of [dialogue](#dialogue-statement) is not going to give the result of the expression, but `{$numberOfCoins + 1}` is a valid line of dialogue that will present the result of that expression. -Expressions are mostly used to control the flow of the if statement, although they are also used as part of set statements, and in interpolated dialogue. +Expressions are mostly used to control the flow of the [if statement](#if), although they are also used as part of [set](#set) and [declare](#declare) statements, and in [interpolated dialogue](#interpolated-dialogue). ### Values @@ -631,38 +654,31 @@ Examples of values include `1`, `true`, `"General Kenobi"`. Yarn supports the following types and these must be supported by an implementing program: -- number -- boolean -- string +- [Number](#numbers) +- [String](#strings) +- [Boolean](#booleans) + +#### Numbers There are two types of numbers, *positive* and *negative*. -Positive Numbers are broken up into three components: the *integer part*, the *decimal seperator*, and the *fractional part*. +Positive Numbers are broken up into three components: the *integer part*, the *decimal separator*, and the *fractional part*. The integer part consists of one or more characters `0` - `9`. -The decimal seperator is optional and consists solely of the `.` symbol. -The fractional part is optional and consists of one or more chracters `0` - `9`. +The decimal separator is optional and consists solely of the `.` symbol. +The fractional part is optional and consists of one or more characters `0` - `9`. -The decimal seperator must not exists without a fractional part also existing. -The decimal seperator and fractional part must not exist without an integer part. +The decimal separator must not exists without a fractional part also existing. +The decimal separator and fractional part must not exist without an integer part. There must be no whitespace between any of the three parts of the number. -Negative numbers follow all the same rules as positive numbers but begin with the *negation indicator* `-`. +Negative numbers follow all the same rules as positive numbers but begin with the *negation indicator* symbol `-`. The negation indicator must go hard up against the integer part, there must not be whitespace between them. The precision, storage, and form of the number internally by the implementing program is unspecified, however it must support decimals. As an example of this in C# the `Decimal`, `Complex`, and `float` formats are valid (though some make more sense than others) but `int` is not. If a number is beyond the precision supported by the implementing program, the program must report this as an error. -Strings must be capable of holding UTF-8 values as this is what the yarn language is written in, but the internals of this is unspecified provided all valid UTF-8 characters are supported. -Strings in expressions must be encapsulated between `"` and `"` symbols. - -Booleans must be capable of representing the boolean logic values of `true` and `false`, however the specific implementation is undefined. -Booleans must not be exposed as `1` and `0` to expressions even if they are represented this way internally by the implementing program. -Booleans in expressions must be written as `true` for true and `false` for false. - -Additional types supported are unspecified but should not be used. - -#### Numeric Examples +##### Examples The following are examples of valid numbers in Yarn: @@ -688,14 +704,31 @@ The second is invalid because it has a decimal seperator but doesn't have a frac The third is invalid because it has a space between the negation indicator and the integer part. The forth is invalid because it has a space between the decimal seperator and the fractional part. +#### Strings + +Strings are an ordered collection of characters and must be capable of holding [UTF-8 characters](https://en.wikipedia.org/wiki/UTF-8) as this is what the yarn language is written in, but the internals of this is unspecified provided all valid UTF-8 strings are supported. +The minimum and maximum lengths of strings are unspecified but if the implementing program cannot support a string it must present this as an error. +Strings in expressions must be encapsulated between `"` and `"` symbols. + +#### Booleans + +Booleans must be capable of representing the boolean logic values of `true` and `false`, however the specific implementation is undefined. +Booleans must not be exposed as `1` and `0` to expressions even if they are represented this way internally by the implementing program. +Booleans in expressions must be written as `true` for true and `false` for false. + +#### Additional Types + +Additional types supported by an implementing program are unspecified but should not be used. + ### Variables _Variables_ are a means of associating a value with a name so that it can be more easily used and changed in multiple places. -Variables can only be used inside of expressions. +Variables must only be used inside of expressions. +A variable encountered outside of an expression must not be considered by the implementing program to be a variable. #### Naming and scope -All variables are a variant on identifiers. +All variables are a variant on [identifiers](#identifiers). Variables are an identifier that start with a `$` symbol and otherwise follow all other identifier rules. The minimum and maximum length of a variable name is unspecified but must be at least one character after the `$` symbol. @@ -712,8 +745,8 @@ Yarn is a statically typed language, in the context of Yarn this means variables Once a variable has its type determined either by declaration or inference it cannot change. The implementing program must not allow variables to hold values of types different from its own. -Due to the nature of elements of Yarn being outside of the control of Yarn, notably functions, its possible for this requirement to be breached due to no fault of the implementing program or the Yarn script. -However In these circumstances the implementing program must generate an error. +Due to the nature of elements of Yarn being outside of the control of Yarn, notably functions, its possible for this requirement to be breached due to no fault of the implementing program or the Yarn as written by the author. +However in these circumstances the implementing program must generate an error. ### Operations @@ -744,8 +777,8 @@ Some of these have multiple operators, these must work identically and exist for The amount of whitespace between operands and operators in binary operations is unspecified. -There are two unary operations that have only a single operand. -The operator always goes to the left side of the operand and the must be no whitespace between the operator and operand. +There are two unary operations, that is operations that have only a single operand. +The operator always goes to the left side of the operand and there must be no whitespace between the operator and operand. The unary operations are: - minus: `-` @@ -757,7 +790,9 @@ Parentheses must be treated as if they are a single operand in other operations. Parentheses start with the open bracket symbol `(` and can have any expression inside of them before being closed with the closing bracket symbol `)`. `2 * (3 + $coins)` is an example of an expression with a parentheses operation, in this case the `3 + $coins` component must be resolved into a value before being able to be multiplied by two. -The `+` operator when operating on strings is not addition in the mathematical sense but concatenation. +The `+` operator when operating on strings represesnt concatenation, the merging of two strings by appending the r-value string to the end of the l-value string. +When operating on numbers the `+` operator is the normal addition operator. +All other operators act according to their already existing arithmetic or logical operations. #### Supported types in operations @@ -816,7 +851,7 @@ Functions must return a value. Functions are comprised of a name, parentheses, and parameters. -The _function name_ is an identifier. +The function _name_ is an [identifier](#identifiers). The minimum and maximum length of function names is unspecified. The parentheses go after the function name and there must be no whitespace between the opening parentheses `(` and the function name. @@ -826,7 +861,7 @@ _Parameters_ go in between the opening `(` and closing `)` parentheses. Parameters must be expressions, functions, values, or variables. Functions can have multiple parameters, these must be separated by the comma `,` symbol. -Whitespace between parameters and the separator is undefined. hmm this allows for newlines is that ok? +Whitespace between parameters and the separator is undefined but newlines characters are must not be allowed. The maximum and minimum number of allowed parameters a function can have is undefined. Examples of functions include the following; @@ -840,8 +875,11 @@ rad2Deg(1.5707963268) #### Handling The handling of functions by the implementing program is unspecified, however the output type of a function must always return the same type of value between calls at runtime. -The Yarn language makes no promises as to the order in which, or number of times an implementing program may call functions. +Yarn functions are assumed to be non-blocking and effectively instantly returning, the implementing program should adhere to this. +If given the same input parameters multiple invocations of the same functions should return the same value each time. The implementing program should allow external parts of the game to provide the return value of the function. -If given the same input parameters multiple invocations of the same functions should return the same value each time. -In general, and while not a specific requirement, implementing programs should err on the side of treating functions in Yarn as if they are [pure functions](https://en.wikipedia.org/wiki/Pure_function). +The implementing program must present and process the parameters to whatever handles the function in the same order as they are presented in the Yarn. + +Yarn makes no promises as to the order in which, or number of times an implementing program may call functions, the results of function calls may be cached or called ahead of time. +In general, and while not a specific requirement, implementing programs and writers should err on the side of treating functions in Yarn as if they are [pure functions](https://en.wikipedia.org/wiki/Pure_function). From da20763fe5ac583e4ea3b510cef2708ad02d4946 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Fri, 17 Sep 2021 15:46:18 +1000 Subject: [PATCH 18/39] Clarified variable scope and duplicate tags --- Documentation/Yarn-Spec.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index b77410631..1dd851f5a 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -177,6 +177,7 @@ The program should flag this as an error. #### Duplicate Tags Duplicate header tags within a node is invalid. +A duplicate tag is a duplicate if it has the same tag name as another. The implementing program must either throw an error when encountering a duplicate tag or ignore all but the first instance of a tag. If the implementing program is ignoring later duplicates then the user should still be informed as the existence of duplicate tags. @@ -735,7 +736,7 @@ The minimum and maximum length of a variable name is unspecified but must be at Variable names must be unique throughout their scope. The _scope_ of the variable is what defines for how long a variable exists. Once a variable leaves its scope it is no longer valid and implementing programs must not support accessing variables outside of their scope. -The scope of variables is undefined, however implementing programs should err on the side of variables being global in scope. +The scope of a variable must be global across the project. `$name` is an example of a variable name, `$𐃩` is another example of a variable name. From a203a74093e91774885b10d27ba49f0f921f60d7 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Fri, 17 Sep 2021 15:48:32 +1000 Subject: [PATCH 19/39] capitalised Yarn --- Documentation/Yarn-Spec.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 1dd851f5a..0d9dca378 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -27,10 +27,10 @@ This is because despite Yarn and Yarn Spinner being separate elements attempting ### Coverage -This document covers the elements of a Yarn script that are required to be considered a valid yarn script as well as the rules necessary for an implementing program to be able to conform to this spec. +This document covers the elements of a Yarn script that are required to be considered a valid Yarn script as well as the rules necessary for an implementing program to be able to conform to this specification. -An *implementing program* is a program that accepts yarn files as inputs and understands them based on the rules in this document. -This document does not cover how a yarn file is to be transformed or handled internally by an implementing program. +An *implementing program* is a program that accepts Yarn files as inputs and understands them based on the rules in this document. +This document does not cover how a Yarn file is to be transformed or handled internally by an implementing program. This document does note when behaviours are *unspecified*. The implementing program may choose how to handle any unspecified behaviour, often unspecified behaviours have no good solution and should result in an error. @@ -80,13 +80,13 @@ File extension should be `.yarn`. ### Project -The yarn *project* is all yarn files that are intended to be associated with one another. +The Yarn *project* is all Yarn files that are intended to be associated with one another. While there is nothing stopping a writer from placing all nodes into one big file (or even making one giant node) it is common to break them up over multiple files. The project is all of these files collected and processed by the implementing program together. ### Lines -The *line* is the common unit that comprises all elements in a yarn file. +The *line* is the common unit that comprises all elements in a Yarn file. A line is a series of characters terminated by the *new line* symbol. The new line symbol should be the `\n` character. The new line must be the same throughout the project regardless of the chosen new line symbol. @@ -112,7 +112,7 @@ A comment is a line that starts with the `//` symbol. All text from the start of the comment to the end of the line must be ignored. A comment starting in the middle of another line ends that line at the point the `//` symbol is encountered. That line is assumed to have finished at that point as if the comment was not there. -Comments must not impact the rest of the lines or have any impact on the resulting yarn program. +Comments must not impact the rest of the lines or have any impact on the resulting Yarn program. ### Identifiers @@ -125,7 +125,7 @@ The minimum and maximum length of identifiers is unspecified. ## Yarn Structure -The basic structure of a yarn file is zero or more file tags and one or more yarn nodes. +The basic structure of a Yarn file is zero or more file tags and one or more Yarn nodes. ### File Tags @@ -136,8 +136,8 @@ File tags must have the `#` symbol at the start of them and then contain all tex ### Nodes -A *node* is the single story element of a yarn file. -Nodes are the story structural building blocks for yarn. +A *node* is the single story element of a Yarn file. +Nodes are the story structural building blocks for Yarn. Nodes are designed to contain pieces of a story and then have these story pieces linked together. This is not a requirement, everything could be done in a single node, this would just be unwieldy. A node must be comprised of a single header and a single body in that order. @@ -212,7 +212,7 @@ Multiple hashtags can exist on a single line. ## Dialogue Statement -A dialogue statement is a statement that represents a single line of text in the yarn body. +A dialogue statement is a statement that represents a single line of text in the Yarn body. In most cases dialogue will be the bulk of the content of a node's body. Dialogue statements can be [interpolated](#interpolated-dialogue) dialogue or [raw](#raw-dialogue) dialogue. A dialogue statement can contain any characters except for the `#` character. @@ -245,10 +245,10 @@ Escaping text must be supported in both normal and interpolated dialogue lines a ### Statement Ambiguity Because the dialogue statement allows a great deal of flexibility in allowed characters every other statement inside the body could be considered to also be a valid dialogue statement. -This creates an ambiguity when parsing a yarn file, as such the dialogue statement must be considered the lowest priority by the implementing program. +This creates an ambiguity when parsing a Yarn file, as such the dialogue statement must be considered the lowest priority by the implementing program. For example `<>` could be read as a [command](#commands) or a dialogue statement, it must be considered a command by the implementing program. -This does create a potential conflict between writer intent and yarn's requirements, however it is unavoidable. +This does create a potential conflict between writer intent and Yarn's requirements, however it is unavoidable. To continue the earlier example if the writer intended `<>` to be a dialogue statement they would have to escape the reserved characters first, so `\<>` which would present as `<>` to the game. ## Commands @@ -269,10 +269,10 @@ Additional required command are unspecified. ### Generic Commands -_Generic Commands_ are commands for sending messages from the yarn to the rest of the program. +_Generic Commands_ are commands for sending messages from the Yarn to the rest of the program. Unlike the other commands generic commands don't impact the dialogue. They can be thought of as lines of dialogue that aren't to be shown in the game. -Implementing programs must not modify the flow of the yarn based on the command. +Implementing programs must not modify the flow of the Yarn based on the command. Generic commands can have any text except for the `#`, `{`, or `}` symbols inside of them. @@ -288,7 +288,7 @@ are examples of generic commands. ### Jump -The _jump_ command is how a yarn program can move from one [node](#nodes) to another. +The _jump_ command is how a Yarn program can move from one [node](#nodes) to another. The jump has two components: the keyword and the destination and these are separated by one or more whitespace. The _keyword_ is the text `jump` and comes first in the command. @@ -459,7 +459,7 @@ The endif exists to allow the implementing program know when the scope of the ot #### Scope and Blocks -For the flow control to be useful there needs to be yarn statements which are run only when their appropriate expression evaluates to true. +For the flow control to be useful there needs to be Yarn statements which are run only when their appropriate expression evaluates to true. Flow control allows for blocks of statements to be scoped to their commands. A _block_ is a collection of statements that are scoped to a particular part of the flow control. The block must be one or more statements. @@ -475,7 +475,7 @@ While it is common for writers to indent their blocks relative to their scope it #### Handling The implementing program must process all statements within the active blocks scope. -The _active block_ is the block of yarn who's command expression evaluates to `true`. +The _active block_ is the block of Yarn who's command expression evaluates to `true`. The block associated with the else command, if present, must only be determined as the active block if all other blocks expressions evaluate to false. An implementing program must not process any statements inside a block that is not the active block. @@ -548,7 +548,7 @@ Each option line may optionally have a block of statements associated with that Similar again to the flow control, if an option line is selected its associated block of must be processed by the implementing program. If an option isn't chosen the associated block must not be processed. -Unlike the flow control however there is no clear way to tell apart different blocks and options from other parts of the yarn, instead indentation is used to determine blocks and the end of the options. +Unlike the flow control however there is no clear way to tell apart different blocks and options from other parts of the Yarn, instead indentation is used to determine blocks and the end of the options. The rules for this must be followed: The first option line in the options determines the base indentation for the options statement, this is determined by counting the number of [whitespace](#whitespace) elements before the `->` symbol. @@ -707,7 +707,7 @@ The forth is invalid because it has a space between the decimal seperator and th #### Strings -Strings are an ordered collection of characters and must be capable of holding [UTF-8 characters](https://en.wikipedia.org/wiki/UTF-8) as this is what the yarn language is written in, but the internals of this is unspecified provided all valid UTF-8 strings are supported. +Strings are an ordered collection of characters and must be capable of holding [UTF-8 characters](https://en.wikipedia.org/wiki/UTF-8) as this is what the Yarn language is written in, but the internals of this is unspecified provided all valid UTF-8 strings are supported. The minimum and maximum lengths of strings are unspecified but if the implementing program cannot support a string it must present this as an error. Strings in expressions must be encapsulated between `"` and `"` symbols. From 117a895644d5207053affbe93ad6e5bfeaff069e Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Fri, 24 Sep 2021 17:00:21 +1000 Subject: [PATCH 20/39] First pass at adding railroad diagrams. Loads are borked though --- Documentation/Yarn-Spec.md | 74 +++ Documentation/railroads/IDENTIFIER.svg | 4 + .../railroads/IDENTIFIER_CHARACTER.svg | 4 + Documentation/railroads/IDENTIFIER_HEAD.svg | 4 + Documentation/railroads/body.svg | 4 + Documentation/railroads/declare.svg | 4 + Documentation/railroads/else.svg | 4 + Documentation/railroads/elseif.svg | 4 + Documentation/railroads/endif.svg | 4 + Documentation/railroads/expression.svg | 4 + Documentation/railroads/file_tag.svg | 4 + Documentation/railroads/flow_control.svg | 4 + Documentation/railroads/function.svg | 4 + Documentation/railroads/generic_command.svg | 483 +++++++++++++++++ Documentation/railroads/hashtag.svg | 4 + Documentation/railroads/header.svg | 4 + Documentation/railroads/header_tag.svg | 4 + Documentation/railroads/if.svg | 4 + Documentation/railroads/jump.svg | 4 + Documentation/railroads/light.css | 484 ++++++++++++++++++ Documentation/railroads/node.svg | 4 + Documentation/railroads/option.svg | 4 + Documentation/railroads/option_block.svg | 4 + Documentation/railroads/options.svg | 4 + Documentation/railroads/set.svg | 4 + Documentation/railroads/statement.svg | 4 + Documentation/railroads/stop.svg | 4 + Documentation/railroads/title_tag.svg | 4 + Documentation/railroads/yarn_file.svg | 4 + 29 files changed, 1145 insertions(+) create mode 100644 Documentation/railroads/IDENTIFIER.svg create mode 100644 Documentation/railroads/IDENTIFIER_CHARACTER.svg create mode 100644 Documentation/railroads/IDENTIFIER_HEAD.svg create mode 100644 Documentation/railroads/body.svg create mode 100644 Documentation/railroads/declare.svg create mode 100644 Documentation/railroads/else.svg create mode 100644 Documentation/railroads/elseif.svg create mode 100644 Documentation/railroads/endif.svg create mode 100644 Documentation/railroads/expression.svg create mode 100644 Documentation/railroads/file_tag.svg create mode 100644 Documentation/railroads/flow_control.svg create mode 100644 Documentation/railroads/function.svg create mode 100644 Documentation/railroads/generic_command.svg create mode 100644 Documentation/railroads/hashtag.svg create mode 100644 Documentation/railroads/header.svg create mode 100644 Documentation/railroads/header_tag.svg create mode 100644 Documentation/railroads/if.svg create mode 100644 Documentation/railroads/jump.svg create mode 100644 Documentation/railroads/light.css create mode 100644 Documentation/railroads/node.svg create mode 100644 Documentation/railroads/option.svg create mode 100644 Documentation/railroads/option_block.svg create mode 100644 Documentation/railroads/options.svg create mode 100644 Documentation/railroads/set.svg create mode 100644 Documentation/railroads/statement.svg create mode 100644 Documentation/railroads/stop.svg create mode 100644 Documentation/railroads/title_tag.svg create mode 100644 Documentation/railroads/yarn_file.svg diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 0d9dca378..60824f7c0 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -65,6 +65,28 @@ The precise handling of errors will be specific to the implementing program but Dates, spelling, and numbers are to be in Australian English. +#### Railroad Diagrams + +At various points [railroad diagrams](https://en.wikipedia.org/wiki/Syntax_diagram) are included with the rules. +These provide a visual means of understanding the rules presented here to aid in parsing Yarn. + +The diagrams are to be read left to right, following the lines until you hit the end of the rule. +Each time you encounter an element in the path that element must be represented in the raw text of the Yarn file for the rule to be valid. +White elements are more complex rules, grey elements are literals either by name for convenience or if they are encapsulated inside single quotes `'` they are a string literal as described above. +Lines may loop back or skip over elements, and every path through the diagram decribes a valid version of the rule. + +The diagrams at various stages use ranges to represent all potential values within that range. +Common uses of this include being able to capture the digits `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`, if you were required to type them out in the diagram each time it would get onerous, so we represent this with a range using square brackets `[` and `]`. +The character on the left side of the range represents the start and the right side represent the end of the range, so the digits would be represented as `[0-9]`. +Hardcoded unicode values are also shown in the diagrams, these represent elements that are either difficult to show visually or for easier capture in ranges. +Unicode values are represented in these diagrams with a `\u` followed by a multiple digit hexadecimal value. +The value of these digits map directly to a unicode code point, for example `\u00A8` represents the `¨` or DIAERESIS symbol. + +It is important to note that railroad diagrams provide the rules for parsing Yarn, and only for parsing. +The side effect of this is certain rules are not able to be easily captured in parser rules alone. +As an example of this the railroad diagram for headers shows that there must be one or more header tags, but doesn't capture that one of those tags must be the title. +Railroad diagrams capture the syntactic but not semantic rules. + ### Modifying This Specification Once this specification is complete it is set and unchanging. @@ -123,10 +145,16 @@ After the first character digits, a period (`.`), and combining Unicode characte The `$` symbol must not be part of an identifier. The minimum and maximum length of identifiers is unspecified. +![](railroads/IDENTIFIER.svg) +![](railroads/IDENTIFIER_HEAD.svg) +![](railroads/IDENTIFIER_CHARACTER.svg) + ## Yarn Structure The basic structure of a Yarn file is zero or more file tags and one or more Yarn nodes. +![](railroads/yarn_file.svg) + ### File Tags _File tags_ are file level metadata that is relevant for all nodes in the file. @@ -134,6 +162,8 @@ A common use for file tags is for versioning the file. File tags must go at the start of a file before any nodes begin. File tags must have the `#` symbol at the start of them and then contain all text up until the end of the line. +![](railroads/file_tag.svg) + ### Nodes A *node* is the single story element of a Yarn file. @@ -142,12 +172,16 @@ Nodes are designed to contain pieces of a story and then have these story pieces This is not a requirement, everything could be done in a single node, this would just be unwieldy. A node must be comprised of a single header and a single body in that order. +![](railroads/node.svg) + ### Headers A *header* is comprised of one or more header tags. The header is finished when encountering a line that only contains the *header delimiter* `---`. After encountering the header delimiter the body of the node is entered. +![](railroads/header.svg) + #### Header Tags A *header tag* is a line broken up into three components, in order; the tag name, the separator, and the tag text. @@ -163,6 +197,8 @@ Every node must have a title tag. Required or banned header tags beyond title are unspecified. The order of header tags is unspecified. +![](railroads/header_tag.svg) + #### Title Tag The *title tag* is a specific header tag that uniquely identifies the node. @@ -174,6 +210,8 @@ The tag text must follow the rules of [identifiers](#identifiers). The behaviour of the program when a title tag's text is not unique across the project is unspecified. The program should flag this as an error. +![](railroads/title_tag.svg) + #### Duplicate Tags Duplicate header tags within a node is invalid. @@ -193,10 +231,14 @@ A *statement* is a line that is one of the following: A statement may have optional [hashtags](#hashtags). A body must have at least one statement. +![](railroads/statement.svg) + The body ends when encountering a line that consists entirely of the *body delimter* `===`. The body delimiter ends both the current node and the body of that node. The end of file must not be used in place of a body delimiter. +![](railroads/body.svg) + #### Hashtags *Hashtags* are metadata associated with the statement they are a part of. @@ -210,6 +252,8 @@ Multiple hashtags can exist on a single line. `#lineID:a10be2 #return` is an example of multiple hashtags on a line. `General Kenobi: Why hello there #lineID:a10be2 #return` is an example of a line of dialogue with multiple hashtags. +![](railroads/hashtag.svg) + ## Dialogue Statement A dialogue statement is a statement that represents a single line of text in the Yarn body. @@ -286,6 +330,8 @@ Any expressions inside of a generic command without being encapsulated must be i ``` are examples of generic commands. +![](railroads/generic_command.svg) + ### Jump The _jump_ command is how a Yarn program can move from one [node](#nodes) to another. @@ -305,6 +351,8 @@ From that point on the destination nodes contents must instead be run. `<>` is an example of a jump command, `<>` is an example of a jump command using an expression to determine the destination node. +![](railroads/jump.svg) + ### Stop The _stop_ command is for halting all progress on the [project](#project). @@ -314,6 +362,8 @@ The stop command should reset any [variable](#variables) or internal state back `<>` is the example of the stop command. +![](railroads/stop.svg) + ### Set The _set_ command allows [variables](#variables) to be given [values](#values). @@ -334,6 +384,8 @@ The following is an example of two set commands: The set command must follow all the rules for [variable naming](#naming-and-scope) and expressions. The set command must not allow setting a variable to an expression whose value is different from the [type](#supported-types) of that variable. +![](railroads/set.svg) + ### Declare [Variables](#variables) in Yarn should be declared to let the implementing program know the [type](#supported-types) of values they hold. @@ -361,6 +413,8 @@ The implementing program must not allow the variable declared to ever have a val If this does occur the implementing program must flag this as an error. The handling of encountering variables which have not been declared is unspecified but should generate an error. +![](railroads/declare.svg) + #### Explicit Typing It is assumed that most of the time a variable's type will be determined implicitly via the initial expression, however the type can also be explicitly set. @@ -413,6 +467,8 @@ If neither of those are the case then the `else-scope` line will be shown. <> ``` +![](railroads/flow_control.svg) + #### if The _if_ command is the opening command of flow control and is broken up into two parts, the keyword and the expression and must be in that order. @@ -422,6 +478,8 @@ The expression must resolve to a boolean. `< 1>>` is an example of an if command, `<>` is an example of an invalid if, it is invalid because the expression does not resolve to a boolean. +![](railroads/if.svg) + #### elseif The _elseif_ command is an optional component of flow control and allows for additional flow to be expressed. @@ -437,6 +495,8 @@ The minimum mumber of required elseif commands must be zero. The maximum number of allowed elseif commands in a flow control statement is unspecified but must be greater than zero. An elseif command must not exist without an if command and must go after the if command. +![](railroads/elseif.svg) + #### else The _else_ command is an optional component of flow control and allows for additional flow to be expressed. @@ -450,6 +510,8 @@ The else's block will run only if the `if` and any `elseif` components all evalu The example of the else command is `<>`. +![](railroads/else.svg) + #### endif The _endif_ command is the final element of flow control and is comprised solely of the keyword `endif`. @@ -457,6 +519,8 @@ The endif must be present whenever there is flow control and must go after the i The endif exists to allow the implementing program know when the scope of the other elements in the flow control has ended. `<>` is the example of the endif command. +![](railroads/endif.svg) + #### Scope and Blocks For the flow control to be useful there needs to be Yarn statements which are run only when their appropriate expression evaluates to true. @@ -520,6 +584,8 @@ _Options_ are the means by which Yarn can present dialogue choices to the game a Options are comprised of one or more option lines. An _option line_ represents a single choice in an option, and are comprised of three parts: the keyword, the dialogue, the [conditional](#conditional) in that order. +![](railroads/option.svg) + The _keyword_ is how the implementing program can tell a line is part of an option instead of dialogue and is the symbol `->`. There must be at least one whitespace between the keyword and the next element, the dialogue. The _dialogue_ is a normal line of [dialogue](#dialogue-statement) following all rules associated with that. @@ -529,6 +595,8 @@ Each option must be provided in the order they are written in the node. The mechanism by which an option line is chosen is unspecified. Only a single option line must be chosen. +![](railroads/options.svg) + ### Conditional The _conditional_ is a command which provides addtional data about the validity of the option. @@ -561,6 +629,8 @@ Options can be nested inside option blocks. Not every option line needs to have blocks. The maximum number of supported indentation of options inside a block is unspecified. +![](railroads/option_block.svg) + #### Tabs vs Space The choice to require either tabs or spaces over the other is unspecified. @@ -645,6 +715,8 @@ For example a line that is just `$numberOfCoins + 1` while a valid line of [dial Expressions are mostly used to control the flow of the [if statement](#if), although they are also used as part of [set](#set) and [declare](#declare) statements, and in [interpolated dialogue](#interpolated-dialogue). +![](railroads/expression.svg) + ### Values A _Value_ is a single concrete form of one of the supported types. @@ -848,6 +920,8 @@ _Functions_ are an alternate way of getting values into expressions. Functions are intended to be used to allow more complex code be bundled and called in a different environment, such as in the game itself. Functions must return a value. +![](railroads/function.svg) + #### Structure Functions are comprised of a name, parentheses, and parameters. diff --git a/Documentation/railroads/IDENTIFIER.svg b/Documentation/railroads/IDENTIFIER.svg new file mode 100644 index 000000000..633a8639b --- /dev/null +++ b/Documentation/railroads/IDENTIFIER.svg @@ -0,0 +1,4 @@ + + + +IDENTIFIER HEADIDENTIFIER CHARACTER \ No newline at end of file diff --git a/Documentation/railroads/IDENTIFIER_CHARACTER.svg b/Documentation/railroads/IDENTIFIER_CHARACTER.svg new file mode 100644 index 000000000..5d921897d --- /dev/null +++ b/Documentation/railroads/IDENTIFIER_CHARACTER.svg @@ -0,0 +1,4 @@ + + + +[0-9][\u0300-\u036F][\u1DC0-\u1DFF][\u20D0-\u20FF][\uFE20-\uFE2F]IDENTIFIER_HEAD'.' \ No newline at end of file diff --git a/Documentation/railroads/IDENTIFIER_HEAD.svg b/Documentation/railroads/IDENTIFIER_HEAD.svg new file mode 100644 index 000000000..844d288f5 --- /dev/null +++ b/Documentation/railroads/IDENTIFIER_HEAD.svg @@ -0,0 +1,4 @@ + + + +[a-zA-Z_]'\u00A8''\u00AA''\u00AD''\u00AF'[\u00B2-\u00B5][\u00B7-\u00BA][\u00BC-\u00BE][\u00C0-\u00D6][\u00D8-\u00F6][\u00F8-\u00FF][\u0100-\u02FF][\u0370-\u167F][\u1681-\u180D][\u180F-\u1DBF][\u1E00-\u1FFF][\u200B-\u200D][\u202A-\u202E][\u203F-\u2040]'\u2054'[\u2060-\u206F][\u2070-\u20CF][\u2100-\u218F][\u2460-\u24FF][\u2776-\u2793][\u2C00-\u2DFF][\u2E80-\u2FFF][\u3004-\u3007][\u3021-\u302F][\u3031-\u303F][\u3040-\uD7FF][\uF900-\uFD3D][\uFD40-\uFDCF][\uFDF0-\uFE1F][\uFE30-\uFE44][\uFE47-\uFFFD][\u10000-\u1FFFD][\u20000-\u2FFFD][\u30000-\u3FFFD][\u40000-\u4FFFD][\u50000-\u5FFFD][\u60000-\u6FFFD][\u70000-\u7FFFD][\u80000-\u8FFFD][\u90000-\u9FFFD][\uA0000-\uAFFFD][\uB0000-\uBFFFD][\uC0000-\uCFFFD][\uD0000-\uDFFFD][\uE0000-\uEFFFD] \ No newline at end of file diff --git a/Documentation/railroads/body.svg b/Documentation/railroads/body.svg new file mode 100644 index 000000000..07f045b67 --- /dev/null +++ b/Documentation/railroads/body.svg @@ -0,0 +1,4 @@ + + + +statement \ No newline at end of file diff --git a/Documentation/railroads/declare.svg b/Documentation/railroads/declare.svg new file mode 100644 index 000000000..f5d0d78be --- /dev/null +++ b/Documentation/railroads/declare.svg @@ -0,0 +1,4 @@ + + + +'<<''declare'variable'to''='expression'as''String''Number''Bool''>>' \ No newline at end of file diff --git a/Documentation/railroads/else.svg b/Documentation/railroads/else.svg new file mode 100644 index 000000000..8de96ed8d --- /dev/null +++ b/Documentation/railroads/else.svg @@ -0,0 +1,4 @@ + + + +'<<''else''>>' \ No newline at end of file diff --git a/Documentation/railroads/elseif.svg b/Documentation/railroads/elseif.svg new file mode 100644 index 000000000..26bc601af --- /dev/null +++ b/Documentation/railroads/elseif.svg @@ -0,0 +1,4 @@ + + + +'<<''elseif'expression'>>' \ No newline at end of file diff --git a/Documentation/railroads/endif.svg b/Documentation/railroads/endif.svg new file mode 100644 index 000000000..7f90d056f --- /dev/null +++ b/Documentation/railroads/endif.svg @@ -0,0 +1,4 @@ + + + +'<<''endif''>>' \ No newline at end of file diff --git a/Documentation/railroads/expression.svg b/Documentation/railroads/expression.svg new file mode 100644 index 000000000..79ff446d1 --- /dev/null +++ b/Documentation/railroads/expression.svg @@ -0,0 +1,4 @@ + + + +'('expression')''-'expression'!'expressionexpression'*''/''%'expressionexpression'+''-'expressionexpression'<''>''<=''>='expressionexpression'==''!='expressionexpression'and''&&''or''||''xor''^'expressionfunctionliteralvariable \ No newline at end of file diff --git a/Documentation/railroads/file_tag.svg b/Documentation/railroads/file_tag.svg new file mode 100644 index 000000000..2c3cb995a --- /dev/null +++ b/Documentation/railroads/file_tag.svg @@ -0,0 +1,4 @@ + + + +'#'any tokenNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/flow_control.svg b/Documentation/railroads/flow_control.svg new file mode 100644 index 000000000..6dcf071f0 --- /dev/null +++ b/Documentation/railroads/flow_control.svg @@ -0,0 +1,4 @@ + + + +ifNEWLINEstatementelseifNEWLINEstatementelseNEWLINEstatementendif \ No newline at end of file diff --git a/Documentation/railroads/function.svg b/Documentation/railroads/function.svg new file mode 100644 index 000000000..042c2697f --- /dev/null +++ b/Documentation/railroads/function.svg @@ -0,0 +1,4 @@ + + + +IDENTIFIER'('expression','expression')' \ No newline at end of file diff --git a/Documentation/railroads/generic_command.svg b/Documentation/railroads/generic_command.svg new file mode 100644 index 000000000..3d98b3eec --- /dev/null +++ b/Documentation/railroads/generic_command.svg @@ -0,0 +1,483 @@ + + + + +'<<'TEXTinterpolated_text'>>' \ No newline at end of file diff --git a/Documentation/railroads/hashtag.svg b/Documentation/railroads/hashtag.svg new file mode 100644 index 000000000..a3124b621 --- /dev/null +++ b/Documentation/railroads/hashtag.svg @@ -0,0 +1,4 @@ + + + +'#'not'#'NEWLINE \ No newline at end of file diff --git a/Documentation/railroads/header.svg b/Documentation/railroads/header.svg new file mode 100644 index 000000000..d3a3f6cdd --- /dev/null +++ b/Documentation/railroads/header.svg @@ -0,0 +1,4 @@ + + + +headertag \ No newline at end of file diff --git a/Documentation/railroads/header_tag.svg b/Documentation/railroads/header_tag.svg new file mode 100644 index 000000000..974ee16c0 --- /dev/null +++ b/Documentation/railroads/header_tag.svg @@ -0,0 +1,4 @@ + + + +IDENTIFIER':'TEXTNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/if.svg b/Documentation/railroads/if.svg new file mode 100644 index 000000000..f5584a278 --- /dev/null +++ b/Documentation/railroads/if.svg @@ -0,0 +1,4 @@ + + + +'<<''if'expression'>>' \ No newline at end of file diff --git a/Documentation/railroads/jump.svg b/Documentation/railroads/jump.svg new file mode 100644 index 000000000..d61298acb --- /dev/null +++ b/Documentation/railroads/jump.svg @@ -0,0 +1,4 @@ + + + +'<<''jump'IDENTIFIERinterpolated_text'>>' \ No newline at end of file diff --git a/Documentation/railroads/light.css b/Documentation/railroads/light.css new file mode 100644 index 000000000..2d1b00c36 --- /dev/null +++ b/Documentation/railroads/light.css @@ -0,0 +1,484 @@ +/* + * This file contains all default CSS rules for the light vscode them, used for various diagrams and graphs. + * Use the "antlr4.customcss" setting in vscode to specify your own file, if you like to override some rules. + * + * Most of the appearance is defined here, while only some adjustments for the dark theme exist in dark.css. + * This style sheet is also used for exported svg files. + */ + + body { + padding-left: 20px; +} + +svg { + background: rgba(0, 0, 0, 0.03); +} + + +/* ATN graphs */ + +.transition { + fill: none; + stroke: #AAA; + stroke-width: 2px; +} + +.marker { + fill: #999; + stroke: none; +} + +.stateLabel { + font: bold 11pt "Helvetica Neue", Arial, sans-serif; + fill: white; + text-anchor: middle; + pointer-events: none; +} + +.stateTypeLabel { + font: bold 7pt monospace; + fill: #EEE; + text-anchor: middle; + pointer-events: none; +} + +.linkLabel { + font: bold 9pt "Helvetica Neue", Arial, sans-serif; + fill: #606060; + text-anchor: middle; + pointer-events: none; +} + +.state { + stroke: #505050; + stroke-width: 3px; + cursor: move; + pointer-events: all; + /*filter: url(#black-glow);*/ +} + +.state.BASIC { + fill: #AAA; +} + +.state.START { + fill: #36bde0; +} + +.state.BSTART { + fill: #f39900; +} + +.state.PBSTART { + fill: #98c000; +} + +.state.SBSTART { + fill: #607dbd; +} + +.state.TSTART { + fill: #ffd300; +} + +.state.STOP { + fill: #2baa5b; +} + +.state.BEND { + fill: #c2c269; +} + +.state.SLBACK { + fill: #608b4e; +} + +.state.SLENTRY { + fill: #a260cb; +} + +.state.PLBACK { + fill: #517979; +} + +.state.LEND { + fill: #9b90c3; +} + +.state.RULE { + fill: #b73645; +} + +.state.RULE.recursive { + fill: #36bde0; +} + + +/* Railroad diagrams */ + +svg.railroad-diagram path { + /* The connection lines. */ + stroke-width: 2; + stroke: darkgray; + fill: rgba(0, 0, 0, 0); +} + +svg.railroad-diagram text { + /* All text except comments. */ + font: bold 12px Hack, "Source Code Pro", monospace; + text-anchor: middle; + fill: #404040; + /* Use fill instead of color for svg text. */ +} + +svg.railroad-diagram text.comment { + /* Comment text */ + font: italic 10px Hack, "Source Code Pro", monospace; + fill: #404040; +} + +svg.railroad-diagram g.non-terminal rect { + /* The non-terminal boxes. */ + stroke-width: 2; + stroke: #404040; + fill: rgba(255, 255, 255, 1); +} + +svg.railroad-diagram g.terminal rect { + /* The terminal boxes. */ + stroke-width: 2; + stroke: #404040; + fill: rgba(0, 0, 0, 0.1); +} + +svg.railroad-diagram text.diagram-text { + /* Multiple choice text, not working atm. */ + font-size: 12px Hack, "Source Code Pro", monospace; + fill: red; +} + +svg.railroad-diagram path.diagram-text { + /* Multiple choice text, not working atm. */ + stroke-width: 1; + stroke: red; + fill: red; + cursor: help; +} + +svg.railroad-diagram g.diagram-text:hover path.diagram-text { + /* Multiple choice text, not working atm. */ + fill: #f00; +} + + +/* Call graphs */ + +.node { + font: 200 10px "Helvetica Neue", Helvetica, Arial, sans-serif; +} + +.link { + stroke: #000; + stroke-opacity: .2; + fill: none; + pointer-events: none; + animation: fadeIn 0.25s ease-out 0.2s 1 normal backwards; +} + +.module-1 { + fill: #0ca9fd; +} + +.module-2 { + fill: #63bf8d; +} + +.module-3 { + fill: #ff8801; +} + +.module-4 { + fill: #b9fc34; +} + +.module-5 { + fill: #90e0e0; +} + +.module-6 { + fill: #b4a3f5; +} + +.module-7 { + fill: #f92672; +} + +.module-8 { + fill: #e9e901; +} + +.module-9 { + fill: #83be69; +} + +.module-10 { + fill: #f1d18c; +} + +.node:hover { + fill: #000; +} + +.node:hover, +.node-source, +.node-target { + font: 700 12px "Helvetica Neue", Helvetica, Arial, sans-serif; + cursor: pointer; +} + +.node-source { + fill: #ff5711; +} + +.node-target { + fill: #45aa73; +} + +.link-source, +.link-target { + stroke-opacity: 1; + stroke-width: 2px; + animation: none; +} + +.link-source { + stroke: #3dcd92; +} + +.link-target { + stroke: #ff5711; +} + +@keyframes fadeOut { + 0% { + stroke-opacity: 0.2; + } + 100% { + stroke-opacity: 0.075; + } +} + +@keyframes fadeIn { + 0% { + stroke-opacity: 0.075; + } + 100% { + stroke-opacity: 0.2; + } +} + +.link-dimmed { + stroke-opacity: 0.075; + animation: fadeOut 0.25s ease-out 0.1s 1 normal backwards; +} + + +/* Parse trees */ +.tree-node { + stroke-width: 2; + stroke: #C0C0C0; + fill: rgba(255, 255, 255, 1); +} + +.tree-root { + stroke-width: 2; + fill: #7db6dd; + stroke: #7db6dd; +} + +.tree-leaf { + cursor: default; + stroke-width: 2; + fill: rgba(160, 171, 136, 1); + stroke: rgba(117, 119, 91, 1); +} + +.tree-error { + stroke-width: 2; + fill: #dd8f7d; + stroke: rgba(188, 106, 122, 1); +} + +.tree-node text { + cursor: default; + font: 16px "Helvetica Neue", sans-serif; + fill: rgba(41, 41, 41, 1); + stroke: none; +} + +.tree-leaf text, +.tree-root text, +.tree-error text { + font: 16px "Helvetica Neue", sans-serif; + fill: #ffffff; + stroke: none; +} + +.tree-link { + stroke-width: 2px; + fill: none; + stroke: rgba(128, 128, 128, 1); +} + +g .token-value { + fill: #404040; + stroke: none; + font: 14pt "Source Code Pro", "Hack", "Consolas", "Andale Mono", monospace; +} + +g .token-range { + fill: rgba(0, 77, 98, 1); + stroke: none; + font: 8pt "Source Code Pro", "Hack", "Consolas", "Andale Mono", monospace; +} + +/* Internal elements, only used in vscode */ + +.header { + font-size: 12pt; + z-index: 9999; + top: 0; + left: 0; + right: 0; + height: 45px; + background-color: var(--background-color); + cursor: default; + user-select: none; + white-space: nowrap; +} + +.graph-initial { + font-size: 30pt; + font-weight: 600; + vertical-align: middle; +} + +.rule-index { + font-size: 8pt; +} + +#container { + margin-top: 45px; +} + +.action-box { + font: 10pt monospace; + margin-left: 15px; + padding: 5px; + border: dotted 1px #606060; + cursor: default; +} + +.atn-graph-color { + color: rgba(206, 11, 70, 1); +} + +.atn-graph-save-image { + background: rgba(206, 11, 70, 1) url('../misc/save.png'); + vertical-align: middle; + margin-left: 5px; + width: 24px; + height: 24px; + display: inline-block; + cursor: pointer; +} + +.rrd-color { + color: rgba(10, 188, 80, 1); +} + +.rrd-save-image { + background: rgba(10, 188, 80, 1) url('../misc/save.png'); + vertical-align: middle; + margin-left: 5px; + width: 24px; + height: 24px; + display: inline-block; + cursor: pointer; +} + +.call-graph-color { + color: rgba(255, 191, 15, 1); +} + +.call-graph-save-image { + background: rgba(255, 191, 15, 1) url('../misc/save.png'); + vertical-align: middle; + margin-left: 5px; + width: 24px; + height: 24px; + display: inline-block; + cursor: pointer; +} + +.parse-tree-color { + color: rgba(49, 112, 212, 1); +} + +.parse-tree-save-image { + background: rgba(49, 112, 212, 1) url('../misc/save.png'); + vertical-align: middle; + margin-left: 5px; + width: 24px; + height: 24px; + display: inline-block; + cursor: pointer; +} + +.switch label { + width: 100%; + height: 100%; + margin: 0; + padding: 0; + display: block; + position: absolute; + top: 0; + left: 0; + z-index: 10; +} + +.switch input { + display: none; +} + +.switch > span { + display: inline-block; + top: 3px; + transition: left 0.2s; +} + +.switch-border { + height: 12px; + width: 24px; + position: relative; + border: 1px solid rgba(49, 112, 212, 0.75); + background-color: rgba(49, 112, 212, 0.75); + border-radius: 3.5em; +} + +.switch-handle-top { + width: 12px; + height: 12px; + position: absolute; + left: 0px; + top: 0px; + z-index: 4; + background-color: white; + border-radius: 2.5em; + transition: left 0.2s; +} + +.switch input:checked~.switch-handle-top { + top: 0px; + left: 12px; +} diff --git a/Documentation/railroads/node.svg b/Documentation/railroads/node.svg new file mode 100644 index 000000000..44cac5d07 --- /dev/null +++ b/Documentation/railroads/node.svg @@ -0,0 +1,4 @@ + + + +header'---'NEWLINEbody'==='NEWLINE \ No newline at end of file diff --git a/Documentation/railroads/option.svg b/Documentation/railroads/option.svg new file mode 100644 index 000000000..4b460e52b --- /dev/null +++ b/Documentation/railroads/option.svg @@ -0,0 +1,4 @@ + + + +'->'dialogue'<<''if'expression'>>'hashtagNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/option_block.svg b/Documentation/railroads/option_block.svg new file mode 100644 index 000000000..332a93292 --- /dev/null +++ b/Documentation/railroads/option_block.svg @@ -0,0 +1,4 @@ + + + +INDENTstatementDEDENT \ No newline at end of file diff --git a/Documentation/railroads/options.svg b/Documentation/railroads/options.svg new file mode 100644 index 000000000..5ac006154 --- /dev/null +++ b/Documentation/railroads/options.svg @@ -0,0 +1,4 @@ + + + +optionoption_block \ No newline at end of file diff --git a/Documentation/railroads/set.svg b/Documentation/railroads/set.svg new file mode 100644 index 000000000..265291f40 --- /dev/null +++ b/Documentation/railroads/set.svg @@ -0,0 +1,4 @@ + + + +'<<''set'variable'to''='expression'>>' \ No newline at end of file diff --git a/Documentation/railroads/statement.svg b/Documentation/railroads/statement.svg new file mode 100644 index 000000000..e559e2b8e --- /dev/null +++ b/Documentation/railroads/statement.svg @@ -0,0 +1,4 @@ + + + +dialoguejumpstopcommandhashtagNEWLINEflow controloption list \ No newline at end of file diff --git a/Documentation/railroads/stop.svg b/Documentation/railroads/stop.svg new file mode 100644 index 000000000..a3ef42565 --- /dev/null +++ b/Documentation/railroads/stop.svg @@ -0,0 +1,4 @@ + + + +'<<''stop''>>' \ No newline at end of file diff --git a/Documentation/railroads/title_tag.svg b/Documentation/railroads/title_tag.svg new file mode 100644 index 000000000..3958f0d3e --- /dev/null +++ b/Documentation/railroads/title_tag.svg @@ -0,0 +1,4 @@ + + + +IDENTIFIER':'IDENTIFIERNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/yarn_file.svg b/Documentation/railroads/yarn_file.svg new file mode 100644 index 000000000..c7a475991 --- /dev/null +++ b/Documentation/railroads/yarn_file.svg @@ -0,0 +1,4 @@ + + + +filetagnodeEOF \ No newline at end of file From 06a42872600725fe14a092dc65a6f48f6bac833a Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Mon, 27 Sep 2021 11:35:29 +1000 Subject: [PATCH 21/39] embedded style sheet into SVGs directly This fixes them looking weird on certain browsers/programs. Does have the side effect of making each way bigger than they were before, oh well. --- Documentation/railroads/IDENTIFIER.svg | 482 ++++++++++++++++- .../railroads/IDENTIFIER_CHARACTER.svg | 483 ++++++++++++++++- Documentation/railroads/IDENTIFIER_HEAD.svg | 482 ++++++++++++++++- Documentation/railroads/body.svg | 482 ++++++++++++++++- Documentation/railroads/declare.svg | 482 ++++++++++++++++- Documentation/railroads/else.svg | 482 ++++++++++++++++- Documentation/railroads/elseif.svg | 482 ++++++++++++++++- Documentation/railroads/endif.svg | 482 ++++++++++++++++- Documentation/railroads/expression.svg | 482 ++++++++++++++++- Documentation/railroads/file_tag.svg | 482 ++++++++++++++++- Documentation/railroads/flow_control.svg | 482 ++++++++++++++++- Documentation/railroads/function.svg | 482 ++++++++++++++++- Documentation/railroads/hashtag.svg | 482 ++++++++++++++++- Documentation/railroads/header.svg | 482 ++++++++++++++++- Documentation/railroads/header_tag.svg | 482 ++++++++++++++++- Documentation/railroads/if.svg | 482 ++++++++++++++++- Documentation/railroads/jump.svg | 482 ++++++++++++++++- Documentation/railroads/light.css | 484 ------------------ Documentation/railroads/node.svg | 482 ++++++++++++++++- Documentation/railroads/option.svg | 482 ++++++++++++++++- Documentation/railroads/option_block.svg | 482 ++++++++++++++++- Documentation/railroads/options.svg | 482 ++++++++++++++++- Documentation/railroads/set.svg | 482 ++++++++++++++++- Documentation/railroads/statement.svg | 482 ++++++++++++++++- Documentation/railroads/stop.svg | 482 ++++++++++++++++- Documentation/railroads/title_tag.svg | 482 ++++++++++++++++- Documentation/railroads/yarn_file.svg | 482 ++++++++++++++++- 27 files changed, 12481 insertions(+), 536 deletions(-) delete mode 100644 Documentation/railroads/light.css diff --git a/Documentation/railroads/IDENTIFIER.svg b/Documentation/railroads/IDENTIFIER.svg index 633a8639b..7ddad8e0e 100644 --- a/Documentation/railroads/IDENTIFIER.svg +++ b/Documentation/railroads/IDENTIFIER.svg @@ -1,4 +1,482 @@ - -IDENTIFIER HEADIDENTIFIER CHARACTER \ No newline at end of file + + +IDENTIFIER HEADIDENTIFIER CHARACTER \ No newline at end of file diff --git a/Documentation/railroads/IDENTIFIER_CHARACTER.svg b/Documentation/railroads/IDENTIFIER_CHARACTER.svg index 5d921897d..24e041f76 100644 --- a/Documentation/railroads/IDENTIFIER_CHARACTER.svg +++ b/Documentation/railroads/IDENTIFIER_CHARACTER.svg @@ -1,4 +1,483 @@ - -[0-9][\u0300-\u036F][\u1DC0-\u1DFF][\u20D0-\u20FF][\uFE20-\uFE2F]IDENTIFIER_HEAD'.' \ No newline at end of file + + +[0-9][\u0300-\u036F][\u1DC0-\u1DFF][\u20D0-\u20FF][\uFE20-\uFE2F]IDENTIFIER_HEAD'.' \ No newline at end of file diff --git a/Documentation/railroads/IDENTIFIER_HEAD.svg b/Documentation/railroads/IDENTIFIER_HEAD.svg index 844d288f5..9cd07b5fe 100644 --- a/Documentation/railroads/IDENTIFIER_HEAD.svg +++ b/Documentation/railroads/IDENTIFIER_HEAD.svg @@ -1,4 +1,482 @@ - -[a-zA-Z_]'\u00A8''\u00AA''\u00AD''\u00AF'[\u00B2-\u00B5][\u00B7-\u00BA][\u00BC-\u00BE][\u00C0-\u00D6][\u00D8-\u00F6][\u00F8-\u00FF][\u0100-\u02FF][\u0370-\u167F][\u1681-\u180D][\u180F-\u1DBF][\u1E00-\u1FFF][\u200B-\u200D][\u202A-\u202E][\u203F-\u2040]'\u2054'[\u2060-\u206F][\u2070-\u20CF][\u2100-\u218F][\u2460-\u24FF][\u2776-\u2793][\u2C00-\u2DFF][\u2E80-\u2FFF][\u3004-\u3007][\u3021-\u302F][\u3031-\u303F][\u3040-\uD7FF][\uF900-\uFD3D][\uFD40-\uFDCF][\uFDF0-\uFE1F][\uFE30-\uFE44][\uFE47-\uFFFD][\u10000-\u1FFFD][\u20000-\u2FFFD][\u30000-\u3FFFD][\u40000-\u4FFFD][\u50000-\u5FFFD][\u60000-\u6FFFD][\u70000-\u7FFFD][\u80000-\u8FFFD][\u90000-\u9FFFD][\uA0000-\uAFFFD][\uB0000-\uBFFFD][\uC0000-\uCFFFD][\uD0000-\uDFFFD][\uE0000-\uEFFFD] \ No newline at end of file + + +[a-zA-Z_]'\u00A8''\u00AA''\u00AD''\u00AF'[\u00B2-\u00B5][\u00B7-\u00BA][\u00BC-\u00BE][\u00C0-\u00D6][\u00D8-\u00F6][\u00F8-\u00FF][\u0100-\u02FF][\u0370-\u167F][\u1681-\u180D][\u180F-\u1DBF][\u1E00-\u1FFF][\u200B-\u200D][\u202A-\u202E][\u203F-\u2040]'\u2054'[\u2060-\u206F][\u2070-\u20CF][\u2100-\u218F][\u2460-\u24FF][\u2776-\u2793][\u2C00-\u2DFF][\u2E80-\u2FFF][\u3004-\u3007][\u3021-\u302F][\u3031-\u303F][\u3040-\uD7FF][\uF900-\uFD3D][\uFD40-\uFDCF][\uFDF0-\uFE1F][\uFE30-\uFE44][\uFE47-\uFFFD][\u10000-\u1FFFD][\u20000-\u2FFFD][\u30000-\u3FFFD][\u40000-\u4FFFD][\u50000-\u5FFFD][\u60000-\u6FFFD][\u70000-\u7FFFD][\u80000-\u8FFFD][\u90000-\u9FFFD][\uA0000-\uAFFFD][\uB0000-\uBFFFD][\uC0000-\uCFFFD][\uD0000-\uDFFFD][\uE0000-\uEFFFD] \ No newline at end of file diff --git a/Documentation/railroads/body.svg b/Documentation/railroads/body.svg index 07f045b67..b0afd5881 100644 --- a/Documentation/railroads/body.svg +++ b/Documentation/railroads/body.svg @@ -1,4 +1,482 @@ - -statement \ No newline at end of file + + +statement \ No newline at end of file diff --git a/Documentation/railroads/declare.svg b/Documentation/railroads/declare.svg index f5d0d78be..01ec87d18 100644 --- a/Documentation/railroads/declare.svg +++ b/Documentation/railroads/declare.svg @@ -1,4 +1,482 @@ - -'<<''declare'variable'to''='expression'as''String''Number''Bool''>>' \ No newline at end of file + + +'<<''declare'variable'to''='expression'as''String''Number''Bool''>>' \ No newline at end of file diff --git a/Documentation/railroads/else.svg b/Documentation/railroads/else.svg index 8de96ed8d..2bb7e7481 100644 --- a/Documentation/railroads/else.svg +++ b/Documentation/railroads/else.svg @@ -1,4 +1,482 @@ - -'<<''else''>>' \ No newline at end of file + + +'<<''else''>>' \ No newline at end of file diff --git a/Documentation/railroads/elseif.svg b/Documentation/railroads/elseif.svg index 26bc601af..5170d169e 100644 --- a/Documentation/railroads/elseif.svg +++ b/Documentation/railroads/elseif.svg @@ -1,4 +1,482 @@ - -'<<''elseif'expression'>>' \ No newline at end of file + + +'<<''elseif'expression'>>' \ No newline at end of file diff --git a/Documentation/railroads/endif.svg b/Documentation/railroads/endif.svg index 7f90d056f..9013b6005 100644 --- a/Documentation/railroads/endif.svg +++ b/Documentation/railroads/endif.svg @@ -1,4 +1,482 @@ - -'<<''endif''>>' \ No newline at end of file + + +'<<''endif''>>' \ No newline at end of file diff --git a/Documentation/railroads/expression.svg b/Documentation/railroads/expression.svg index 79ff446d1..9a9795145 100644 --- a/Documentation/railroads/expression.svg +++ b/Documentation/railroads/expression.svg @@ -1,4 +1,482 @@ - -'('expression')''-'expression'!'expressionexpression'*''/''%'expressionexpression'+''-'expressionexpression'<''>''<=''>='expressionexpression'==''!='expressionexpression'and''&&''or''||''xor''^'expressionfunctionliteralvariable \ No newline at end of file + + +'('expression')''-'expression'!'expressionexpression'*''/''%'expressionexpression'+''-'expressionexpression'<''>''<=''>='expressionexpression'==''!='expressionexpression'and''&&''or''||''xor''^'expressionfunctionliteralvariable \ No newline at end of file diff --git a/Documentation/railroads/file_tag.svg b/Documentation/railroads/file_tag.svg index 2c3cb995a..b0b244c2b 100644 --- a/Documentation/railroads/file_tag.svg +++ b/Documentation/railroads/file_tag.svg @@ -1,4 +1,482 @@ - -'#'any tokenNEWLINE \ No newline at end of file + + +'#'any tokenNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/flow_control.svg b/Documentation/railroads/flow_control.svg index 6dcf071f0..950ffd691 100644 --- a/Documentation/railroads/flow_control.svg +++ b/Documentation/railroads/flow_control.svg @@ -1,4 +1,482 @@ - -ifNEWLINEstatementelseifNEWLINEstatementelseNEWLINEstatementendif \ No newline at end of file + + +ifNEWLINEstatementelseifNEWLINEstatementelseNEWLINEstatementendif \ No newline at end of file diff --git a/Documentation/railroads/function.svg b/Documentation/railroads/function.svg index 042c2697f..d47bbcaf7 100644 --- a/Documentation/railroads/function.svg +++ b/Documentation/railroads/function.svg @@ -1,4 +1,482 @@ - -IDENTIFIER'('expression','expression')' \ No newline at end of file + + +IDENTIFIER'('expression','expression')' \ No newline at end of file diff --git a/Documentation/railroads/hashtag.svg b/Documentation/railroads/hashtag.svg index a3124b621..494e4eab0 100644 --- a/Documentation/railroads/hashtag.svg +++ b/Documentation/railroads/hashtag.svg @@ -1,4 +1,482 @@ - -'#'not'#'NEWLINE \ No newline at end of file + + +'#'not'#'NEWLINE \ No newline at end of file diff --git a/Documentation/railroads/header.svg b/Documentation/railroads/header.svg index d3a3f6cdd..0f82fbfbb 100644 --- a/Documentation/railroads/header.svg +++ b/Documentation/railroads/header.svg @@ -1,4 +1,482 @@ - -headertag \ No newline at end of file + + +headertag \ No newline at end of file diff --git a/Documentation/railroads/header_tag.svg b/Documentation/railroads/header_tag.svg index 974ee16c0..5f3582b99 100644 --- a/Documentation/railroads/header_tag.svg +++ b/Documentation/railroads/header_tag.svg @@ -1,4 +1,482 @@ - -IDENTIFIER':'TEXTNEWLINE \ No newline at end of file + + +IDENTIFIER':'TEXTNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/if.svg b/Documentation/railroads/if.svg index f5584a278..9c22a572f 100644 --- a/Documentation/railroads/if.svg +++ b/Documentation/railroads/if.svg @@ -1,4 +1,482 @@ - -'<<''if'expression'>>' \ No newline at end of file + + +'<<''if'expression'>>' \ No newline at end of file diff --git a/Documentation/railroads/jump.svg b/Documentation/railroads/jump.svg index d61298acb..fea855b1c 100644 --- a/Documentation/railroads/jump.svg +++ b/Documentation/railroads/jump.svg @@ -1,4 +1,482 @@ - -'<<''jump'IDENTIFIERinterpolated_text'>>' \ No newline at end of file + + +'<<''jump'IDENTIFIERinterpolated_text'>>' \ No newline at end of file diff --git a/Documentation/railroads/light.css b/Documentation/railroads/light.css deleted file mode 100644 index 2d1b00c36..000000000 --- a/Documentation/railroads/light.css +++ /dev/null @@ -1,484 +0,0 @@ -/* - * This file contains all default CSS rules for the light vscode them, used for various diagrams and graphs. - * Use the "antlr4.customcss" setting in vscode to specify your own file, if you like to override some rules. - * - * Most of the appearance is defined here, while only some adjustments for the dark theme exist in dark.css. - * This style sheet is also used for exported svg files. - */ - - body { - padding-left: 20px; -} - -svg { - background: rgba(0, 0, 0, 0.03); -} - - -/* ATN graphs */ - -.transition { - fill: none; - stroke: #AAA; - stroke-width: 2px; -} - -.marker { - fill: #999; - stroke: none; -} - -.stateLabel { - font: bold 11pt "Helvetica Neue", Arial, sans-serif; - fill: white; - text-anchor: middle; - pointer-events: none; -} - -.stateTypeLabel { - font: bold 7pt monospace; - fill: #EEE; - text-anchor: middle; - pointer-events: none; -} - -.linkLabel { - font: bold 9pt "Helvetica Neue", Arial, sans-serif; - fill: #606060; - text-anchor: middle; - pointer-events: none; -} - -.state { - stroke: #505050; - stroke-width: 3px; - cursor: move; - pointer-events: all; - /*filter: url(#black-glow);*/ -} - -.state.BASIC { - fill: #AAA; -} - -.state.START { - fill: #36bde0; -} - -.state.BSTART { - fill: #f39900; -} - -.state.PBSTART { - fill: #98c000; -} - -.state.SBSTART { - fill: #607dbd; -} - -.state.TSTART { - fill: #ffd300; -} - -.state.STOP { - fill: #2baa5b; -} - -.state.BEND { - fill: #c2c269; -} - -.state.SLBACK { - fill: #608b4e; -} - -.state.SLENTRY { - fill: #a260cb; -} - -.state.PLBACK { - fill: #517979; -} - -.state.LEND { - fill: #9b90c3; -} - -.state.RULE { - fill: #b73645; -} - -.state.RULE.recursive { - fill: #36bde0; -} - - -/* Railroad diagrams */ - -svg.railroad-diagram path { - /* The connection lines. */ - stroke-width: 2; - stroke: darkgray; - fill: rgba(0, 0, 0, 0); -} - -svg.railroad-diagram text { - /* All text except comments. */ - font: bold 12px Hack, "Source Code Pro", monospace; - text-anchor: middle; - fill: #404040; - /* Use fill instead of color for svg text. */ -} - -svg.railroad-diagram text.comment { - /* Comment text */ - font: italic 10px Hack, "Source Code Pro", monospace; - fill: #404040; -} - -svg.railroad-diagram g.non-terminal rect { - /* The non-terminal boxes. */ - stroke-width: 2; - stroke: #404040; - fill: rgba(255, 255, 255, 1); -} - -svg.railroad-diagram g.terminal rect { - /* The terminal boxes. */ - stroke-width: 2; - stroke: #404040; - fill: rgba(0, 0, 0, 0.1); -} - -svg.railroad-diagram text.diagram-text { - /* Multiple choice text, not working atm. */ - font-size: 12px Hack, "Source Code Pro", monospace; - fill: red; -} - -svg.railroad-diagram path.diagram-text { - /* Multiple choice text, not working atm. */ - stroke-width: 1; - stroke: red; - fill: red; - cursor: help; -} - -svg.railroad-diagram g.diagram-text:hover path.diagram-text { - /* Multiple choice text, not working atm. */ - fill: #f00; -} - - -/* Call graphs */ - -.node { - font: 200 10px "Helvetica Neue", Helvetica, Arial, sans-serif; -} - -.link { - stroke: #000; - stroke-opacity: .2; - fill: none; - pointer-events: none; - animation: fadeIn 0.25s ease-out 0.2s 1 normal backwards; -} - -.module-1 { - fill: #0ca9fd; -} - -.module-2 { - fill: #63bf8d; -} - -.module-3 { - fill: #ff8801; -} - -.module-4 { - fill: #b9fc34; -} - -.module-5 { - fill: #90e0e0; -} - -.module-6 { - fill: #b4a3f5; -} - -.module-7 { - fill: #f92672; -} - -.module-8 { - fill: #e9e901; -} - -.module-9 { - fill: #83be69; -} - -.module-10 { - fill: #f1d18c; -} - -.node:hover { - fill: #000; -} - -.node:hover, -.node-source, -.node-target { - font: 700 12px "Helvetica Neue", Helvetica, Arial, sans-serif; - cursor: pointer; -} - -.node-source { - fill: #ff5711; -} - -.node-target { - fill: #45aa73; -} - -.link-source, -.link-target { - stroke-opacity: 1; - stroke-width: 2px; - animation: none; -} - -.link-source { - stroke: #3dcd92; -} - -.link-target { - stroke: #ff5711; -} - -@keyframes fadeOut { - 0% { - stroke-opacity: 0.2; - } - 100% { - stroke-opacity: 0.075; - } -} - -@keyframes fadeIn { - 0% { - stroke-opacity: 0.075; - } - 100% { - stroke-opacity: 0.2; - } -} - -.link-dimmed { - stroke-opacity: 0.075; - animation: fadeOut 0.25s ease-out 0.1s 1 normal backwards; -} - - -/* Parse trees */ -.tree-node { - stroke-width: 2; - stroke: #C0C0C0; - fill: rgba(255, 255, 255, 1); -} - -.tree-root { - stroke-width: 2; - fill: #7db6dd; - stroke: #7db6dd; -} - -.tree-leaf { - cursor: default; - stroke-width: 2; - fill: rgba(160, 171, 136, 1); - stroke: rgba(117, 119, 91, 1); -} - -.tree-error { - stroke-width: 2; - fill: #dd8f7d; - stroke: rgba(188, 106, 122, 1); -} - -.tree-node text { - cursor: default; - font: 16px "Helvetica Neue", sans-serif; - fill: rgba(41, 41, 41, 1); - stroke: none; -} - -.tree-leaf text, -.tree-root text, -.tree-error text { - font: 16px "Helvetica Neue", sans-serif; - fill: #ffffff; - stroke: none; -} - -.tree-link { - stroke-width: 2px; - fill: none; - stroke: rgba(128, 128, 128, 1); -} - -g .token-value { - fill: #404040; - stroke: none; - font: 14pt "Source Code Pro", "Hack", "Consolas", "Andale Mono", monospace; -} - -g .token-range { - fill: rgba(0, 77, 98, 1); - stroke: none; - font: 8pt "Source Code Pro", "Hack", "Consolas", "Andale Mono", monospace; -} - -/* Internal elements, only used in vscode */ - -.header { - font-size: 12pt; - z-index: 9999; - top: 0; - left: 0; - right: 0; - height: 45px; - background-color: var(--background-color); - cursor: default; - user-select: none; - white-space: nowrap; -} - -.graph-initial { - font-size: 30pt; - font-weight: 600; - vertical-align: middle; -} - -.rule-index { - font-size: 8pt; -} - -#container { - margin-top: 45px; -} - -.action-box { - font: 10pt monospace; - margin-left: 15px; - padding: 5px; - border: dotted 1px #606060; - cursor: default; -} - -.atn-graph-color { - color: rgba(206, 11, 70, 1); -} - -.atn-graph-save-image { - background: rgba(206, 11, 70, 1) url('../misc/save.png'); - vertical-align: middle; - margin-left: 5px; - width: 24px; - height: 24px; - display: inline-block; - cursor: pointer; -} - -.rrd-color { - color: rgba(10, 188, 80, 1); -} - -.rrd-save-image { - background: rgba(10, 188, 80, 1) url('../misc/save.png'); - vertical-align: middle; - margin-left: 5px; - width: 24px; - height: 24px; - display: inline-block; - cursor: pointer; -} - -.call-graph-color { - color: rgba(255, 191, 15, 1); -} - -.call-graph-save-image { - background: rgba(255, 191, 15, 1) url('../misc/save.png'); - vertical-align: middle; - margin-left: 5px; - width: 24px; - height: 24px; - display: inline-block; - cursor: pointer; -} - -.parse-tree-color { - color: rgba(49, 112, 212, 1); -} - -.parse-tree-save-image { - background: rgba(49, 112, 212, 1) url('../misc/save.png'); - vertical-align: middle; - margin-left: 5px; - width: 24px; - height: 24px; - display: inline-block; - cursor: pointer; -} - -.switch label { - width: 100%; - height: 100%; - margin: 0; - padding: 0; - display: block; - position: absolute; - top: 0; - left: 0; - z-index: 10; -} - -.switch input { - display: none; -} - -.switch > span { - display: inline-block; - top: 3px; - transition: left 0.2s; -} - -.switch-border { - height: 12px; - width: 24px; - position: relative; - border: 1px solid rgba(49, 112, 212, 0.75); - background-color: rgba(49, 112, 212, 0.75); - border-radius: 3.5em; -} - -.switch-handle-top { - width: 12px; - height: 12px; - position: absolute; - left: 0px; - top: 0px; - z-index: 4; - background-color: white; - border-radius: 2.5em; - transition: left 0.2s; -} - -.switch input:checked~.switch-handle-top { - top: 0px; - left: 12px; -} diff --git a/Documentation/railroads/node.svg b/Documentation/railroads/node.svg index 44cac5d07..71bc1fd08 100644 --- a/Documentation/railroads/node.svg +++ b/Documentation/railroads/node.svg @@ -1,4 +1,482 @@ - -header'---'NEWLINEbody'==='NEWLINE \ No newline at end of file + + +header'---'NEWLINEbody'==='NEWLINE \ No newline at end of file diff --git a/Documentation/railroads/option.svg b/Documentation/railroads/option.svg index 4b460e52b..667bb6d3e 100644 --- a/Documentation/railroads/option.svg +++ b/Documentation/railroads/option.svg @@ -1,4 +1,482 @@ - -'->'dialogue'<<''if'expression'>>'hashtagNEWLINE \ No newline at end of file + + +'->'dialogue'<<''if'expression'>>'hashtagNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/option_block.svg b/Documentation/railroads/option_block.svg index 332a93292..3d22bcd2e 100644 --- a/Documentation/railroads/option_block.svg +++ b/Documentation/railroads/option_block.svg @@ -1,4 +1,482 @@ - -INDENTstatementDEDENT \ No newline at end of file + + +INDENTstatementDEDENT \ No newline at end of file diff --git a/Documentation/railroads/options.svg b/Documentation/railroads/options.svg index 5ac006154..930da71b1 100644 --- a/Documentation/railroads/options.svg +++ b/Documentation/railroads/options.svg @@ -1,4 +1,482 @@ - -optionoption_block \ No newline at end of file + + +optionoption_block \ No newline at end of file diff --git a/Documentation/railroads/set.svg b/Documentation/railroads/set.svg index 265291f40..eb1223116 100644 --- a/Documentation/railroads/set.svg +++ b/Documentation/railroads/set.svg @@ -1,4 +1,482 @@ - -'<<''set'variable'to''='expression'>>' \ No newline at end of file + + +'<<''set'variable'to''='expression'>>' \ No newline at end of file diff --git a/Documentation/railroads/statement.svg b/Documentation/railroads/statement.svg index e559e2b8e..aae6f6967 100644 --- a/Documentation/railroads/statement.svg +++ b/Documentation/railroads/statement.svg @@ -1,4 +1,482 @@ - -dialoguejumpstopcommandhashtagNEWLINEflow controloption list \ No newline at end of file + + +dialoguejumpstopcommandhashtagNEWLINEflow controloption list \ No newline at end of file diff --git a/Documentation/railroads/stop.svg b/Documentation/railroads/stop.svg index a3ef42565..0fa4bc355 100644 --- a/Documentation/railroads/stop.svg +++ b/Documentation/railroads/stop.svg @@ -1,4 +1,482 @@ - -'<<''stop''>>' \ No newline at end of file + + +'<<''stop''>>' \ No newline at end of file diff --git a/Documentation/railroads/title_tag.svg b/Documentation/railroads/title_tag.svg index 3958f0d3e..6bff73edf 100644 --- a/Documentation/railroads/title_tag.svg +++ b/Documentation/railroads/title_tag.svg @@ -1,4 +1,482 @@ - -IDENTIFIER':'IDENTIFIERNEWLINE \ No newline at end of file + + +IDENTIFIER':'IDENTIFIERNEWLINE \ No newline at end of file diff --git a/Documentation/railroads/yarn_file.svg b/Documentation/railroads/yarn_file.svg index c7a475991..f3508dd71 100644 --- a/Documentation/railroads/yarn_file.svg +++ b/Documentation/railroads/yarn_file.svg @@ -1,4 +1,482 @@ - -filetagnodeEOF \ No newline at end of file + + +filetagnodeEOF \ No newline at end of file From 3ad723215eaeab54e8947badb53a9a29cb1fc917 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Mon, 27 Sep 2021 11:54:09 +1000 Subject: [PATCH 22/39] More tweaks to the diagrams --- Documentation/Yarn-Spec.md | 8 ++++---- Documentation/railroads/generic_command.svg | 2 +- Documentation/railroads/jump.svg | 2 +- Documentation/railroads/options.svg | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 60824f7c0..6709c4d2d 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -140,14 +140,14 @@ Comments must not impact the rest of the lines or have any impact on the resulti Throughout various points in this document identifiers are mentioned, the rules for these are shared across all stages of the Yarn project. -An *identifier* is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a noncombining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. -After the first character digits, a period (`.`), and combining Unicode characters are also allowed. +An *identifier* is built up of two main parts, first the *identifier head* which is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a noncombining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. +After the identifier head any number of *identifier characters* are allowed, which are all of the identifier head symbols in addition to digits, a period (`.`), and combining Unicode characters. The `$` symbol must not be part of an identifier. The minimum and maximum length of identifiers is unspecified. ![](railroads/IDENTIFIER.svg) -![](railroads/IDENTIFIER_HEAD.svg) -![](railroads/IDENTIFIER_CHARACTER.svg) +![The first allowed symbol in the identifier](railroads/IDENTIFIER_HEAD.svg) +![All subsequent allowed symbols](railroads/IDENTIFIER_CHARACTER.svg) ## Yarn Structure diff --git a/Documentation/railroads/generic_command.svg b/Documentation/railroads/generic_command.svg index 3d98b3eec..69978b120 100644 --- a/Documentation/railroads/generic_command.svg +++ b/Documentation/railroads/generic_command.svg @@ -480,4 +480,4 @@ g .token-range { } -'<<'TEXTinterpolated_text'>>' \ No newline at end of file +'<<'TEXTinterpolated text'>>' \ No newline at end of file diff --git a/Documentation/railroads/jump.svg b/Documentation/railroads/jump.svg index fea855b1c..aa5ab893d 100644 --- a/Documentation/railroads/jump.svg +++ b/Documentation/railroads/jump.svg @@ -479,4 +479,4 @@ g .token-range { left: 12px; } -'<<''jump'IDENTIFIERinterpolated_text'>>' \ No newline at end of file +'<<''jump'IDENTIFIERinterpolated text'>>' \ No newline at end of file diff --git a/Documentation/railroads/options.svg b/Documentation/railroads/options.svg index 930da71b1..47cce3a67 100644 --- a/Documentation/railroads/options.svg +++ b/Documentation/railroads/options.svg @@ -479,4 +479,4 @@ g .token-range { left: 12px; } -optionoption_block \ No newline at end of file +optionoption block \ No newline at end of file From ec85172707e45c0e7cabec963305f96974433b62 Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 11:21:00 +1000 Subject: [PATCH 23/39] Edited intro --- Documentation/Yarn-Spec.md | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 6709c4d2d..994129e27 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -1,29 +1,31 @@ # Yarn Spec +*Language version 2.0 | Last updated: 28th September 2021* -This document describes the specification of the Yarn Script format version 2 and guidance and rules for implementing programs who wish to process Yarn scripts. +This document defines the Yarn Script version 2 language format, and contains guidance and rules for implementing programs to process Yarn 2.x scripts. ## Introduction Yarn is a language for representing branching and linear interactive fiction in games. Yarn was created for the game Night in the Woods and was inspired by the Twine language. -Its focus is on flexibility and writer ease, the goal of the language is to have clear syntax when necessary but to otherwise be as close to just writing text as possible. -For writers there should be minimal friction in creating the language and for programmers minimal annoyance when interfacing with it. +Its focus is on flexibility and writer ease; the primary goal of the language is to have clear, minimal syntax and to remain as close to just writing dialogue text as possible. +For writers there should be minimal friction in authoring in Yarn and, for programmers, there should be minimal annoyance when interfacing with it. -During development of Night in the Woods Yarn Spinner was created as an open source side project and had no affiliation to Night in the Woods at the time. -Yarn Spinner could read and understand Yarn files but had several advantages over the Yarn interpreter in Night in the Woods so the decision was made to use Yarn Spinner for the game. +During development of Night in the Woods, Yarn Spinner was created as an open source framework to better integrate Yarn with the Unity Game Engine--a side project and had no affiliation to Night in the Woods at the time. +But Yarn Spinner could read and understand Yarn files, and had several advantages over the Yarn interpreter in Night in the Woods, so the decision was made to use Yarn Spinner for the game. This made Yarn Spinner the de facto Yarn interpreter and had the side effect of giving it control over the specification of the language. -Yarn essentially became and was always defined in terms of what Yarn Spinner could understand. +Yarn essentially became and was henceforth defined by what Yarn Spinner could understand. -As Night in the Woods was developed additional features and work was done on Yarn Spinner for the game the set of features and syntax exploded and became difficult to understand or reimplement. -Post Night in the Woods Yarn Spinner continued as its own thing with version 0.9 being released which was mostly a polish of the version used in Night in the Woods. -Later version 1.0 of Yarn Spinner, and as such the language, came out with improved syntax and was the first significant release that wasn't tied to Night in the Woods. -Neither Yarn Spinner 0.9 or 1.0 however came with complete specifications of the Yarn language and had a great deal of legacy elements. +As Night in the Woods was developed additional features, and work was done on Yarn Spinner for the game, the set of features and syntax exploded and became difficult to understand or reimplement. +Post-Night in the Woods, Yarn Spinner continued as an independent project. +Yarn Spinner version 0.9 was mostly a polished form of the framework as was used in Night in the Woods, but 1.0 came with improved syntax and was the first significant release that wasn't tied to Night in the Woods. +Neither Yarn Spinner 0.9 or 1.0 however came with complete specifications of the Yarn language and had a great deal of legacy elements. A concerted effort was made to clean up the Yarn language for Yarn Spinner 2.0 into something hopefully more understandable but also more flexible. -A component of this is the creation of this specification guide so implementations beyond Yarn Spinner can have something to base decisions on that isn't "do what Yarn Spinner does". +A component of this is the creation of this specification guide, so implementations of alternative interpreters or other Yarn- or Yarn Spinner-related tools can have a clear source of truth (that isn't "just copy what Yarn Spinner does"). +We hope this will empower others to make their mark on the broader Yarn Spinner ecosystem, by supporting the creation of new tools or bridging frameworks to bring Yarn Spinner to a broader range of game engines and workflows. -Despite this being the first version of the Yarn language to ever exist it is version 2 of the Yarn language. -This is because despite Yarn and Yarn Spinner being separate elements attempting to not stay, at least initially, in version lock with the de facto implementation is just asking for trouble, hence version 2 of Yarn. +Despite this being the first time a Yarn language specification has existed, it is version 2 of the Yarn language and will begin versioning at 2.0. +This is to avoid confusion that would arise should the Yarn languge specification and the Yarn Spinner framework be versioned separately. ### Coverage From 1345e0956d0a3a1b827b6ca2fa9fee645f9a2174 Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 11:40:43 +1000 Subject: [PATCH 24/39] Done up to ## Yarn Structure --- Documentation/Yarn-Spec.md | 47 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 994129e27..56df08663 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -29,7 +29,7 @@ This is to avoid confusion that would arise should the Yarn languge specificatio ### Coverage -This document covers the elements of a Yarn script that are required to be considered a valid Yarn script as well as the rules necessary for an implementing program to be able to conform to this specification. +This document covers the elements of a Yarn script that are required to be considered valid, as well as the rules necessary for an implementing program to conform to this specification. An *implementing program* is a program that accepts Yarn files as inputs and understands them based on the rules in this document. This document does not cover how a Yarn file is to be transformed or handled internally by an implementing program. @@ -41,17 +41,17 @@ Only the `title` tag is required, an implementation may choose to make other tag ### Assumptions -There is one large assumption in this document and about the language itself. -That is it that it is intended to be embedded into a larger game project. +There is one large assumption in this document and about the language itself: +that it is intended to be employed as part of a larger game project. -As such details like how lines are viewed, how selections of options are made, how generic commands get used, or how functions are handled are all assumed to be passed off onto the larger game to handle. -This is not technically necessary but does explain what would otherwise be gaps in the language. -If your project does not have a game to offload certain tasks to these elements will have to be handled by the implementing program itself. +As such, details like how lines are viewed, how selections of options are made, how generic commands get used, or how functions are handled are all assumed to be passed off onto the larger game to handle. +This is not technically necessary, but does explain what would otherwise be gaps in the language. +If your project does not have a game to offload certain tasks to, these elements will have to be handled by the implementing program itself. ### Reading This Specification `monofont` terms are to be taken as literals. -As an example the `title` tag would be written as a string literal `"title"` in C#. +As an example the `title` tag would be written as a string literal `"title"` in C#, or just the text `title` in a Yarn script. *italics* terms are terms which are reused throughout the document. They are presented in italics the first time they are defined. @@ -59,11 +59,12 @@ They are presented in italics the first time they are defined. _Must_ is a hard requirement. _Should_ is a recommendation, albeit a strong one. -_Errors_ are mentioned multiple times and represent situations that are unrecoverable. +_Errors_ are mentioned multiple times and represent situations that are **unrecoverable**. A goal of Yarn is to have all errors known and handled at creation time instead of runtime but this isn't always possible. -Errors are intended to allow the implementing program to let the user or other parts of the game know that an unrecoverable situation has occured. -The implementing program must abort progress on the Yarn after creating an error. -The precise handling of errors will be specific to the implementing program but should use whatever error mechanisms exist already, for example Yarn Spinner throws normal C# exceptions for its errors. +Errors are intended to allow the implementing program to let the user, or other parts of the game, know that an unrecoverable situation has occured. +This means the implementing program **must abort** after creating an error. +The precise handling of errors will be specific to the implementing program, but should use whatever error mechanisms exist already. +For example, Yarn Spinner throws normal C# exceptions for its errors. Dates, spelling, and numbers are to be in Australian English. @@ -78,8 +79,8 @@ White elements are more complex rules, grey elements are literals either by name Lines may loop back or skip over elements, and every path through the diagram decribes a valid version of the rule. The diagrams at various stages use ranges to represent all potential values within that range. -Common uses of this include being able to capture the digits `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`, if you were required to type them out in the diagram each time it would get onerous, so we represent this with a range using square brackets `[` and `]`. -The character on the left side of the range represents the start and the right side represent the end of the range, so the digits would be represented as `[0-9]`. +Common uses of this include being able to capture the digits `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`, as `[0-9]`. +For ranges enclosed in `[]` notation, the character on the left side of the range represents the start and the right side represent the end of the range (inclusive). Hardcoded unicode values are also shown in the diagrams, these represent elements that are either difficult to show visually or for easier capture in ranges. Unicode values are represented in these diagrams with a `\u` followed by a multiple digit hexadecimal value. The value of these digits map directly to a unicode code point, for example `\u00A8` represents the `¨` or DIAERESIS symbol. @@ -105,19 +106,19 @@ File extension should be `.yarn`. ### Project The Yarn *project* is all Yarn files that are intended to be associated with one another. -While there is nothing stopping a writer from placing all nodes into one big file (or even making one giant node) it is common to break them up over multiple files. +While there is nothing stopping a writer from placing all nodes into one big file (or even one giant node), it is common to break them up over multiple files. The project is all of these files collected and processed by the implementing program together. ### Lines The *line* is the common unit that comprises all elements in a Yarn file. A line is a series of characters terminated by the *new line* symbol. -The new line symbol should be the `\n` character. -The new line must be the same throughout the project regardless of the chosen new line symbol. +The new line symbol should contain at least the `\n` character, but different operating system conventions may result in compound characters such as `\r\n`. +Once chosen, the new line symbol must remain the same throughout the project. The following Yarn file contains four lines (in order); one header tag line, one header delimiter line, one body dialogue line, one body delimiter line. ```yarn -title:Start +title: Start --- This is some text === @@ -137,15 +138,19 @@ All text from the start of the comment to the end of the line must be ignored. A comment starting in the middle of another line ends that line at the point the `//` symbol is encountered. That line is assumed to have finished at that point as if the comment was not there. Comments must not impact the rest of the lines or have any impact on the resulting Yarn program. +Comments may occur in any part of a Yarn file: in headers, delimiter lines, or node bodies. ### Identifiers -Throughout various points in this document identifiers are mentioned, the rules for these are shared across all stages of the Yarn project. +Identifiers are mentioned at various points in this document, and the rules for these are shared across all stages of the Yarn project. + +An *identifier* is built up of two main parts: + +1. the *identifier head* which is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a noncombining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. +2. (after the identifier head) any number of *identifier characters* are allowed, which may be any of the identifier head symbols, as well as digits, the period (`.`), and combining Unicode characters. -An *identifier* is built up of two main parts, first the *identifier head* which is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a noncombining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. -After the identifier head any number of *identifier characters* are allowed, which are all of the identifier head symbols in addition to digits, a period (`.`), and combining Unicode characters. The `$` symbol must not be part of an identifier. -The minimum and maximum length of identifiers is unspecified. +The minimum length of an identifier is 1 character (the identifier head with no further identifier characters), but the maximum length of an identifier is **unspecified**. ![](railroads/IDENTIFIER.svg) ![The first allowed symbol in the identifier](railroads/IDENTIFIER_HEAD.svg) From 10a55553202d7617cbf899fa04e7309990f03289 Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 12:30:13 +1000 Subject: [PATCH 25/39] Up to interpolated dialogue --- Documentation/Yarn-Spec.md | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 56df08663..858dd4360 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -36,7 +36,7 @@ This document does not cover how a Yarn file is to be transformed or handled int This document does note when behaviours are *unspecified*. The implementing program may choose how to handle any unspecified behaviour, often unspecified behaviours have no good solution and should result in an error. -An example of unspecified behaviour are required tags on Nodes. +An example of unspecified behaviour are required tags on nodes. Only the `title` tag is required, an implementation may choose to make other tags required or banned. ### Assumptions @@ -113,10 +113,11 @@ The project is all of these files collected and processed by the implementing pr The *line* is the common unit that comprises all elements in a Yarn file. A line is a series of characters terminated by the *new line* symbol. -The new line symbol should contain at least the `\n` character, but different operating system conventions may result in compound characters such as `\r\n`. +The new line symbol should be either the `\n` character or `\r\n`. Once chosen, the new line symbol must remain the same throughout the project. The following Yarn file contains four lines (in order); one header tag line, one header delimiter line, one body dialogue line, one body delimiter line. + ```yarn title: Start --- @@ -129,7 +130,7 @@ This is some text *Whitespace* is any non-visible character with a width greater than 0. Common whitespace encountered include the space and the tab. -Whitespace for the most part plays no role for the majority of Yarn, but has significant syntactic impact for [Options](#options). +Whitespace for the most part plays no role for the majority of Yarn, but has significant syntactic impact for [options](#options). ### Comments @@ -138,7 +139,7 @@ All text from the start of the comment to the end of the line must be ignored. A comment starting in the middle of another line ends that line at the point the `//` symbol is encountered. That line is assumed to have finished at that point as if the comment was not there. Comments must not impact the rest of the lines or have any impact on the resulting Yarn program. -Comments may occur in any part of a Yarn file: in headers, delimiter lines, or node bodies. +Comments may occur in any line of a Yarn file and take precedence over any other parsing rules such as [hashtags](#hashtags), but may still be affected by [escaping text](#escaping-text). ### Identifiers @@ -174,9 +175,8 @@ File tags must have the `#` symbol at the start of them and then contain all tex ### Nodes A *node* is the single story element of a Yarn file. -Nodes are the story structural building blocks for Yarn. -Nodes are designed to contain pieces of a story and then have these story pieces linked together. -This is not a requirement, everything could be done in a single node, this would just be unwieldy. +Nodes are the story structural building blocks of Yarn; they are designed to contain pieces of a story and then have these story pieces linked together. +This is not a requirement--everything could be done in a single node--but avoidance of the node structure quickly becomes unwieldy for the author. A node must be comprised of a single header and a single body in that order. ![](railroads/node.svg) @@ -197,8 +197,8 @@ The *tag separator* is the character `:`. The *tag text* is all text up until the end of line. Header tags are commonly used as node specific metadata but using them in this manner is not required, beyond the [title tag](#title-tag). -The amount of allowed whitespace between the tag name, the separator, and the tag text is unspecified. -An example of a header tag is the title tag: `title:start`. +The maximum amount of whitespace allowed between the tag separator and the tag text is unspecified. The minimum amount is zero characters. +An example of a header tag is the title tag: `title: start`. Every node must have a title tag. Required or banned header tags beyond title are unspecified. @@ -214,7 +214,7 @@ The tag text for the title tag must be unique within the file. The tag text for the title tag should be unique within the project. The tag text must follow the rules of [identifiers](#identifiers). -The behaviour of the program when a title tag's text is not unique across the project is unspecified. +The behaviour of the program when a title tag's text is not unique across the file or project is unspecified. The program should flag this as an error. ![](railroads/title_tag.svg) @@ -238,21 +238,20 @@ A *statement* is a line that is one of the following: A statement may have optional [hashtags](#hashtags). A body must have at least one statement. +![](railroads/body.svg) ![](railroads/statement.svg) The body ends when encountering a line that consists entirely of the *body delimter* `===`. The body delimiter ends both the current node and the body of that node. The end of file must not be used in place of a body delimiter. -![](railroads/body.svg) - #### Hashtags *Hashtags* are metadata associated with the statement they are a part of. Hashtags must go at the end of the statement. The other components of the statement must end at the hashtag, the hashtag operates effectively as the newline terminator for the statement. -A hashtag starts with the `#` symbol and contain any text up to the newline or another hashtag. +A hashtag starts with the `#` symbol and contain any text up to the newline, a whitespace character, or another hashtag. `#lineID:a10be2` is an example of a hashtag. Multiple hashtags can exist on a single line. @@ -264,9 +263,9 @@ Multiple hashtags can exist on a single line. ## Dialogue Statement A dialogue statement is a statement that represents a single line of text in the Yarn body. -In most cases dialogue will be the bulk of the content of a node's body. +In most cases dialogue will be the bulk of a node's body. Dialogue statements can be [interpolated](#interpolated-dialogue) dialogue or [raw](#raw-dialogue) dialogue. -A dialogue statement can contain any characters except for the `#` character. +A dialogue statement can contain any characters except for the `#` character, but is subject to a variety of stop conditions including a newline or the start of a control flow. `{$name}, you are a bold one.` is an example of an interpolated dialogue statement. `General Kenobi, you are a bold one.` is an example of a raw dialogue statement. @@ -277,7 +276,7 @@ An *interpolated dialogue* is dialogue where there are [expressions](#expression Expressions are encapsulated within the `{` and `}` symbols and it is the presence of these symbols that determine if a line is an interpolated one or not. The expression inside the `{}` symbols must be a valid expression. The result of the expression must be inserted into the dialogue. -Other than replacing expressions dialogue statments must not be modified by the implementing program, and provided to the game as written. +Other than replacing expressions, dialogue statements must not be modified by the implementing program, and provided to the game as written. The encapsulated expression can go anywhere inside the statement or even be the entire dialogue statement by itself. ### Raw Dialogue From 3fb244be3dab5f784ed830d24c508db9a2233e16 Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 12:52:05 +1000 Subject: [PATCH 26/39] Up to flow control --- Documentation/Yarn-Spec.md | 49 ++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 858dd4360..c6f973fd4 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -275,9 +275,17 @@ A dialogue statement can contain any characters except for the `#` character, bu An *interpolated dialogue* is dialogue where there are [expressions](#expressions) in the line. Expressions are encapsulated within the `{` and `}` symbols and it is the presence of these symbols that determine if a line is an interpolated one or not. The expression inside the `{}` symbols must be a valid expression. -The result of the expression must be inserted into the dialogue. +The result of the expression must be resolved as a [string value](#supported-types) to be inserted into the dialogue. +The string representation behaviour of each variable type in Yarn is unspecified, but should follow common conventions such as those shown below. + +| Type | Example Value | String Representation | +|:--|:--|:--| +| String | "Hello" | Hello | +| Number | 1e-4 | 0.0001 | +| Boolean | TRUE | True | + Other than replacing expressions, dialogue statements must not be modified by the implementing program, and provided to the game as written. -The encapsulated expression can go anywhere inside the statement or even be the entire dialogue statement by itself. +The encapsulated expression can go anywhere inside the statement, or even be the entire dialogue statement. ### Raw Dialogue @@ -298,8 +306,8 @@ Because the dialogue statement allows a great deal of flexibility in allowed cha This creates an ambiguity when parsing a Yarn file, as such the dialogue statement must be considered the lowest priority by the implementing program. For example `<>` could be read as a [command](#commands) or a dialogue statement, it must be considered a command by the implementing program. -This does create a potential conflict between writer intent and Yarn's requirements, however it is unavoidable. -To continue the earlier example if the writer intended `<>` to be a dialogue statement they would have to escape the reserved characters first, so `\<>` which would present as `<>` to the game. +This does create a potential conflict between writer intent and Yarn's requirements, but this is unavoidable. +To continue the earlier example: if the writer intended `<>` to be a dialogue statement, they would have to escape the reserved characters first, so `\<>` which would present as `<>` to the game. ## Commands @@ -315,14 +323,14 @@ The possible types of commands are: - [flow control](#flow-control) All commands must start with the `<<` symbol and end with the `>>` symbol. -Additional required command are unspecified. +Additional required commands are unspecified. ### Generic Commands _Generic Commands_ are commands for sending messages from the Yarn to the rest of the program. -Unlike the other commands generic commands don't impact the dialogue. +Unlike the other commands, generic commands don't impact the dialogue. They can be thought of as lines of dialogue that aren't to be shown in the game. -Implementing programs must not modify the flow of the Yarn based on the command. +Implementing programs must not modify the flow of the Yarn script based on the command. Generic commands can have any text except for the `#`, `{`, or `}` symbols inside of them. @@ -341,7 +349,7 @@ are examples of generic commands. ### Jump The _jump_ command is how a Yarn program can move from one [node](#nodes) to another. -The jump has two components: the keyword and the destination and these are separated by one or more whitespace. +The jump has two components: the keyword and the destination and these are separated by one or more whitespace characters. The _keyword_ is the text `jump` and comes first in the command. The _destination_ is the name of the node to move to. @@ -352,10 +360,10 @@ The expression must resolve to a [string value](#supported-types) and must be a The behaviour of an implementing program is unspecified when asked to jump to a destination that doesn't match a title in the project. The implementing program should flag this as an error. -Once the jump command has been completed the current node must be exited immediately, this means any dialogue, options or commands below the jump are to be ignored. -From that point on the destination nodes contents must instead be run. +Once the jump command has been completed the current node must be exited immediately. This means any dialogue, options, or commands below the jump are to be ignored. +From that point on, the destination node's contents must instead be run. -`<>` is an example of a jump command, `<>` is an example of a jump command using an expression to determine the destination node. +`<>` is an example of a jump command, `<>` is an example of a jump command using an expression to determine the destination node. ![](railroads/jump.svg) @@ -364,7 +372,7 @@ From that point on the destination nodes contents must instead be run. The _stop_ command is for halting all progress on the [project](#project). Once the stop command is reached all processing on the project must halt, no additional [nodes](#nodes) are to be loaded and run, no additional [dialogue](#dialogue-statement) or [commands](#commands) are to processed. The stop command has only one component, the _keyword_ `stop`. -The stop command should reset any [variable](#variables) or internal state back to their initial states. +The stop command should reset any [variable](#variables) or internal state back to their initial states as if the script had not been run. `<>` is the example of the stop command. @@ -373,7 +381,7 @@ The stop command should reset any [variable](#variables) or internal state back ### Set The _set_ command allows [variables](#variables) to be given [values](#values). -The set command has four components: the keyword, the variable, the operator and the value and must be presented in that order. +The set command has four components: the keyword, the variable, the operator and the value, and these must be presented in that order. Each component must be separated by one or more whitespace characters. The _keyword_ is the text `set`. @@ -387,15 +395,15 @@ The following is an example of two set commands: <> ``` -The set command must follow all the rules for [variable naming](#naming-and-scope) and expressions. +Components in the set command must follow the rules for [variable naming](#naming-and-scope) and expressions. The set command must not allow setting a variable to an expression whose value is different from the [type](#supported-types) of that variable. ![](railroads/set.svg) ### Declare -[Variables](#variables) in Yarn should be declared to let the implementing program know the [type](#supported-types) of values they hold. -The intent of this is to allow the implementing program to set up memory and to provide guidance as to the usage of a variable directly from the writer. +[Variables](#variables) in Yarn must be declared before they are used, to let the implementing program know the [type](#supported-types) of values they hold. +The intent of this is to allow the implementing program to set up memory, and to provide guidance as to the usage of a variable directly from the writer. The declare command has four components: the keyword, the variable, the operator and the value, and must be presented in that order. Each component must be separated by one or more whitespace characters. @@ -417,7 +425,8 @@ The value of the expression is used determine what type the value is to be decla The implementing program must not allow the variable declared to ever have a value set which is not of the declared type. If this does occur the implementing program must flag this as an error. -The handling of encountering variables which have not been declared is unspecified but should generate an error. +An interpreter may elect to statically analyse a Yarn script an insert the necessary declare commands as part of a build or compile process but once the script is run, encountering variables which have not been declared by some means should generate an error. +The delcare command should only be used to set the initial value of a variable; encountering a declare command for a variable that has already been declared should generate an error, even if the resulting [type](#supported-types) is the same as that declared previously. ![](railroads/declare.svg) @@ -427,15 +436,15 @@ It is assumed that most of the time a variable's type will be determined implici Syntactically this works identically to the implicit type declaration with two additional elements at the end of the command, the `as` keyword and a type. The type of the expression must match one of the [suported types](#supported-types) keywords: +- `String` for Strings - `Number` for Numbers - `Bool` for Booleans -- `String` for Strings `<>` is an example of an explicitly typed declaration. Explicitly typed declarations will most likely be used when getting intial values from [functions](#functions) who's type is undefined. -The default value's type given in a an explictly typed declaration must match the type, for example `<>` is an invalid declaration because `General Kenobi` isn't a `Number`. +The default value's type given in an explictly typed declaration must match the type, for example `<>` is an invalid declaration because `"General Kenobi"` isn't a `Number`. -If additional types are in use by the implementing program the keywords for their explicit definition are unspecified, but they must be consistent across all declarations. +If additional types are in use by the implementing program, the keywords for their explicit definition are unspecified, but they must be consistent across all declarations. ### Flow control From 186daa70a659990d43e9b1e32ce5c6bde0d92e30 Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 13:02:24 +1000 Subject: [PATCH 27/39] Up to #### Scope and Blocks --- Documentation/Yarn-Spec.md | 50 +++++++++++++++----------------------- 1 file changed, 20 insertions(+), 30 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index c6f973fd4..210abbd24 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -265,7 +265,7 @@ Multiple hashtags can exist on a single line. A dialogue statement is a statement that represents a single line of text in the Yarn body. In most cases dialogue will be the bulk of a node's body. Dialogue statements can be [interpolated](#interpolated-dialogue) dialogue or [raw](#raw-dialogue) dialogue. -A dialogue statement can contain any characters except for the `#` character, but is subject to a variety of stop conditions including a newline or the start of a control flow. +A dialogue statement can contain any characters except for the `#` character. `{$name}, you are a bold one.` is an example of an interpolated dialogue statement. `General Kenobi, you are a bold one.` is an example of a raw dialogue statement. @@ -276,13 +276,6 @@ An *interpolated dialogue* is dialogue where there are [expressions](#expression Expressions are encapsulated within the `{` and `}` symbols and it is the presence of these symbols that determine if a line is an interpolated one or not. The expression inside the `{}` symbols must be a valid expression. The result of the expression must be resolved as a [string value](#supported-types) to be inserted into the dialogue. -The string representation behaviour of each variable type in Yarn is unspecified, but should follow common conventions such as those shown below. - -| Type | Example Value | String Representation | -|:--|:--|:--| -| String | "Hello" | Hello | -| Number | 1e-4 | 0.0001 | -| Boolean | TRUE | True | Other than replacing expressions, dialogue statements must not be modified by the implementing program, and provided to the game as written. The encapsulated expression can go anywhere inside the statement, or even be the entire dialogue statement. @@ -298,7 +291,7 @@ To use reserved symbols in dialogue preface any reserved symbol with the escape Any character following the escape must be presented in the dialogue as-is and must not be parsed as a special character. As an example `\{$name\}, you are a bold one.` would be presented as `{$name}, you are a bold one.` to the game. -Escaping text must be supported in both normal and interpolated dialogue lines as well as in the dialogue component of [Options](#options). +Escaping text must be supported in both normal and interpolated dialogue lines as well as in the dialogue component of [options](#options). ### Statement Ambiguity @@ -451,27 +444,20 @@ If additional types are in use by the implementing program, the keywords for the _Flow control_ is a collection of commands that allow the writer to control the flow of the story. The purpose of these commands is to limit and select which pieces of a story are presented. Flow control in combination with [options](#options) and [jumps](#jump) are what make Yarn a non-linear narrative language. -There are four commands which work in conjunction to support flow control: - -- if -- else -- elseif -- endif - -The order of these commands is always the same and must be followed: +There are four commands which work in conjunction to support flow control. +These are ordered, and the order of these commands must be followed: -1. if -1. elseif -1. else -1. endif +- `if` +- `elseif` +- `else` +- `endif` The if and endif must be present, the elseif and else must be optional. -While each of these commands are their own statement they should be considered to be part of a larger flow control statement which spans multiple lines. +While each of these commands are their own statement, they should be considered to be part of a larger flow control statement which spans multiple lines. Each of these, except the `endif`, have an attached [block](#scope-and-blocks). -The following is an example of flow control, the dialogue line to be shown will depend on the value of `$var`. -If `$var` is `1`, the line `if-scope` will be presented, if it is `2` then the `elseif-scope` line will be shown. -If neither of those are the case then the `else-scope` line will be shown. +The following is an example of flow control: + ```yarn <> if-scope @@ -482,11 +468,15 @@ If neither of those are the case then the `else-scope` line will be shown. <> ``` +The dialogue line shown will depend on the value of `$var`. +If `$var` is `1`, the line `if-scope` will be presented, if it is `2` then the `elseif-scope` line will be shown. +If neither of those are the case then the `else-scope` line will be shown. + ![](railroads/flow_control.svg) #### if -The _if_ command is the opening command of flow control and is broken up into two parts, the keyword and the expression and must be in that order. +The _if_ command is the opening command of flow control and is broken up into two parts, the keyword and the expression, that must be in that order. The _keyword_ is the text `if`. The _expression_ is an [expression](#expressions). The expression must resolve to a boolean. @@ -502,12 +492,12 @@ The command works in a fashion very similar to the if command. The command is broken up into two parts, the keyword and the expression and must be presented in that order. The _keyword_ is the text `elseif`. The _expression_ is an [expression](#expressions). -The expression must resolve to a boolean. +The expression must resolve to a [boolean value](#supported-types). -The elseif will run only if the `if` component, and any other `elseif`'s before it evaluated to false, and if its own expression evaluates to true. +The `elseif` will run only if the `if` component and any other `elseif`s before it evaluated to false, and if its own expression evaluates to true. The minimum mumber of required elseif commands must be zero. -The maximum number of allowed elseif commands in a flow control statement is unspecified but must be greater than zero. +The maximum number of allowed elseif commands in a flow control statement is unspecified but must be greater than one. An elseif command must not exist without an if command and must go after the if command. ![](railroads/elseif.svg) @@ -538,7 +528,7 @@ The endif exists to allow the implementing program know when the scope of the ot #### Scope and Blocks -For the flow control to be useful there needs to be Yarn statements which are run only when their appropriate expression evaluates to true. +For flow control to be useful there needs to be Yarn statements which are run only when their appropriate expression evaluates to true. Flow control allows for blocks of statements to be scoped to their commands. A _block_ is a collection of statements that are scoped to a particular part of the flow control. The block must be one or more statements. From 5103f2b5fb8bd782d0ea6e0d442b20308d2a868d Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 14:51:26 +1000 Subject: [PATCH 28/39] Up to ## Expressions --- Documentation/Yarn-Spec.md | 68 +++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 210abbd24..0834aa563 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -51,8 +51,6 @@ If your project does not have a game to offload certain tasks to, these elements ### Reading This Specification `monofont` terms are to be taken as literals. -As an example the `title` tag would be written as a string literal `"title"` in C#, or just the text `title` in a Yarn script. - *italics* terms are terms which are reused throughout the document. They are presented in italics the first time they are defined. @@ -543,13 +541,13 @@ While it is common for writers to indent their blocks relative to their scope it #### Handling -The implementing program must process all statements within the active blocks scope. +The implementing program must process all statements within the active block's scope. The _active block_ is the block of Yarn who's command expression evaluates to `true`. The block associated with the else command, if present, must only be determined as the active block if all other blocks expressions evaluate to false. An implementing program must not process any statements inside a block that is not the active block. An implementing program must only have, at most, one active block. -If no blocks expression evaluates to true then no block must be processed. +If no block's expression evaluates to true then no block must be processed. #### Ambiguity @@ -570,11 +568,11 @@ For example take the following flow control: Both of the elseif commands expressions evaluate to true, so either ones attached block could be run and seen to be correct. However because one is above the other the block with `elseif-1-scope` dialogue inside would be the selected one. -The implementing program should attempt to identify these scenarios however and alert the writer. +If multiple commands evaluate the result of the same variable or expression, the implementing program should attempt to identify this and alert the writer. ### Command Ambiguity -Generic commands support all the same characters as the other commands, as such this creates an ambiguity between commands, with every more specialised command also being a valid [generic command](#generic-commands). +Generic commands support all the same characters as the other commands and this creates an ambiguity between commands, with each more specialised command also being a valid [generic command](#generic-commands). To resolve this ambiguity all other commands take priority over the generic command. As an example `<>` is a valid generic command but also a valid [jump](#jump) command, it must be assumed to be a jump command. @@ -587,15 +585,15 @@ In the above `<>` example the implementing program must consider this is _Options_ are the means by which Yarn can present dialogue choices to the game and much as with flow control are an element that spans multiple lines. Options are comprised of one or more option lines. -An _option line_ represents a single choice in an option, and are comprised of three parts: the keyword, the dialogue, the [conditional](#conditional) in that order. +An _option line_ represents a single choice in an option, and are comprised of three parts: the keyword, the dialogue, and an optional [conditional](#conditional), in that order. ![](railroads/option.svg) The _keyword_ is how the implementing program can tell a line is part of an option instead of dialogue and is the symbol `->`. -There must be at least one whitespace between the keyword and the next element, the dialogue. The _dialogue_ is a normal line of [dialogue](#dialogue-statement) following all rules associated with that. +The maximum amount of whitespace allowed between the keyword and the dialogue is unspecified. The minimum amount is zero characters. -As the intention of options is to provide choice to the player when options are encountered the implementing program must halt further progress through the node until an option has been selected. +As the intention of options is to provide choice to the player, when options are encountered the implementing program must halt further progress through the node until an option has been selected. Each option must be provided in the order they are written in the node. The mechanism by which an option line is chosen is unspecified. Only a single option line must be chosen. @@ -604,9 +602,9 @@ Only a single option line must be chosen. ### Conditional -The _conditional_ is a command which provides addtional data about the validity of the option. -The intent of the conditional is to allow the writer to give the game more information about the option. +The _conditional_ is a command that provides additional information about how to treat, or whether to present, particular option lines. The conditional's syntax is identical to the [if command](#if) and follows all rules there, but as it is not part of flow control must not have an accompanying [endif](#endif) or attached block. + The conditional must be an optional component of the line. As the conditional is optional any option line without a conditional must be assumed to be `true`. @@ -616,22 +614,21 @@ It is the responsibility of the other components of the game to control how inva ### Blocks -Much like with flow control options may have [blocks of statements](#scope-and-blocks) which are triggered should that option line be chosen. -Each option line may optionally have a block of statements associated with that option line. -Similar again to the flow control, if an option line is selected its associated block of must be processed by the implementing program. -If an option isn't chosen the associated block must not be processed. +Much like with flow control options may have [blocks of statements](#scope-and-blocks) which are triggered--should that option line be chosen--each option line may optionally have a block of statements associated with that option line. +Similar again to the flow control; if an option line is selected, its associated block must be processed by the implementing program. +If an option isn't chosen, the associated block must not be processed. -Unlike the flow control however there is no clear way to tell apart different blocks and options from other parts of the Yarn, instead indentation is used to determine blocks and the end of the options. +Unlike the flow control, however, there is no clear way to tell apart different blocks and options from other parts of the Yarn, instead indentation is used to determine blocks and the end of a set of options. The rules for this must be followed: The first option line in the options determines the base indentation for the options statement, this is determined by counting the number of [whitespace](#whitespace) elements before the `->` symbol. Any statements following the option line at a greater level of indentation counts as part of the block for that option line. Any other options lines with the same indentation is considered a new option line and closes the block for the preceeding option. -These rules are repeated for each option line until a non-option line with the same, or less indentation than the base indentation is encountered which closes the block and the option statement entirely. +These rules are repeated for each option line until a non-option line with the same, or less indentation than the base indentation is encountered, which closes the block and the option statement entirely. Options can be nested inside option blocks. -Not every option line needs to have blocks. +Not every option line needs to have a block. The maximum number of supported indentation of options inside a block is unspecified. ![](railroads/option_block.svg) @@ -646,15 +643,19 @@ If there is a need to choose one, tabs should be preferred due to their improved ### Examples -``` +Basic dialogue options: + +```yarn -> Hi -> Hi {$name} ``` The above is an example of an option with two choices for the player to make. -The first is a regular lines of dialogue, the second is an interpolated line of dialogue. +The first is a line of raw dialogue, the second is a line of interpolated dialogue. -``` +Options with conditionals: + +```yarn -> Hi -> Hi Fred < 3>> ``` @@ -663,7 +664,9 @@ The above is an example of an option with two choices for the player to make. Both have regular lines of dialogue. The second has a conditional component, the validity of the second option line will be `true`. -``` +Options with blocks: + +```yarn -> Hi So, are we doing this? Yes, lets. @@ -673,16 +676,19 @@ The second has a conditional component, the validity of the second option line w Alright! ``` -The above is an example of an option with two choices and another line of dialogue after the option. +The above is an example of an option with two choices, and another line of dialogue after the option. Both are a regular lines of dialogue and both have an attached block. If the first option was selected then the lines to be presented would be as follows: -``` + +```yarn So, are we doing this? Yes, lets. Alright! ``` -``` +Options with nested options: + +```yarn -> Hi Fred What's the plan? We're doing it. @@ -696,7 +702,9 @@ The above is an example of an option with nested options in its block. The `Alright` and `Ok` option lines are inside the `Hi Fred` option line's block. The `Yep` line would only ever be presented if the `Hi Fred` option was selected and then the `Alright` option was selected after that. -``` +Putting it all together: + +```yarn -> Hi -> Hi Fred < 3>> what's the plan? @@ -716,7 +724,7 @@ _Expressions_ are mathematical chains of values, variables, functions, expressio Expressions are not a statement but are a component of various statements and must only be used as part of a statement, they cannot exist in isolation. This means if you do want to show the result of an expression it will have to be wrapped inside an interpolated dialogue statement. -For example a line that is just `$numberOfCoins + 1` while a valid line of [dialogue](#dialogue-statement) is not going to give the result of the expression, but `{$numberOfCoins + 1}` is a valid line of dialogue that will present the result of that expression. +For example, a line that is just `$numberOfCoins + 1`, while a valid line of [dialogue](#dialogue-statement), is not going to give the result of the expression, but `{$numberOfCoins + 1}` will present the result as a line of dialogue. Expressions are mostly used to control the flow of the [if statement](#if), although they are also used as part of [set](#set) and [declare](#declare) statements, and in [interpolated dialogue](#interpolated-dialogue). @@ -725,7 +733,7 @@ Expressions are mostly used to control the flow of the [if statement](#if), alth ### Values A _Value_ is a single concrete form of one of the supported types. -All expressions, subexpressions, variables and functions, must resolve down into a value before it can be used. +All expressions, subexpressions, variables and functions, must resolve to a value before they can be used. Examples of values include `1`, `true`, `"General Kenobi"`. ### Supported Types @@ -760,7 +768,7 @@ If a number is beyond the precision supported by the implementing program, the p The following are examples of valid numbers in Yarn: -``` +```yarn 1 0.5 -1 @@ -770,7 +778,7 @@ The following are examples of valid numbers in Yarn: The following are examples of invalid numbers in Yarn: -``` +```yarn .5 1. - 1 From 4040e09aef2934baf5b250b247423a92fc7062a1 Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 15:38:51 +1000 Subject: [PATCH 29/39] First pass --- Documentation/Yarn-Spec.md | 66 ++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 35 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 0834aa563..2050ac6ef 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -779,32 +779,27 @@ The following are examples of valid numbers in Yarn: The following are examples of invalid numbers in Yarn: ```yarn -.5 -1. -- 1 -1. 414 +.5 // no integer part to the number +1. // a decimal separator but no fractional part +- 1 // space between the negation indicator and the integer part +1. 414 // space between the decimal separator and the fractional part ``` -The first of these is invalid because it does not have an integer part to the number. -The second is invalid because it has a decimal seperator but doesn't have a fractional part. -The third is invalid because it has a space between the negation indicator and the integer part. -The forth is invalid because it has a space between the decimal seperator and the fractional part. - #### Strings -Strings are an ordered collection of characters and must be capable of holding [UTF-8 characters](https://en.wikipedia.org/wiki/UTF-8) as this is what the Yarn language is written in, but the internals of this is unspecified provided all valid UTF-8 strings are supported. +Strings are an ordered collection of characters and must be capable of holding [UTF-8 characters](https://en.wikipedia.org/wiki/UTF-8), as this is what the Yarn language is written in, but the internals of this is unspecified--provided all valid UTF-8 strings are supported. The minimum and maximum lengths of strings are unspecified but if the implementing program cannot support a string it must present this as an error. Strings in expressions must be encapsulated between `"` and `"` symbols. #### Booleans Booleans must be capable of representing the boolean logic values of `true` and `false`, however the specific implementation is undefined. -Booleans must not be exposed as `1` and `0` to expressions even if they are represented this way internally by the implementing program. +Booleans must not be exposed to expressions as `1` and `0`--or similar intermediate representations--even if they are represented this way internally by the implementing program. Booleans in expressions must be written as `true` for true and `false` for false. #### Additional Types -Additional types supported by an implementing program are unspecified but should not be used. +Additional types supported by an implementing program should not be used. ### Variables @@ -816,7 +811,7 @@ A variable encountered outside of an expression must not be considered by the im All variables are a variant on [identifiers](#identifiers). Variables are an identifier that start with a `$` symbol and otherwise follow all other identifier rules. -The minimum and maximum length of a variable name is unspecified but must be at least one character after the `$` symbol. +The maximum length of a variable name is unspecified, but the minimum is one character after the `$` symbol. Variable names must be unique throughout their scope. The _scope_ of the variable is what defines for how long a variable exists. @@ -828,11 +823,13 @@ The scope of a variable must be global across the project. #### Types Yarn is a statically typed language, in the context of Yarn this means variables have a type which represents which of the supported type's values it can hold. -Once a variable has its type determined either by declaration or inference it cannot change. -The implementing program must not allow variables to hold values of types different from its own. +Once a variable has its type determined--whether by explicit declaration or inference--it cannot change. +The implementing program must not allow variables to hold values of a type different from what the type specified or the value provided when the variable was declared. + +Due to some elements being outside of the control of Yarn--notably functions--it is also possible for this requirement to be breached due to no fault of the implementing program or the Yarn as written by the author. +For example, a variable may be assigned the return value of a function whose specifics are not known to Yarn--causing an issue that may not be identified until runtime. -Due to the nature of elements of Yarn being outside of the control of Yarn, notably functions, its possible for this requirement to be breached due to no fault of the implementing program or the Yarn as written by the author. -However in these circumstances the implementing program must generate an error. +No matter the cause, if a variable is assigned a value that does not match its declared type, the implementing program must generate an error. ### Operations @@ -870,15 +867,14 @@ The unary operations are: - minus: `-` - boolean NOT: `!` -Parentheses are a special form of operation. -They are for bundling up elements of an expression into a subexpression. -Parentheses must be treated as if they are a single operand in other operations. -Parentheses start with the open bracket symbol `(` and can have any expression inside of them before being closed with the closing bracket symbol `)`. -`2 * (3 + $coins)` is an example of an expression with a parentheses operation, in this case the `3 + $coins` component must be resolved into a value before being able to be multiplied by two. +Parentheses are used to bundle up some elements of an expression into a subexpression. +Parentheses start with the open parenthesis symbol `(` and can have any expression inside of them before being closed with the closing parenthesis symbol `)`. +Parenthetical subexpressions must be evaluated to a single value before being treated as a single operand in the enclosing expression. +For example, in the expression `2 * (3 + $coins)`, the `3 + $coins` component must be resolved into a value before being able to be multiplied by two. -The `+` operator when operating on strings represesnt concatenation, the merging of two strings by appending the r-value string to the end of the l-value string. +The `+` operator, when operating on strings, represesnt concatenation: the merging of two strings by appending the r-value string to the end of the l-value string. When operating on numbers the `+` operator is the normal addition operator. -All other operators act according to their already existing arithmetic or logical operations. +All other operators act according to their existing arithmetic or logical operations. #### Supported types in operations @@ -898,9 +894,9 @@ The following table shows the compatible types for each unary operation and must | strings | ❌ | ❌ | | booleans | ✅ | ❌ | -Operations between different or incompatible types is unspecified but should not be supported due to the potential confusion. -If however they are supported existing behaviour around transitivity, commutativity, and symmetry of operations should be respected. -For example if `"hello" < 5` is `true` then `5 > "hello"` should also be `true`. +Operations between different or incompatible types is unspecified but should not be supported, due to the potential for confusion. +If they are supported (against recommendation), existing behaviour around transitivity, commutativity, and symmetry of operations should be respected. +For example if `"hello" < 5` is `true` then `5 > "hello"` should also be `true` and `"hello" >= 5` should be `false`. Likewise `("hello" + 2) < 5` resulted in `true` then `(2 + "hello") < 5` should also be `true`. This taken to the extreme should mean that `1 + "hello" == "hello + 1` should evaluate to `true` which is confusing to most people, hence the recommendation against supporting operations between disparate types. @@ -930,7 +926,7 @@ If there are any equal priority operations in an expression they are resolved le ### Functions _Functions_ are an alternate way of getting values into expressions. -Functions are intended to be used to allow more complex code be bundled and called in a different environment, such as in the game itself. +Functions are intended to be used to allow more complex code to be bundled and called in a different environment, such as in the game itself. Functions must return a value. ![](railroads/function.svg) @@ -940,7 +936,7 @@ Functions must return a value. Functions are comprised of a name, parentheses, and parameters. The function _name_ is an [identifier](#identifiers). -The minimum and maximum length of function names is unspecified. +Thus, the minimum length is one character and the maximum length of a function name is unspecified. The parentheses go after the function name and there must be no whitespace between the opening parentheses `(` and the function name. The closing parethensis `)` finishes the function. @@ -949,8 +945,8 @@ _Parameters_ go in between the opening `(` and closing `)` parentheses. Parameters must be expressions, functions, values, or variables. Functions can have multiple parameters, these must be separated by the comma `,` symbol. -Whitespace between parameters and the separator is undefined but newlines characters are must not be allowed. -The maximum and minimum number of allowed parameters a function can have is undefined. +Whitespace between parameters and the separator is undefined, but newline characters must not be allowed. +The minimum number of allowed parameters a function can have is zero (empty parentheses), and the maximum is undefined. Examples of functions include the following; @@ -964,10 +960,10 @@ rad2Deg(1.5707963268) The handling of functions by the implementing program is unspecified, however the output type of a function must always return the same type of value between calls at runtime. Yarn functions are assumed to be non-blocking and effectively instantly returning, the implementing program should adhere to this. -If given the same input parameters multiple invocations of the same functions should return the same value each time. +If given the same input parameters, multiple invocations of the same functions should return the same value each time. The implementing program should allow external parts of the game to provide the return value of the function. -The implementing program must present and process the parameters to whatever handles the function in the same order as they are presented in the Yarn. +The implementing program must pass function parameters to these delegate systems in the same order as they are presented in the Yarn at the function call site. +However, Yarn makes no promises as to the order in which, or number of times an implementing program may call functions; the results of function calls may be cached or called ahead of time. -Yarn makes no promises as to the order in which, or number of times an implementing program may call functions, the results of function calls may be cached or called ahead of time. -In general, and while not a specific requirement, implementing programs and writers should err on the side of treating functions in Yarn as if they are [pure functions](https://en.wikipedia.org/wiki/Pure_function). +In general, and while not a specific requirement, implementing programs and writers should err on the side of treating functions in Yarn as if they are [pure functions](https://en.wikipedia.org/wiki/Pure_function). \ No newline at end of file From c34b41ee48439c82672d4410d4444023f8d0cd17 Mon Sep 17 00:00:00 2001 From: Mars Buttfield-Addison Date: Tue, 28 Sep 2021 15:48:27 +1000 Subject: [PATCH 30/39] Spellcheck --- Documentation/Yarn-Spec.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 2050ac6ef..3d696df8c 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -25,7 +25,7 @@ A component of this is the creation of this specification guide, so implementati We hope this will empower others to make their mark on the broader Yarn Spinner ecosystem, by supporting the creation of new tools or bridging frameworks to bring Yarn Spinner to a broader range of game engines and workflows. Despite this being the first time a Yarn language specification has existed, it is version 2 of the Yarn language and will begin versioning at 2.0. -This is to avoid confusion that would arise should the Yarn languge specification and the Yarn Spinner framework be versioned separately. +This is to avoid confusion that would arise should the Yarn language specification and the Yarn Spinner framework be versioned separately. ### Coverage @@ -59,7 +59,7 @@ _Should_ is a recommendation, albeit a strong one. _Errors_ are mentioned multiple times and represent situations that are **unrecoverable**. A goal of Yarn is to have all errors known and handled at creation time instead of runtime but this isn't always possible. -Errors are intended to allow the implementing program to let the user, or other parts of the game, know that an unrecoverable situation has occured. +Errors are intended to allow the implementing program to let the user, or other parts of the game, know that an unrecoverable situation has occurred. This means the implementing program **must abort** after creating an error. The precise handling of errors will be specific to the implementing program, but should use whatever error mechanisms exist already. For example, Yarn Spinner throws normal C# exceptions for its errors. @@ -74,7 +74,7 @@ These provide a visual means of understanding the rules presented here to aid in The diagrams are to be read left to right, following the lines until you hit the end of the rule. Each time you encounter an element in the path that element must be represented in the raw text of the Yarn file for the rule to be valid. White elements are more complex rules, grey elements are literals either by name for convenience or if they are encapsulated inside single quotes `'` they are a string literal as described above. -Lines may loop back or skip over elements, and every path through the diagram decribes a valid version of the rule. +Lines may loop back or skip over elements, and every path through the diagram describes a valid version of the rule. The diagrams at various stages use ranges to represent all potential values within that range. Common uses of this include being able to capture the digits `0, 1, 2, 3, 4, 5, 6, 7, 8, 9`, as `[0-9]`. @@ -145,7 +145,7 @@ Identifiers are mentioned at various points in this document, and the rules for An *identifier* is built up of two main parts: -1. the *identifier head* which is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a noncombining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. +1. the *identifier head* which is any of the following symbols: an upper or lowercase letter A to Z, an underscore (`_`), a non-combining alphanumeric Unicode character in the Basic Multilingual Plane, or a character outside the Basic Multilingual Plane that isn't in the Private Use Area. 2. (after the identifier head) any number of *identifier characters* are allowed, which may be any of the identifier head symbols, as well as digits, the period (`.`), and combining Unicode characters. The `$` symbol must not be part of an identifier. @@ -222,7 +222,7 @@ The program should flag this as an error. Duplicate header tags within a node is invalid. A duplicate tag is a duplicate if it has the same tag name as another. The implementing program must either throw an error when encountering a duplicate tag or ignore all but the first instance of a tag. -If the implementing program is ignoring later duplicates then the user should still be informed as the existence of duplicate tags. +If the implementing program is ignoring later duplicates, the user should still be informed of the existence of duplicate tags. ### Body @@ -239,7 +239,7 @@ A body must have at least one statement. ![](railroads/body.svg) ![](railroads/statement.svg) -The body ends when encountering a line that consists entirely of the *body delimter* `===`. +The body ends when encountering a line that consists entirely of the *body delimiter* `===`. The body delimiter ends both the current node and the body of that node. The end of file must not be used in place of a body delimiter. @@ -417,7 +417,7 @@ The value of the expression is used determine what type the value is to be decla The implementing program must not allow the variable declared to ever have a value set which is not of the declared type. If this does occur the implementing program must flag this as an error. An interpreter may elect to statically analyse a Yarn script an insert the necessary declare commands as part of a build or compile process but once the script is run, encountering variables which have not been declared by some means should generate an error. -The delcare command should only be used to set the initial value of a variable; encountering a declare command for a variable that has already been declared should generate an error, even if the resulting [type](#supported-types) is the same as that declared previously. +The declare command should only be used to set the initial value of a variable; encountering a declare command for a variable that has already been declared should generate an error, even if the resulting [type](#supported-types) is the same as that declared previously. ![](railroads/declare.svg) @@ -425,15 +425,15 @@ The delcare command should only be used to set the initial value of a variable; It is assumed that most of the time a variable's type will be determined implicitly via the initial expression, however the type can also be explicitly set. Syntactically this works identically to the implicit type declaration with two additional elements at the end of the command, the `as` keyword and a type. -The type of the expression must match one of the [suported types](#supported-types) keywords: +The type of the expression must match one of the [supported types](#supported-types) keywords: - `String` for Strings - `Number` for Numbers - `Bool` for Booleans `<>` is an example of an explicitly typed declaration. -Explicitly typed declarations will most likely be used when getting intial values from [functions](#functions) who's type is undefined. -The default value's type given in an explictly typed declaration must match the type, for example `<>` is an invalid declaration because `"General Kenobi"` isn't a `Number`. +Explicitly typed declarations will most likely be used when getting initial values from [functions](#functions) whose type is undefined. +The type of the default value given in an explicitly typed declaration must match the stated type, for example `<>` is an invalid declaration because `"General Kenobi"` isn't a `Number`. If additional types are in use by the implementing program, the keywords for their explicit definition are unspecified, but they must be consistent across all declarations. @@ -494,7 +494,7 @@ The expression must resolve to a [boolean value](#supported-types). The `elseif` will run only if the `if` component and any other `elseif`s before it evaluated to false, and if its own expression evaluates to true. -The minimum mumber of required elseif commands must be zero. +The minimum number of required elseif commands must be zero. The maximum number of allowed elseif commands in a flow control statement is unspecified but must be greater than one. An elseif command must not exist without an if command and must go after the if command. @@ -543,7 +543,7 @@ While it is common for writers to indent their blocks relative to their scope it The implementing program must process all statements within the active block's scope. The _active block_ is the block of Yarn who's command expression evaluates to `true`. -The block associated with the else command, if present, must only be determined as the active block if all other blocks expressions evaluate to false. +The block associated with the else command, if present, must only be determined as the active block if all other blocks' expressions evaluate to false. An implementing program must not process any statements inside a block that is not the active block. An implementing program must only have, at most, one active block. @@ -551,7 +551,7 @@ If no block's expression evaluates to true then no block must be processed. #### Ambiguity -Because the flow control commands allow for potentially multiple commands and their blocks to be the true one, the implementing program must select them in a top down approach when there is conflicting flow. +Because the flow control commands allow for potentially multiple commands and their blocks to be true simultaneously, the implementing program must select them in a top down approach wherever there is ambiguity. For example take the following flow control: ```yarn @@ -566,7 +566,7 @@ For example take the following flow control: <> ``` -Both of the elseif commands expressions evaluate to true, so either ones attached block could be run and seen to be correct. +Both of the elseif commands' expressions evaluate to true, so either one's attached block could be run and seen to be correct. However because one is above the other the block with `elseif-1-scope` dialogue inside would be the selected one. If multiple commands evaluate the result of the same variable or expression, the implementing program should attempt to identify this and alert the writer. @@ -872,7 +872,7 @@ Parentheses start with the open parenthesis symbol `(` and can have any expressi Parenthetical subexpressions must be evaluated to a single value before being treated as a single operand in the enclosing expression. For example, in the expression `2 * (3 + $coins)`, the `3 + $coins` component must be resolved into a value before being able to be multiplied by two. -The `+` operator, when operating on strings, represesnt concatenation: the merging of two strings by appending the r-value string to the end of the l-value string. +The `+` operator, when operating on strings, represents concatenation: the merging of two strings by appending the r-value string to the end of the l-value string. When operating on numbers the `+` operator is the normal addition operator. All other operators act according to their existing arithmetic or logical operations. @@ -898,7 +898,7 @@ Operations between different or incompatible types is unspecified but should not If they are supported (against recommendation), existing behaviour around transitivity, commutativity, and symmetry of operations should be respected. For example if `"hello" < 5` is `true` then `5 > "hello"` should also be `true` and `"hello" >= 5` should be `false`. Likewise `("hello" + 2) < 5` resulted in `true` then `(2 + "hello") < 5` should also be `true`. -This taken to the extreme should mean that `1 + "hello" == "hello + 1` should evaluate to `true` which is confusing to most people, hence the recommendation against supporting operations between disparate types. +This taken to the extreme should mean that `1 + "hello" == "hello + 1` should evaluate to `true`. This is confusing, hence the recommendation against supporting operations between disparate types. #### Operation Output @@ -938,8 +938,8 @@ Functions are comprised of a name, parentheses, and parameters. The function _name_ is an [identifier](#identifiers). Thus, the minimum length is one character and the maximum length of a function name is unspecified. -The parentheses go after the function name and there must be no whitespace between the opening parentheses `(` and the function name. -The closing parethensis `)` finishes the function. +The parentheses go after the function name and there must be no whitespace between the opening parenthesis `(` and the function name. +The closing parethesis `)` finishes the function. _Parameters_ go in between the opening `(` and closing `)` parentheses. Parameters must be expressions, functions, values, or variables. From 3360d919f95d2655a61d25c7931d9caa926e7c44 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Wed, 29 Sep 2021 12:13:59 +1000 Subject: [PATCH 31/39] removed partial versioning --- Documentation/Yarn-Spec.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 3d696df8c..1288df0f4 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -1,7 +1,7 @@ # Yarn Spec -*Language version 2.0 | Last updated: 28th September 2021* +*Language version 2 | Last updated: 29th September 2021* -This document defines the Yarn Script version 2 language format, and contains guidance and rules for implementing programs to process Yarn 2.x scripts. +This document defines the Yarn Script version 2 language format, and contains guidance and rules for implementing programs to process Yarn 2 scripts. ## Introduction @@ -24,7 +24,7 @@ A concerted effort was made to clean up the Yarn language for Yarn Spinner 2.0 i A component of this is the creation of this specification guide, so implementations of alternative interpreters or other Yarn- or Yarn Spinner-related tools can have a clear source of truth (that isn't "just copy what Yarn Spinner does"). We hope this will empower others to make their mark on the broader Yarn Spinner ecosystem, by supporting the creation of new tools or bridging frameworks to bring Yarn Spinner to a broader range of game engines and workflows. -Despite this being the first time a Yarn language specification has existed, it is version 2 of the Yarn language and will begin versioning at 2.0. +Despite this being the first time a Yarn language specification has existed, it is version 2 of the Yarn language. This is to avoid confusion that would arise should the Yarn language specification and the Yarn Spinner framework be versioned separately. ### Coverage From b6a5a98b6c2c0ef10c970197cccb9d8de3b37129 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Wed, 29 Sep 2021 12:16:41 +1000 Subject: [PATCH 32/39] softened the wording around comments. As it was it implied that escaped text needed to be handled inside of comments, when what we want to say is you can escape comments if you need to. --- Documentation/Yarn-Spec.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 1288df0f4..9011c8d2e 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -137,7 +137,7 @@ All text from the start of the comment to the end of the line must be ignored. A comment starting in the middle of another line ends that line at the point the `//` symbol is encountered. That line is assumed to have finished at that point as if the comment was not there. Comments must not impact the rest of the lines or have any impact on the resulting Yarn program. -Comments may occur in any line of a Yarn file and take precedence over any other parsing rules such as [hashtags](#hashtags), but may still be affected by [escaping text](#escaping-text). +Comments may occur in any line of a Yarn file and take precedence over any other parsing rules such as [hashtags](#hashtags), but may still be [escaped](#escaping-text). ### Identifiers From 60f0c6830e90a0b16ccfaf8b6714d058ddd61d89 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Wed, 29 Sep 2021 12:19:06 +1000 Subject: [PATCH 33/39] Its an error, not unspecified when you a repeated title within a file --- Documentation/Yarn-Spec.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 9011c8d2e..7c7b39d3e 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -209,10 +209,11 @@ The order of header tags is unspecified. The *title tag* is a specific header tag that uniquely identifies the node. The tag name for the title tag must be `title`. The tag text for the title tag must be unique within the file. +It is an error for a title text to be repeated within a file. The tag text for the title tag should be unique within the project. The tag text must follow the rules of [identifiers](#identifiers). -The behaviour of the program when a title tag's text is not unique across the file or project is unspecified. +The behaviour of the program when a title tag's text is not unique across the project is unspecified. The program should flag this as an error. ![](railroads/title_tag.svg) From 7b5f3e36189f949033d997b3362975f1310e3acf Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Wed, 29 Sep 2021 13:38:49 +1000 Subject: [PATCH 34/39] Added a small note on string coercion This is a point to come back to I reckon. People may well have opinions on this. --- Documentation/Yarn-Spec.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 7c7b39d3e..adf345589 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -274,7 +274,7 @@ A dialogue statement can contain any characters except for the `#` character. An *interpolated dialogue* is dialogue where there are [expressions](#expressions) in the line. Expressions are encapsulated within the `{` and `}` symbols and it is the presence of these symbols that determine if a line is an interpolated one or not. The expression inside the `{}` symbols must be a valid expression. -The result of the expression must be resolved as a [string value](#supported-types) to be inserted into the dialogue. +The result of the expression must be [coerced](#string-coercion) into a [string value](#supported-types) to be inserted into the dialogue. Other than replacing expressions, dialogue statements must not be modified by the implementing program, and provided to the game as written. The encapsulated expression can go anywhere inside the statement, or even be the entire dialogue statement. @@ -798,6 +798,12 @@ Booleans must be capable of representing the boolean logic values of `true` and Booleans must not be exposed to expressions as `1` and `0`--or similar intermediate representations--even if they are represented this way internally by the implementing program. Booleans in expressions must be written as `true` for true and `false` for false. +#### String Coercion + +When used as part of [interpolated](#interpolated-dialogue) dialogue the value must be coerced into a string before they can be shown as a piece of the dialogue. +The process for coercising one type into a string is unspecified. +The only requirement is each value being coerced must appear the same every time it is presented regardless of the expression that creates the value. + #### Additional Types Additional types supported by an implementing program should not be used. From d12a22da7d0b98a3a6883ff5dbe00c7df53378c1 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Wed, 29 Sep 2021 14:05:43 +1000 Subject: [PATCH 35/39] Reworded elseif to hopefully make its optionality clearer --- Documentation/Yarn-Spec.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index adf345589..390369d35 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -495,8 +495,8 @@ The expression must resolve to a [boolean value](#supported-types). The `elseif` will run only if the `if` component and any other `elseif`s before it evaluated to false, and if its own expression evaluates to true. -The minimum number of required elseif commands must be zero. -The maximum number of allowed elseif commands in a flow control statement is unspecified but must be greater than one. +Each flow control can have zero or more elseif commands. +The maximum number of allowed elseifs as a part of flow control is unspecified but must be greater than zero. An elseif command must not exist without an if command and must go after the if command. ![](railroads/elseif.svg) From 00996e3aabae6e1346ab84c55ec87e98bb7d593f Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Thu, 30 Sep 2021 11:28:22 +1000 Subject: [PATCH 36/39] slight tweak to the coercion section --- Documentation/Yarn-Spec.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 390369d35..5ceab558d 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -1,5 +1,5 @@ # Yarn Spec -*Language version 2 | Last updated: 29th September 2021* +*Language version 2 | Last updated: 30th September 2021* This document defines the Yarn Script version 2 language format, and contains guidance and rules for implementing programs to process Yarn 2 scripts. @@ -801,7 +801,11 @@ Booleans in expressions must be written as `true` for true and `false` for false #### String Coercion When used as part of [interpolated](#interpolated-dialogue) dialogue the value must be coerced into a string before they can be shown as a piece of the dialogue. -The process for coercising one type into a string is unspecified. + +Strings do not require coercion and must be injected into the dialogue as is. +The only requirement for strings being added into dialogue is that it must not include the encapsulating `"` symbols. + +The process for coercising numbers and booleans into a string is unspecified. The only requirement is each value being coerced must appear the same every time it is presented regardless of the expression that creates the value. #### Additional Types From e600560302b33d955e33b981d51f8d8c75ebaa81 Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Thu, 30 Sep 2021 15:52:01 +1000 Subject: [PATCH 37/39] Rephrased the declare statement section. As it previously existed while it was a valid approach and technically what we do in Yarn Spinner it was very rigid and requires a two pass approach. There is no reason that a fully type inferred version of Yarn doing this all line by line at runtime couldn't exist (assuming people use variables) properly and this would require no declarations. The errors still exist for using variables that don't match their type. --- Documentation/Yarn-Spec.md | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Documentation/Yarn-Spec.md b/Documentation/Yarn-Spec.md index 5ceab558d..efdf60c91 100644 --- a/Documentation/Yarn-Spec.md +++ b/Documentation/Yarn-Spec.md @@ -394,8 +394,10 @@ The set command must not allow setting a variable to an expression whose value i ### Declare -[Variables](#variables) in Yarn must be declared before they are used, to let the implementing program know the [type](#supported-types) of values they hold. -The intent of this is to allow the implementing program to set up memory, and to provide guidance as to the usage of a variable directly from the writer. +Declare is a command that works on [variable](#variables) to provide guidance as to the usage of the variable, both for the writer and the implementing program. +Yarn is a [statically typed](#static-types) language so every variable has a type associated with it which determines what [type](#supported-types) of values it is allowed to hold. +This means variables need have this determined before they can be used, the declare command is one means of doing this. + The declare command has four components: the keyword, the variable, the operator and the value, and must be presented in that order. Each component must be separated by one or more whitespace characters. @@ -417,8 +419,11 @@ The value of the expression is used determine what type the value is to be decla The implementing program must not allow the variable declared to ever have a value set which is not of the declared type. If this does occur the implementing program must flag this as an error. -An interpreter may elect to statically analyse a Yarn script an insert the necessary declare commands as part of a build or compile process but once the script is run, encountering variables which have not been declared by some means should generate an error. -The declare command should only be used to set the initial value of a variable; encountering a declare command for a variable that has already been declared should generate an error, even if the resulting [type](#supported-types) is the same as that declared previously. + +A variable may only be declared once in a program, duplicate declarations are not allowed. +A duplicate declaration is where the variable component of the declaration is idential to another declarations. +The implementing program must flag any duplicate variable declarations as an error. +This is true even if the declaration is identical or not in conflict with the use of the variable. ![](railroads/declare.svg) @@ -831,16 +836,24 @@ The scope of a variable must be global across the project. `$name` is an example of a variable name, `$𐃩` is another example of a variable name. -#### Types +#### Static Types Yarn is a statically typed language, in the context of Yarn this means variables have a type which represents which of the supported type's values it can hold. +Implementing programs have two means at their disposal to determine a variables type, inference and declaration. + +Declaration is an explicit action by the writer and is the result of the [declare](#declare) command. +Inference is when the implementing program observes the use of a variable and infers its type based on this. +The majority of the time it is expected that inference will be the preferred means of determining the type of a variable. +Declaration takes precedence over inference, even in cases where the inference correctly determines the variable type and the declaration is in conflict with this. +Declaration is allowed even if it is only formalising the same result the inference would provide. + Once a variable has its type determined--whether by explicit declaration or inference--it cannot change. -The implementing program must not allow variables to hold values of a type different from what the type specified or the value provided when the variable was declared. +The implementing program must not allow variables to hold values of a type different from what the type specified or the value provided when the variable type was determined. Due to some elements being outside of the control of Yarn--notably functions--it is also possible for this requirement to be breached due to no fault of the implementing program or the Yarn as written by the author. For example, a variable may be assigned the return value of a function whose specifics are not known to Yarn--causing an issue that may not be identified until runtime. -No matter the cause, if a variable is assigned a value that does not match its declared type, the implementing program must generate an error. +No matter the cause, if a variable is assigned a value that does not match its associated type, the implementing program must generate an error. ### Operations From 4791416716ce6a7eb48fccd1bbfec3f490ff622e Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Thu, 30 Sep 2021 15:54:12 +1000 Subject: [PATCH 38/39] Replaced function railroad diagram The previous one technically required at least one parameter --- Documentation/railroads/function.svg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/railroads/function.svg b/Documentation/railroads/function.svg index d47bbcaf7..abe55cd6d 100644 --- a/Documentation/railroads/function.svg +++ b/Documentation/railroads/function.svg @@ -1,6 +1,6 @@ - + -IDENTIFIER'('expression','expression')' \ No newline at end of file +IDENTIFIER'('expression','expression')' \ No newline at end of file From 9275277f50a6acbe8438b29596acc8527cf5581a Mon Sep 17 00:00:00 2001 From: Tim Nugent Date: Fri, 1 Oct 2021 10:33:48 +1000 Subject: [PATCH 39/39] Updated title tag, previously it was an almost duplicate of header tags --- Documentation/railroads/title_tag.svg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/railroads/title_tag.svg b/Documentation/railroads/title_tag.svg index 6bff73edf..5f8ee13bb 100644 --- a/Documentation/railroads/title_tag.svg +++ b/Documentation/railroads/title_tag.svg @@ -1,6 +1,6 @@ - + -IDENTIFIER':'IDENTIFIERNEWLINE \ No newline at end of file +'title'':'IDENTIFIERNEWLINE \ No newline at end of file