public virtual BlockBase StartAlternate(int lineNumber) { if (Tokens.Last() is ConditionalBlock child) { child.returnBlockId = this is ConditionalBlock ? returnBlockId : BlockId; BlockBase result = child.RequiresAlternate(); if (result != null) { result.returnBlockId = this is ConditionalBlock ? returnBlockId : BlockId; result = result.StartAlternate(lineNumber); (result as ConditionalBlock).AcceptAlternate(); return(result); } return(this); } return(this as ConditionalBlock); }
public IEnumerator <Script> GetEnumerator() { bool inScript = false; ScriptParserState parserState = ScriptParserState.None; BlockBase currentBlock = null; foreach (Token token in tokenizer) { if (inScript) { switch (token.Type) { case TokenType.StatementEnd: currentBlock = currentBlock.CompleteBlock() ?? throw new InvalidDataException($"Malformed Script detected"); parserState = ScriptParserState.None; continue; case TokenType.LineEnd: if (parserState == ScriptParserState.ScriptName) { parserState = ScriptParserState.None; } continue; case TokenType.BlockOpen: currentBlock = currentBlock.StartBlock(tokenizer.LineNumber); continue; case TokenType.BracketOpen: currentBlock = currentBlock.StartEnclosure(tokenizer.LineNumber); continue; case TokenType.BlockClose: case TokenType.BracketClose: if ((token.Type == TokenType.BracketClose && currentBlock is Enclosure) || (token.Type == TokenType.BlockClose && currentBlock is Block)) { currentBlock = currentBlock.CompleteBlock() ?? throw new InvalidDataException($"Malformed Script detected");; continue; } else //something wrong here { throw new InvalidDataException($"Error in signal script data, matching element not found in line {tokenizer.LineNumber}."); } case TokenType.Value: if (parserState == ScriptParserState.ScriptName) //script names may include any value token or operator, only ended by line end { (currentBlock as Script).ScriptName += token.Value; continue; } switch (token.Value) { case "REM": yield return(currentBlock as Script); inScript = false; parserState = ScriptParserState.Remark; continue; case "SCRIPT": if (!(currentBlock is Script)) { throw new InvalidDataException($"Error in signal script, matching element not found before new script in line {tokenizer.LineNumber}."); } yield return(currentBlock as Script); if (parserState == ScriptParserState.Remark) { parserState = ScriptParserState.None; } else { currentBlock = new Script(tokenizer.LineNumber); parserState = ScriptParserState.ScriptName; inScript = true; } continue; case "IF": currentBlock = currentBlock.StartCondition(tokenizer.LineNumber); continue; case "ELSE": currentBlock = currentBlock.StartAlternate(tokenizer.LineNumber); continue; case "AND": case "OR": case "NOT": case "MOD": case "DIV": currentBlock = currentBlock.Add(new OperatorToken(token.Value, tokenizer.LineNumber), tokenizer.LineNumber); continue; default: currentBlock = currentBlock.Add(new ScriptToken() { Token = token.Value }, tokenizer.LineNumber); continue; } case TokenType.Separator: case TokenType.Tab: case TokenType.Comma: continue; case TokenType.Operator: if (parserState == ScriptParserState.ScriptName) { (currentBlock as Script).ScriptName += token.Value; } else { if (token.Value != "#") //ignoring single # operator (rounding) which isn't used in OR { currentBlock = currentBlock.Add(new OperatorToken(token.Value, tokenizer.LineNumber), tokenizer.LineNumber); } } continue; default: throw new InvalidOperationException($"Unknown token type {token.Type} containing '{token.Value}' in line {tokenizer.LineNumber}"); } } else if (token.Type == TokenType.Value) { switch (token.Value) { case "REM": parserState = ScriptParserState.Remark; continue; case "SCRIPT": if (parserState == ScriptParserState.Remark) { parserState = ScriptParserState.None; } else // start new script { currentBlock = new Script(tokenizer.LineNumber); parserState = ScriptParserState.ScriptName; inScript = true; } continue; } } } yield return(currentBlock as Script); }
public ConditionalBlock(BlockBase parent, int lineNumber) : base(parent, lineNumber) { }
public Enclosure(BlockBase parent, int lineNumber) : base(parent, lineNumber) { }
public Block(BlockBase parent, int lineNumber) : base(parent, lineNumber) { }
public Statement(BlockBase parent, int lineNumber) : base(parent, lineNumber) { }
protected void AddNestedBlock(BlockBase block) { Current = block; Tokens.Add(block); }
public BlockBase(BlockBase parent, int lineNumber) { Parent = parent; Parent?.AddNestedBlock(this); LineNumber = lineNumber; }