mirror of
https://github.com/Ratstail91/Mementos.git
synced 2025-11-29 02:24:28 +11:00
218 lines
7.4 KiB
C#
218 lines
7.4 KiB
C#
using Ink.Parsed;
|
|
using System.Text;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace Ink
|
|
{
|
|
public partial class InkParser
|
|
{
|
|
void TrimEndWhitespace(List<Parsed.Object> mixedTextAndLogicResults, bool terminateWithSpace)
|
|
{
|
|
// Trim whitespace from end
|
|
if (mixedTextAndLogicResults.Count > 0) {
|
|
var lastObjIdx = mixedTextAndLogicResults.Count - 1;
|
|
var lastObj = mixedTextAndLogicResults[lastObjIdx];
|
|
if (lastObj is Text) {
|
|
var text = (Text)lastObj;
|
|
text.text = text.text.TrimEnd (' ', '\t');
|
|
|
|
if (terminateWithSpace)
|
|
text.text += " ";
|
|
|
|
// No content left at all? trim the whole object
|
|
else if( text.text.Length == 0 ) {
|
|
mixedTextAndLogicResults.RemoveAt(lastObjIdx);
|
|
|
|
// Recurse in case there's more whitespace
|
|
TrimEndWhitespace(mixedTextAndLogicResults, terminateWithSpace:false);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
protected List<Parsed.Object> LineOfMixedTextAndLogic()
|
|
{
|
|
// Consume any whitespace at the start of the line
|
|
// (Except for escaped whitespace)
|
|
Parse (Whitespace);
|
|
|
|
var result = Parse(MixedTextAndLogic);
|
|
|
|
// Terminating tag
|
|
bool onlyTags = false;
|
|
var tags = Parse (Tags);
|
|
if (tags != null) {
|
|
if (result == null) {
|
|
result = tags.Cast<Parsed.Object> ().ToList ();
|
|
onlyTags = true;
|
|
} else {
|
|
foreach (var tag in tags) {
|
|
result.Add(tag);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (result == null || result.Count == 0)
|
|
return null;
|
|
|
|
// Warn about accidentally writing "return" without "~"
|
|
var firstText = result[0] as Text;
|
|
if (firstText) {
|
|
if (firstText.text.StartsWith ("return")) {
|
|
Warning ("Do you need a '~' before 'return'? If not, perhaps use a glue: <> (since it's lowercase) or rewrite somehow?");
|
|
}
|
|
}
|
|
if (result.Count == 0)
|
|
return null;
|
|
|
|
var lastObj = result [result.Count - 1];
|
|
if (!(lastObj is Divert)) {
|
|
TrimEndWhitespace (result, terminateWithSpace:false);
|
|
}
|
|
|
|
// Add newline since it's the end of the line
|
|
// (so long as it's a line with only tags)
|
|
if( !onlyTags )
|
|
result.Add (new Text ("\n"));
|
|
|
|
Expect(EndOfLine, "end of line", recoveryRule: SkipToNextLine);
|
|
|
|
return result;
|
|
}
|
|
|
|
protected List<Parsed.Object> MixedTextAndLogic()
|
|
{
|
|
// Check for disallowed "~" within this context
|
|
var disallowedTilda = ParseObject(Spaced(String("~")));
|
|
if (disallowedTilda != null)
|
|
Error ("You shouldn't use a '~' here - tildas are for logic that's on its own line. To do inline logic, use { curly braces } instead");
|
|
|
|
// Either, or both interleaved
|
|
var results = Interleave<Parsed.Object>(Optional (ContentText), Optional (InlineLogicOrGlue));
|
|
|
|
// Terminating divert?
|
|
// (When parsing content for the text of a choice, diverts aren't allowed.
|
|
// The divert on the end of the body of a choice is handled specially.)
|
|
if (!_parsingChoice) {
|
|
|
|
var diverts = Parse (MultiDivert);
|
|
if (diverts != null) {
|
|
|
|
// May not have had any results at all if there's *only* a divert!
|
|
if (results == null)
|
|
results = new List<Parsed.Object> ();
|
|
|
|
TrimEndWhitespace (results, terminateWithSpace:true);
|
|
|
|
results.AddRange (diverts);
|
|
}
|
|
|
|
}
|
|
|
|
if (results == null)
|
|
return null;
|
|
|
|
return results;
|
|
}
|
|
|
|
protected Parsed.Text ContentText()
|
|
{
|
|
return ContentTextAllowingEcapeChar ();
|
|
}
|
|
|
|
protected Parsed.Text ContentTextAllowingEcapeChar()
|
|
{
|
|
StringBuilder sb = null;
|
|
|
|
do {
|
|
var str = Parse(ContentTextNoEscape);
|
|
bool gotEscapeChar = ParseString(@"\") != null;
|
|
|
|
if( gotEscapeChar || str != null ) {
|
|
if( sb == null ) {
|
|
sb = new StringBuilder();
|
|
}
|
|
|
|
if( str != null ) {
|
|
sb.Append(str);
|
|
}
|
|
|
|
if( gotEscapeChar ) {
|
|
char c = ParseSingleCharacter();
|
|
sb.Append(c);
|
|
}
|
|
|
|
} else {
|
|
break;
|
|
}
|
|
|
|
} while(true);
|
|
|
|
if (sb != null ) {
|
|
return new Parsed.Text (sb.ToString ());
|
|
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Content text is an unusual parse rule compared with most since it's
|
|
// less about saying "this is is the small selection of stuff that we parse"
|
|
// and more "we parse ANYTHING except this small selection of stuff".
|
|
protected string ContentTextNoEscape()
|
|
{
|
|
// Eat through text, pausing at the following characters, and
|
|
// attempt to parse the nonTextRule.
|
|
// "-": possible start of divert or start of gather
|
|
// "<": possible start of glue
|
|
if (_nonTextPauseCharacters == null) {
|
|
_nonTextPauseCharacters = new CharacterSet ("-<");
|
|
}
|
|
|
|
// If we hit any of these characters, we stop *immediately* without bothering to even check the nonTextRule
|
|
// "{" for start of logic
|
|
// "|" for mid logic branch
|
|
if (_nonTextEndCharacters == null) {
|
|
_nonTextEndCharacters = new CharacterSet ("{}|\n\r\\#");
|
|
_notTextEndCharactersChoice = new CharacterSet (_nonTextEndCharacters);
|
|
_notTextEndCharactersChoice.AddCharacters ("[]");
|
|
_notTextEndCharactersString = new CharacterSet (_nonTextEndCharacters);
|
|
_notTextEndCharactersString.AddCharacters ("\"");
|
|
}
|
|
|
|
// When the ParseUntil pauses, check these rules in case they evaluate successfully
|
|
ParseRule nonTextRule = () => OneOf (ParseDivertArrow, ParseThreadArrow, EndOfLine, Glue);
|
|
|
|
CharacterSet endChars = null;
|
|
if (parsingStringExpression) {
|
|
endChars = _notTextEndCharactersString;
|
|
}
|
|
else if (_parsingChoice) {
|
|
endChars = _notTextEndCharactersChoice;
|
|
}
|
|
else {
|
|
endChars = _nonTextEndCharacters;
|
|
}
|
|
|
|
string pureTextContent = ParseUntil (nonTextRule, _nonTextPauseCharacters, endChars);
|
|
if (pureTextContent != null ) {
|
|
return pureTextContent;
|
|
|
|
} else {
|
|
return null;
|
|
}
|
|
|
|
}
|
|
|
|
CharacterSet _nonTextPauseCharacters;
|
|
CharacterSet _nonTextEndCharacters;
|
|
CharacterSet _notTextEndCharactersChoice;
|
|
CharacterSet _notTextEndCharactersString;
|
|
|
|
|
|
|
|
}
|
|
}
|
|
|