- using System.Collections.Generic;
- using System.Linq;
- using Ink.Parsed;
- namespace Ink
- {
- public partial class InkParser
- {
- protected Parsed.Object LogicLine()
- {
- Whitespace ();
- if (ParseString ("~") == null) {
- return null;
- }
- Whitespace ();
-
-
-
-
-
-
-
-
- ParseRule afterTilda = () => OneOf (ReturnStatement, TempDeclarationOrAssignment, Expression);
- var result = Expect(afterTilda, "expression after '~'", recoveryRule: SkipToNextLine) as Parsed.Object;
-
- if (result == null) return new ContentList();
-
-
-
-
-
-
- if (result is Expression && !(result is FunctionCall || result is IncDecExpression) ) {
-
- var varRef = result as VariableReference;
- if (varRef && varRef.name == "include") {
- Error ("'~ include' is no longer the correct syntax - please use 'INCLUDE your_filename.ink', without the tilda, and in block capitals.");
- }
- else {
- Error ("Logic following a '~' can't be that type of expression. It can only be something like:\n\t~ return\n\t~ var x = blah\n\t~ x++\n\t~ myFunction()");
- }
- }
-
-
-
-
- var funCall = result as FunctionCall;
- if (funCall) funCall.shouldPopReturnedValue = true;
-
-
-
-
-
-
-
- if (result.Find<FunctionCall>() != null ) {
- result = new ContentList (result, new Parsed.Text ("\n"));
- }
- Expect(EndOfLine, "end of line", recoveryRule: SkipToNextLine);
- return result as Parsed.Object;
- }
- protected Parsed.Object VariableDeclaration()
- {
- Whitespace ();
- var id = Parse (Identifier);
- if (id != "VAR")
- return null;
- Whitespace ();
- var varName = Expect (IdentifierWithMetadata, "variable name") as Identifier;
- Whitespace ();
- Expect (String ("="), "the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)");
- Whitespace ();
- var definition = Expect (Expression, "initial value for ");
- var expr = definition as Parsed.Expression;
- if (expr) {
- if (!(expr is Number || expr is StringExpression || expr is DivertTarget || expr is VariableReference || expr is List)) {
- Error ("initial value for a variable must be a number, constant, list or divert target");
- }
- if (Parse (ListElementDefinitionSeparator) != null)
- Error ("Unexpected ','. If you're trying to declare a new list, use the LIST keyword, not VAR");
-
- else if (expr is StringExpression) {
- var strExpr = expr as StringExpression;
- if (!strExpr.isSingleString)
- Error ("Constant strings cannot contain any logic.");
- }
- var result = new VariableAssignment (varName, expr);
- result.isGlobalDeclaration = true;
- return result;
- }
- return null;
- }
- protected Parsed.VariableAssignment ListDeclaration ()
- {
- Whitespace ();
- var id = Parse (Identifier);
- if (id != "LIST")
- return null;
- Whitespace ();
- var varName = Expect (IdentifierWithMetadata, "list name") as Identifier;
- Whitespace ();
- Expect (String ("="), "the '=' for an assignment of the list definition");
- Whitespace ();
- var definition = Expect (ListDefinition, "list item names") as ListDefinition;
- if (definition) {
- definition.identifier = varName;
- return new VariableAssignment (varName, definition);
- }
- return null;
- }
- protected Parsed.ListDefinition ListDefinition ()
- {
- AnyWhitespace ();
- var allElements = SeparatedList (ListElementDefinition, ListElementDefinitionSeparator);
- if (allElements == null)
- return null;
- return new ListDefinition (allElements);
- }
- protected string ListElementDefinitionSeparator ()
- {
- AnyWhitespace ();
- if (ParseString (",") == null) return null;
- AnyWhitespace ();
- return ",";
- }
- protected Parsed.ListElementDefinition ListElementDefinition ()
- {
- var inInitialList = ParseString ("(") != null;
- var needsToCloseParen = inInitialList;
- Whitespace ();
- var name = Parse (IdentifierWithMetadata);
- if (name == null)
- return null;
- Whitespace ();
- if (inInitialList) {
- if (ParseString (")") != null) {
- needsToCloseParen = false;
- Whitespace ();
- }
- }
- int? elementValue = null;
- if (ParseString ("=") != null) {
- Whitespace ();
- var elementValueNum = Expect (ExpressionInt, "value to be assigned to list item") as Number;
- if (elementValueNum != null) {
- elementValue = (int) elementValueNum.value;
- }
- if (needsToCloseParen) {
- Whitespace ();
- if (ParseString (")") != null)
- needsToCloseParen = false;
- }
- }
- if (needsToCloseParen)
- Error("Expected closing ')'");
- return new ListElementDefinition (name, inInitialList, elementValue);
- }
- protected Parsed.Object ConstDeclaration()
- {
- Whitespace ();
- var id = Parse (Identifier);
- if (id != "CONST")
- return null;
- Whitespace ();
- var varName = Expect (IdentifierWithMetadata, "constant name") as Identifier;
- Whitespace ();
- Expect (String ("="), "the '=' for an assignment of a value, e.g. '= 5' (initial values are mandatory)");
- Whitespace ();
- var expr = Expect (Expression, "initial value for ") as Parsed.Expression;
- if (!(expr is Number || expr is DivertTarget || expr is StringExpression)) {
- Error ("initial value for a constant must be a number or divert target");
- }
-
- else if (expr is StringExpression) {
- var strExpr = expr as StringExpression;
- if (!strExpr.isSingleString)
- Error ("Constant strings cannot contain any logic.");
- }
- var result = new ConstantDeclaration (varName, expr);
- return result;
- }
- protected Parsed.Object InlineLogicOrGlueOrStartTag()
- {
- return (Parsed.Object) OneOf (InlineLogic, Glue, StartTag);
- }
- protected Parsed.Glue Glue()
- {
-
-
- var glueStr = ParseString("<>");
- if (glueStr != null) {
- return new Parsed.Glue (new Runtime.Glue ());
- } else {
- return null;
- }
- }
- protected Parsed.Object InlineLogic()
- {
- if ( ParseString ("{") == null) {
- return null;
- }
- var wasParsingString = parsingStringExpression;
- var wasTagActive = tagActive;
- Whitespace ();
- var logic = (Parsed.Object) Expect(InnerLogic, "some kind of logic, conditional or sequence within braces: { ... }");
- if (logic == null) {
- parsingStringExpression = wasParsingString;
- return null;
- }
- DisallowIncrement (logic);
- ContentList contentList = logic as ContentList;
- if (!contentList) {
- contentList = new ContentList (logic);
- }
- Whitespace ();
- Expect (String("}"), "closing brace '}' for inline logic");
-
- parsingStringExpression = wasParsingString;
-
-
-
-
-
-
-
-
- if( !wasTagActive ) EndTagIfNecessary(contentList);
- return contentList;
- }
- protected Parsed.Object InnerLogic()
- {
- Whitespace ();
-
-
-
- SequenceType? explicitSeqType = (SequenceType?) ParseObject(SequenceTypeAnnotation);
- if (explicitSeqType != null) {
- var contentLists = (List<ContentList>) Expect(InnerSequenceObjects, "sequence elements (for cycle/stoping etc)");
- if (contentLists == null)
- return null;
- return new Sequence (contentLists, (SequenceType) explicitSeqType);
- }
-
- var initialQueryExpression = Parse(ConditionExpression);
- if (initialQueryExpression) {
- var conditional = (Conditional) Expect(() => InnerConditionalContent (initialQueryExpression), "conditional content following query");
- return conditional;
- }
-
- ParseRule[] rules = {
-
-
-
-
-
-
- InnerConditionalContent,
- InnerSequence,
- InnerExpression,
- };
- bool wasTagActiveAtStartOfScope = tagActive;
-
-
-
-
-
-
- foreach (ParseRule rule in rules) {
- int ruleId = BeginRule ();
- Parsed.Object result = ParseObject(rule) as Parsed.Object;
- if (result) {
-
- if (Peek (Spaced (String ("}"))) == null)
- FailRule (ruleId);
-
- else {
- return (Parsed.Object) SucceedRule (ruleId, result);
- }
- } else {
- FailRule (ruleId);
- }
- }
- return null;
- }
- protected Parsed.Object InnerExpression()
- {
- var expr = Parse(Expression);
- if (expr) {
- expr.outputWhenComplete = true;
- }
- return expr;
- }
- protected Identifier IdentifierWithMetadata()
- {
- var id = Identifier();
- if( id == null ) return null;
-
- return new Identifier { name = id, debugMetadata = null };
- }
-
-
- protected string Identifier()
- {
-
- var name = ParseCharactersFromCharSet (identifierCharSet);
- if (name == null)
- return null;
-
- bool isNumberCharsOnly = true;
- foreach (var c in name) {
- if ( !(c >= '0' && c <= '9') ) {
- isNumberCharsOnly = false;
- break;
- }
- }
- if (isNumberCharsOnly) {
- return null;
- }
- return name;
- }
- CharacterSet identifierCharSet {
- get {
- if (_identifierCharSet == null) {
- (_identifierCharSet = new CharacterSet ())
- .AddRange ('A', 'Z')
- .AddRange ('a', 'z')
- .AddRange ('0', '9')
- .Add ('_');
-
- ExtendIdentifierCharacterRanges (_identifierCharSet);
- }
- return _identifierCharSet;
- }
- }
- private CharacterSet _identifierCharSet;
- }
- }