mirror of
https://github.com/Ratstail91/Mementos.git
synced 2025-11-29 10:34:27 +11:00
Committed everything
This commit is contained in:
@@ -0,0 +1,206 @@
|
||||
using System.Collections.Generic;
|
||||
using Ink.Parsed;
|
||||
|
||||
|
||||
namespace Ink
|
||||
{
|
||||
public partial class InkParser
|
||||
{
|
||||
protected List<Parsed.Object> MultiDivert()
|
||||
{
|
||||
Whitespace ();
|
||||
|
||||
List<Parsed.Object> diverts = null;
|
||||
|
||||
// Try single thread first
|
||||
var threadDivert = Parse(StartThread);
|
||||
if (threadDivert) {
|
||||
diverts = new List<Object> ();
|
||||
diverts.Add (threadDivert);
|
||||
return diverts;
|
||||
}
|
||||
|
||||
// Normal diverts and tunnels
|
||||
var arrowsAndDiverts = Interleave<object> (
|
||||
ParseDivertArrowOrTunnelOnwards,
|
||||
DivertIdentifierWithArguments);
|
||||
|
||||
if (arrowsAndDiverts == null)
|
||||
return null;
|
||||
|
||||
diverts = new List<Parsed.Object> ();
|
||||
|
||||
// Possible patterns:
|
||||
// -> -- explicit gather
|
||||
// ->-> -- tunnel onwards
|
||||
// -> div -- normal divert
|
||||
// ->-> div -- tunnel onwards, followed by override divert
|
||||
// -> div -> -- normal tunnel
|
||||
// -> div ->-> -- tunnel then tunnel continue
|
||||
// -> div -> div -- tunnel then divert
|
||||
// -> div -> div -> -- tunnel then tunnel
|
||||
// -> div -> div ->->
|
||||
// -> div -> div ->-> div (etc)
|
||||
|
||||
// Look at the arrows and diverts
|
||||
for (int i = 0; i < arrowsAndDiverts.Count; ++i) {
|
||||
bool isArrow = (i % 2) == 0;
|
||||
|
||||
// Arrow string
|
||||
if (isArrow) {
|
||||
|
||||
// Tunnel onwards
|
||||
if ((string)arrowsAndDiverts [i] == "->->") {
|
||||
|
||||
bool tunnelOnwardsPlacementValid = (i == 0 || i == arrowsAndDiverts.Count - 1 || i == arrowsAndDiverts.Count - 2);
|
||||
if (!tunnelOnwardsPlacementValid)
|
||||
Error ("Tunnel onwards '->->' must only come at the begining or the start of a divert");
|
||||
|
||||
var tunnelOnwards = new TunnelOnwards ();
|
||||
if (i < arrowsAndDiverts.Count - 1) {
|
||||
var tunnelOnwardDivert = arrowsAndDiverts [i+1] as Parsed.Divert;
|
||||
tunnelOnwards.divertAfter = tunnelOnwardDivert;
|
||||
}
|
||||
|
||||
diverts.Add (tunnelOnwards);
|
||||
|
||||
// Not allowed to do anything after a tunnel onwards.
|
||||
// If we had anything left it would be caused in the above Error for
|
||||
// the positioning of a ->->
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Divert
|
||||
else {
|
||||
|
||||
var divert = arrowsAndDiverts [i] as Divert;
|
||||
|
||||
// More to come? (further arrows) Must be tunnelling.
|
||||
if (i < arrowsAndDiverts.Count - 1) {
|
||||
divert.isTunnel = true;
|
||||
}
|
||||
|
||||
diverts.Add (divert);
|
||||
}
|
||||
}
|
||||
|
||||
// Single -> (used for default choices)
|
||||
if (diverts.Count == 0 && arrowsAndDiverts.Count == 1) {
|
||||
var gatherDivert = new Divert ((Parsed.Object)null);
|
||||
gatherDivert.isEmpty = true;
|
||||
diverts.Add (gatherDivert);
|
||||
|
||||
if (!_parsingChoice)
|
||||
Error ("Empty diverts (->) are only valid on choices");
|
||||
}
|
||||
|
||||
return diverts;
|
||||
}
|
||||
|
||||
protected Divert StartThread()
|
||||
{
|
||||
Whitespace ();
|
||||
|
||||
if (ParseThreadArrow() == null)
|
||||
return null;
|
||||
|
||||
Whitespace ();
|
||||
|
||||
var divert = Expect(DivertIdentifierWithArguments, "target for new thread", () => new Divert(null)) as Divert;
|
||||
divert.isThread = true;
|
||||
|
||||
return divert;
|
||||
}
|
||||
|
||||
protected Divert DivertIdentifierWithArguments()
|
||||
{
|
||||
Whitespace ();
|
||||
|
||||
List<Identifier> targetComponents = Parse (DotSeparatedDivertPathComponents);
|
||||
if (targetComponents == null)
|
||||
return null;
|
||||
|
||||
Whitespace ();
|
||||
|
||||
var optionalArguments = Parse(ExpressionFunctionCallArguments);
|
||||
|
||||
Whitespace ();
|
||||
|
||||
var targetPath = new Path (targetComponents);
|
||||
return new Divert (targetPath, optionalArguments);
|
||||
}
|
||||
|
||||
protected Divert SingleDivert()
|
||||
{
|
||||
var diverts = Parse (MultiDivert);
|
||||
if (diverts == null)
|
||||
return null;
|
||||
|
||||
// Ideally we'd report errors if we get the
|
||||
// wrong kind of divert, but unfortunately we
|
||||
// have to hack around the fact that sequences use
|
||||
// a very similar syntax.
|
||||
// i.e. if you have a multi-divert at the start
|
||||
// of a sequence, it initially tries to parse it
|
||||
// as a divert target (part of an expression of
|
||||
// a conditional) and gives errors. So instead
|
||||
// we just have to blindly reject it as a single
|
||||
// divert, and give a slightly less nice error
|
||||
// when you DO use a multi divert as a divert taret.
|
||||
|
||||
if (diverts.Count != 1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var singleDivert = diverts [0];
|
||||
if (singleDivert is TunnelOnwards) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var divert = diverts [0] as Divert;
|
||||
if (divert.isTunnel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return divert;
|
||||
}
|
||||
|
||||
List<Identifier> DotSeparatedDivertPathComponents()
|
||||
{
|
||||
return Interleave<Identifier> (Spaced (IdentifierWithMetadata), Exclude (String (".")));
|
||||
}
|
||||
|
||||
protected string ParseDivertArrowOrTunnelOnwards()
|
||||
{
|
||||
int numArrows = 0;
|
||||
while (ParseString ("->") != null)
|
||||
numArrows++;
|
||||
|
||||
if (numArrows == 0)
|
||||
return null;
|
||||
|
||||
else if (numArrows == 1)
|
||||
return "->";
|
||||
|
||||
else if (numArrows == 2)
|
||||
return "->->";
|
||||
|
||||
else {
|
||||
Error ("Unexpected number of arrows in divert. Should only have '->' or '->->'");
|
||||
return "->->";
|
||||
}
|
||||
}
|
||||
|
||||
protected string ParseDivertArrow()
|
||||
{
|
||||
return ParseString ("->");
|
||||
}
|
||||
|
||||
protected string ParseThreadArrow()
|
||||
{
|
||||
return ParseString ("<-");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user