Files
inkblot/InkBlot/InkBlotAntlrGrammar.g4
2025-03-01 12:30:36 +01:00

172 lines
4.0 KiB
ANTLR

grammar InkBlotAntlrGrammar;
import InkBlotAntlrLexer;
/*
* STORY
*/
story: topLevelStatements ;
/*
* STATEMENTS FOR THE VARIOUS LEVELS
*/
topLevelStatements:
topLevelStatement+
;
topLevelStatement:
multiDivert
| contentText
;
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, maybe because they're statements?)
WS?
INLINE_LOGIC_END
// TODO: tags ftw
;
innerLogic:
WS?
sequenceTypeAnnotation innerSequenceObjects
// TODO: the rest of InkParser_Logic => InnerLogic
;
multiDivert:
WS?
multiDivert_withoutWS
;
multiDivert_withoutWS:
THREAD_ARROW divertIdentifierWithArguments # MultiDivertThread
// here be dragons: trying to express the various "Possible patterns" of InkParser_Divert => MultiDivert
// syntax in the original ink parser is overly concessive: https://discord.com/channels/329929050866843648/329929390358265857/1342130940981284945
| (DIVERT_ARROW divertIdentifierWithArguments)* multiDivertArrows_tail # MultiDivertArrows
// TODO: a single DIVERT_ARROW above is only valid in default choices ( https://github.com/inkle/ink/blob/master/Documentation/WritingWithInk.md#fallback-choices )
// TODO: tags ftw
;
multiDivertArrows_tail:
DIVERT_ARROW # MultiDivertArrows_tailDefaultChoice
| DIVERT_ARROW divertIdentifierWithArguments # MultiDivertArrows_tailDivert
| TUNNEL_ARROW divertIdentifierWithArguments # MultiDivertArrows_tailTunnelWithReplacement
| TUNNEL_ARROW # MultiDivertArrows_tailTunnel
;
divertIdentifierWithArguments:
WS?
divertIdentifierWithArguments_name
WS?
(
'('
expression (',' WS? expression)*
')'
)?
WS?
;
divertIdentifierWithArguments_name:
WS? identifier WS? ('.' WS? identifier WS? )*
;
divertIdentifierWithArguments_arguments:
'('
expression (',' WS? expression)*
')'
;
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?)+
;