grammar InkBlotAntlrGrammar; import InkBlotAntlrLexer; /* * STORY */ story: topLevelStatements ; /* * STATEMENTS FOR THE VARIOUS LEVELS */ topLevelStatements: topLevelStatement+ ; topLevelStatement: contentText | multiDivert ; knotLevelStatements: (contentText | multiDivert )+ ; stitchLevelStatements: (contentText | multiDivert )+ ; innerBlockLevelStatements: (contentText | multiDivert )+ ; /* * STATEMENTS */ contentText: CONTENT_TEXT_NO_ESCAPE_SIMPLE ; mixedTextAndLogic: // TODO: ~ is not allowed as first symbol of this (see InkParser_Content => MixedTextAndLog), let's implement it in the C# side? // like in innerInlineSequenceObjects, a bit of a chaos to avoid having completely empty entries contentText? (inlineLogicOrGlueOrTagStart? contentText | inlineLogicOrGlueOrTagStart contentText?)+ // TODO: this is valid only when not parsing a choice, see above for the code where this logic is implemented multiDivert // TODO: management of tag ftw O_O ; inlineLogicOrGlueOrTagStart: inlineLogic // TODO: glue, tag start ; inlineLogic: INLINE_LOGIC_START WS? innerLogic // TODO: += and -= are disabled here (don't know why) WS? INLINE_LOGIC_END // TODO: tags ftw ; innerLogic: WS? sequenceTypeAnnotation innerSequenceObjects // TODO: the rest of InkParser_Logic => InnerLogic ; multiDivert: WS? ( THREAD_ARROW divertIdentifierWithArguments // here be dragons: trying to express the various "Possible patterns" of InkParser_Divert => MultiDivert | (DIVERT_ARROW divertIdentifierWithArguments)+ TUNNEL_ARROW divertIdentifierWithArguments | (DIVERT_ARROW divertIdentifierWithArguments)+ TUNNEL_ARROW | (DIVERT_ARROW divertIdentifierWithArguments)+ DIVERT_ARROW | TUNNEL_ARROW | DIVERT_ARROW // TODO: this is only valid in default choices ( https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md#fallback-choices ) ) ; divertIdentifierWithArguments: WS? identifier WS? ('.' WS? identifier WS? )* WS? ( '(' expression (',' expression)* ')' )? WS? ; identifier: // TODO: reject numbers-only identifier - see InkParser_Logic => Identifier IDENTIFIER ; expression: // TODO: temporary stuff here IDENTIFIER ; // all possible symbols or word(s) for sequencing sequenceTypeAnnotation: op=SEQUENCE_TYPE_SYMBOL_ANNOTATION | ONCE | CYCLE | SHUFFLE | STOPPING | SHUFFLE_ONCE | SHUFFLE_STOPPING ; /* a list of sequence objects, either compressed in a single line (e.g.: {a|b|c}) or expanded in multiple lines (e.g.: {\n- a\n- b\n- c} */ innerSequenceObjects: NL innerMultilineSequenceObjects | innerInlineSequenceObjects ; innerMultilineSequenceObjects: singleMultilineSequenceElement+ ; singleMultilineSequenceElement: WS? /* TODO: how to express this? and why is it here? InkParser_Sequences => SingleMultilineSequenceElement if (ParseString ("->") != null) return null; */ '-' WS? ( innerBlockLevelStatements | MULTILINE_WS ) ; innerInlineSequenceObjects: // it's a bit chaotic, in order to allow for empty mixedTextAndLogic, but always require at least one entry (mixedTextAndLogic ('|' mixedTextAndLogic?)*) | ('|' mixedTextAndLogic?)+ ;