private void ExtendIdentifierCharacterRanges(CharacterSet identifierCharSet) { var characterRanges = ListAllCharacterRanges(); foreach (var charRange in characterRanges) { identifierCharSet.AddCharacters(charRange.ToCharacterSet()); } }
// 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, 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); } }
public string ParseCharactersFromCharSet(CharacterSet charSet, bool shouldIncludeChars = true, int maxCount = -1) { if (maxCount == -1) { maxCount = int.MaxValue; } int startIndex = index; // Optimisation from profiling: // Store in temporary local variables // since they're properties that would have to access // the rule stack every time otherwise. int i = index; int cli = characterInLineIndex; int li = lineIndex; int count = 0; while (i < _chars.Length && charSet.Contains(_chars [i]) == shouldIncludeChars && count < maxCount) { if (_chars [i] == '\n') { li++; cli = -1; } i++; cli++; count++; } index = i; characterInLineIndex = cli; lineIndex = li; int lastCharIndex = index; if (lastCharIndex > startIndex) { return(new string (_chars, startIndex, index - startIndex)); } else { return(null); } }
// Note: we allow identifiers that start with a number, // but not if they *only* comprise numbers protected string Identifier() { if (_identifierCharSet == null) { (_identifierCharSet = new CharacterSet()) .AddRange('A', 'Z') .AddRange('a', 'z') .AddRange('0', '9') .Add('_'); // Enable non-ASCII characters for story identifiers. ExtendIdentifierCharacterRanges(_identifierCharSet); } // Parse remaining characters (if any) var name = ParseCharactersFromCharSet(_identifierCharSet); if (name == null) { return(null); } // Reject if it's just a number bool isNumberCharsOnly = true; foreach (var c in name) { if (!(c >= '0' && c <= '9')) { isNumberCharsOnly = false; break; } } if (isNumberCharsOnly) { return(null); } return(name); }
protected object SequenceTypeSymbolAnnotation() { if (_sequenceTypeSymbols == null) { _sequenceTypeSymbols = new CharacterSet("!&~$ "); } var sequenceType = (SequenceType)0; var sequenceAnnotations = ParseCharactersFromCharSet(_sequenceTypeSymbols); if (sequenceAnnotations == null) { return(null); } foreach (char symbolChar in sequenceAnnotations) { switch (symbolChar) { case '!': sequenceType |= SequenceType.Once; break; case '&': sequenceType |= SequenceType.Cycle; break; case '~': sequenceType |= SequenceType.Shuffle; break; case '$': sequenceType |= SequenceType.Stopping; break; } } if (sequenceType == (SequenceType)0) { return(null); } return(sequenceType); }
public string ParseUntil(ParseRule stopRule, CharacterSet pauseCharacters = null, CharacterSet endCharacters = null) { int ruleId = BeginRule(); CharacterSet pauseAndEnd = new CharacterSet(); if (pauseCharacters != null) { pauseAndEnd.UnionWith(pauseCharacters); } if (endCharacters != null) { pauseAndEnd.UnionWith(endCharacters); } StringBuilder parsedString = new StringBuilder(); object ruleResultAtPause = null; // Keep attempting to parse strings up to the pause (and end) points. // - At each of the pause points, attempt to parse according to the rule // - When the end point is reached (or EOF), we're done do { // TODO: Perhaps if no pause or end characters are passed, we should check *every* character for stopRule? string partialParsedString = ParseUntilCharactersFromCharSet(pauseAndEnd); if (partialParsedString != null) { parsedString.Append(partialParsedString); } // Attempt to run the parse rule at this pause point ruleResultAtPause = Peek(stopRule); // Rule completed - we're done if (ruleResultAtPause != null) { break; } else { if (endOfInput) { break; } // Reached a pause point, but rule failed. Step past and continue parsing string char pauseCharacter = currentCharacter; if (pauseCharacters != null && pauseCharacters.Contains(pauseCharacter)) { parsedString.Append(pauseCharacter); if (pauseCharacter == '\n') { lineIndex++; } index++; continue; } else { break; } } } while(true); if (parsedString.Length > 0) { return((string)SucceedRule(ruleId, parsedString.ToString())); } else { return((string)FailRule(ruleId)); } }
public string ParseUntilCharactersFromCharSet(CharacterSet charSet, int maxCount = -1) { return(ParseCharactersFromCharSet(charSet, false, maxCount)); }
public CharacterSet(CharacterSet charSetToCopy) { AddCharacters(charSetToCopy); }