/// <summary> /// Visits the syntax node. /// </summary> internal void Visit(StateDeclaration parentNode, TokenRange tokenRange, bool isAsync = false) { if (parentNode.EntryDeclaration != null) { throw new ParsingException("Duplicate entry declaration.", this.TokenStream.Peek()); } var node = new EntryDeclaration(this.TokenStream.Program, parentNode, isAsync); node.EntryKeyword = this.TokenStream.Peek(); node.HeaderTokenRange = tokenRange.FinishAndClone(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", this.TokenStream.Peek(), TokenType.LeftCurlyBracket); } var blockNode = new BlockSyntax(this.TokenStream.Program, parentNode.Machine, parentNode); new BlockSyntaxVisitor(this.TokenStream).Visit(blockNode); node.StatementBlock = blockNode; parentNode.EntryDeclaration = node; }
/// <summary> /// Visits the syntax node. /// </summary> internal void Visit(MachineDeclaration parentNode, StateGroupDeclaration groupNode, ModifierSet modSet, TokenRange tokenRange) { this.CheckStateGroupModifierSet(modSet); var node = new StateGroupDeclaration(this.TokenStream.Program, parentNode, groupNode); node.AccessModifier = modSet.AccessModifier; node.StateGroupKeyword = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state group identifier.", this.TokenStream.Peek(), TokenType.Identifier); } this.TokenStream.Swap(TokenType.StateGroupIdentifier); node.Identifier = this.TokenStream.Peek(); node.HeaderTokenRange = tokenRange.FinishAndClone(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", this.TokenStream.Peek(), TokenType.LeftCurlyBracket); } this.TokenStream.Swap(TokenType.StateGroupLeftCurlyBracket); node.LeftCurlyBracketToken = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); this.VisitNextPSharpIntraGroupDeclaration(node); if (groupNode is null) { parentNode.StateGroupDeclarations.Add(node); } else { groupNode.StateGroupDeclarations.Add(node); } var stateDeclarations = node.GetAllStateDeclarations(); if (stateDeclarations.Count == 0) { throw new ParsingException("A state group must declare at least one state.", this.TokenStream.Peek()); } }
/// <summary> /// Visits the syntax node. /// </summary> internal void Visit(NamespaceDeclaration parentNode, bool isMonitor, ModifierSet modSet, TokenRange tokenRange) { if (isMonitor) { this.CheckMonitorModifierSet(modSet); } else { this.CheckMachineModifierSet(modSet); } var node = new MachineDeclaration(this.TokenStream.Program, parentNode, isMonitor, modSet); node.MachineKeyword = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected machine identifier.", this.TokenStream.Peek(), TokenType.Identifier); } this.TokenStream.Swap(TokenType.MachineIdentifier); node.Identifier = this.TokenStream.Peek(); node.HeaderTokenRange = tokenRange.FinishAndClone(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); var nameVisitor = new NameVisitor(this.TokenStream); node.TemplateParameters = nameVisitor.ConsumeTemplateParams(); if (this.TokenStream.Program is PSharpProgram) { if (this.TokenStream.Done || (this.TokenStream.Peek().Type != TokenType.Colon && this.TokenStream.Peek().Type != TokenType.LeftCurlyBracket)) { throw new ParsingException("Expected \":\" or \"{\".", this.TokenStream.Peek(), TokenType.Colon, TokenType.LeftCurlyBracket); } if (this.TokenStream.Peek().Type == TokenType.Colon) { node.ColonToken = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); var baseNameTokensVisitor = new NameVisitor(this.TokenStream, node.HeaderTokenRange); node.BaseNameTokens = baseNameTokensVisitor.ConsumeGenericName(TokenType.MachineIdentifier); } } if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", this.TokenStream.Peek(), TokenType.LeftCurlyBracket); } this.TokenStream.Swap(TokenType.MachineLeftCurlyBracket); node.LeftCurlyBracketToken = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); this.VisitNextPSharpIntraMachineDeclaration(node); parentNode.MachineDeclarations.Add(node); var stateDeclarations = node.GetAllStateDeclarations(); if (stateDeclarations.Count == 0 && node.BaseNameTokens.Count == 0) { throw new ParsingException("A machine must declare at least one state.", this.TokenStream.Peek()); } var startStates = stateDeclarations.FindAll(s => s.IsStart); if (startStates.Count == 0 && node.BaseNameTokens.Count == 0) { throw new ParsingException("A machine must declare a start state.", this.TokenStream.Peek()); } else if (startStates.Count > 1) { throw new ParsingException("A machine can declare only a single start state.", this.TokenStream.Peek()); } }
/// <summary> /// Visits the syntax node. /// </summary> internal void Visit(MachineDeclaration parentNode, StateGroupDeclaration groupNode, ModifierSet modSet, TokenRange tokenRange) { this.CheckMachineStateModifierSet(modSet); var node = new StateDeclaration(this.TokenStream.Program, parentNode, groupNode, modSet); node.StateKeyword = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", this.TokenStream.Peek(), TokenType.Identifier); } this.TokenStream.Swap(TokenType.StateIdentifier); node.Identifier = this.TokenStream.Peek(); node.HeaderTokenRange = tokenRange.FinishAndClone(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); // Check for inherited state. if (!this.TokenStream.Done && this.TokenStream.Peek().Type == TokenType.Colon) { this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", this.TokenStream.Peek(), TokenType.Identifier); } this.TokenStream.Swap(TokenType.StateIdentifier); node.BaseStateToken = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); } if (this.TokenStream.Done || this.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", this.TokenStream.Peek(), TokenType.LeftCurlyBracket); } this.TokenStream.Swap(TokenType.StateLeftCurlyBracket); node.LeftCurlyBracketToken = this.TokenStream.Peek(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (this.TokenStream.Program is PSharpProgram) { this.VisitNextPSharpIntraStateDeclaration(node); } else { this.VisitNextPIntraStateDeclaration(node); } // Insert into (immediately) containing group or machine declaration. if (groupNode != null) { groupNode.StateDeclarations.Add(node); } else { parentNode.StateDeclarations.Add(node); } }