/// <summary> /// Constructor. /// </summary> /// <param name="program">Program</param> /// <param name="machineNode">MachineDeclarationNode</param> /// <param name="stateNode">StateDeclarationNode</param> /// <param name="isModel">Is a model</param> internal BlockSyntax(IPSharpProgram program, MachineDeclaration machineNode, StateDeclaration stateNode, bool isModel) : base(program, isModel) { this.Machine = machineNode; this.State = stateNode; }
/// <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> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { if (parentNode.ExitDeclaration != null) { throw new ParsingException("Duplicate exit declaration.", new List<TokenType>()); } var node = new ExitDeclaration(base.TokenStream.Program, parentNode.IsModel); node.ExitKeyword = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List<TokenType> { TokenType.LeftCurlyBracket }); } var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, parentNode, node.IsModel); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); node.StatementBlock = blockNode; parentNode.ExitDeclaration = node; }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { if (parentNode.EntryDeclaration != null) { throw new ParsingException("Duplicate entry declaration.", new List <TokenType>()); } var node = new EntryDeclaration(base.TokenStream.Program, parentNode.IsModel); node.EntryKeyword = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List <TokenType> { TokenType.LeftCurlyBracket }); } var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, parentNode, node.IsModel); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); node.StatementBlock = blockNode; parentNode.EntryDeclaration = node; }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> /// <param name="isStart">Is start state</param> /// <param name="accMod">Access modifier</param> internal void Visit(MachineDeclaration parentNode, bool isStart, AccessModifier accMod) { var node = new StateDeclaration(base.TokenStream.Program, parentNode, isStart, parentNode.IsModel); node.AccessModifier = accMod; node.StateKeyword = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", new List <TokenType> { TokenType.Identifier }); } base.TokenStream.CurrentState = base.TokenStream.Peek().Text; base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateIdentifier)); node.Identifier = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List <TokenType> { TokenType.LeftCurlyBracket }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateLeftCurlyBracket)); node.LeftCurlyBracketToken = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Program is PSharpProgram) { this.VisitNextPSharpIntraStateDeclaration(node); } else { this.VisitNextPIntraStateDeclaration(node); } parentNode.StateDeclarations.Add(node); }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> /// <param name="isStart">Is start state</param> /// <param name="accMod">Access modifier</param> internal void Visit(MachineDeclaration parentNode, bool isStart, AccessModifier accMod) { var node = new StateDeclaration(base.TokenStream.Program, parentNode, isStart, parentNode.IsModel); node.AccessModifier = accMod; node.StateKeyword = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", new List<TokenType> { TokenType.Identifier }); } base.TokenStream.CurrentState = base.TokenStream.Peek().Text; base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateIdentifier)); node.Identifier = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List<TokenType> { TokenType.LeftCurlyBracket }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateLeftCurlyBracket)); node.LeftCurlyBracketToken = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Program is PSharpProgram) { this.VisitNextPSharpIntraStateDeclaration(node); } else { this.VisitNextPIntraStateDeclaration(node); } parentNode.StateDeclarations.Add(node); }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.MulOp && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent)) { throw new ParsingException("Expected event identifier.", new List <TokenType> { TokenType.Identifier, TokenType.HaltEvent, TokenType.DefaultEvent }); } var nameVisitor = new NameVisitor(base.TokenStream); // Consumes multiple generic event names. var eventIdentifiers = nameVisitor.ConsumeMultipleNames(TokenType.EventIdentifier, tt => nameVisitor.ConsumeGenericEventName(tt)); if (!base.TokenStream.Done && base.TokenStream.Peek().Type == TokenType.Identifier) { throw new ParsingException("Expected \",\".", new List <TokenType> { TokenType.Comma }); } if (!base.TokenStream.Done && (base.TokenStream.Peek().Type == TokenType.LeftAngleBracket || base.TokenStream.Peek().Type == TokenType.RightAngleBracket)) { throw new ParsingException("Invalid generic expression.", new List <TokenType> { }); } if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.DoAction && base.TokenStream.Peek().Type != TokenType.GotoState && base.TokenStream.Peek().Type != TokenType.PushState)) { throw new ParsingException("Expected \"do\", \"goto\" or \"push\".", new List <TokenType> { TokenType.DoAction, TokenType.GotoState, TokenType.PushState }); } var resolvedEventIdentifiers = new Dictionary <Token, List <Token> >(); foreach (var eventIdentifier in eventIdentifiers) { if (eventIdentifier.Count == 1) { // We don't want to collapse halt and default // events to event identifiers. resolvedEventIdentifiers.Add(eventIdentifier[0], eventIdentifier); } else { var identifierBuilder = new StringBuilder(); foreach (var token in eventIdentifier) { identifierBuilder.Append(token.TextUnit.Text); } TextUnit textUnit = new TextUnit(identifierBuilder.ToString(), eventIdentifier[0].TextUnit.Line); resolvedEventIdentifiers.Add(new Token(textUnit, TokenType.EventIdentifier), eventIdentifier); } } if (base.TokenStream.Peek().Type == TokenType.DoAction) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); bool isAsync = false; if (base.TokenStream.Peek().Type == TokenType.Async) { isAsync = true; base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); } if (base.TokenStream.Peek().Type == TokenType.Await) { throw new ParsingException("'await' should not be used on actions.", new List <TokenType>()); } if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket)) { var message = isAsync ? "Expected action identifier or opening curly bracket." : "Expected async keyword, action identifier, or opening curly bracket."; var list = new List <TokenType> { TokenType.Identifier, TokenType.LeftCurlyBracket }; if (!isAsync) { list.Insert(0, TokenType.Async); } throw new ParsingException(message, list); } if (base.TokenStream.Peek().Type == TokenType.LeftCurlyBracket) { var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, null); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); foreach (var kvp in resolvedEventIdentifiers) { if (!parentNode.AddActionBinding(kvp.Key, kvp.Value, new AnonymousActionHandler(blockNode, isAsync))) { throw new ParsingException("Unexpected action handler.", new List <TokenType>()); } } } else { if (isAsync) { throw new ParsingException("'async' should only be used on anonymous actions.", new List <TokenType>()); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.ActionIdentifier)); var actionIdentifier = base.TokenStream.Peek(); foreach (var kvp in resolvedEventIdentifiers) { if (!parentNode.AddActionBinding(kvp.Key, kvp.Value, actionIdentifier)) { throw new ParsingException("Unexpected action handler.", new List <TokenType>()); } } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } } } else if (base.TokenStream.Peek().Type == TokenType.GotoState) { var stateIdentifiers = this.ConsumeState(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.WithExit && base.TokenStream.Peek().Type != TokenType.Semicolon)) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } if (base.TokenStream.Peek().Type == TokenType.WithExit) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); bool isAsync = false; if (base.TokenStream.Peek().Type == TokenType.Async) { isAsync = true; base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List <TokenType> { TokenType.LeftCurlyBracket }); } var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, null); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); foreach (var kvp in resolvedEventIdentifiers) { if (!parentNode.AddGotoStateTransition(kvp.Key, kvp.Value, stateIdentifiers, new AnonymousActionHandler(blockNode, isAsync))) { throw new ParsingException("Unexpected goto state transition.", new List <TokenType>()); } } } else { foreach (var kvp in resolvedEventIdentifiers) { if (!parentNode.AddGotoStateTransition(kvp.Key, kvp.Value, stateIdentifiers)) { throw new ParsingException("Unexpected goto state transition.", new List <TokenType>()); } } } } else if (base.TokenStream.Peek().Type == TokenType.PushState) { if (parentNode.Machine.IsMonitor) { throw new ParsingException("Monitors cannot \"push\".", new List <TokenType>()); } var stateIdentifiers = this.ConsumeState(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } foreach (var kvp in resolvedEventIdentifiers) { if (!parentNode.AddPushStateTransition(kvp.Key, kvp.Value, stateIdentifiers)) { throw new ParsingException("Unexpected push state transition.", new List <TokenType>()); } } } }
/// <summary> /// Visits the next intra-state declration. /// </summary> /// <param name="node">Node</param> private void VisitNextPIntraStateDeclaration(StateDeclaration node) { bool fixpoint = false; while (!fixpoint) { var token = base.TokenStream.Peek(); switch (token.Type) { case TokenType.WhiteSpace: case TokenType.Comment: case TokenType.NewLine: base.TokenStream.Index++; break; case TokenType.CommentLine: case TokenType.Region: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.CommentStart: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.Entry: new StateEntryDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.OnAction: new StateActionDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.DeferEvent: new DeferEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.IgnoreEvent: new IgnoreEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.RightCurlyBracket: base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateRightCurlyBracket)); node.RightCurlyBracketToken = base.TokenStream.Peek(); base.TokenStream.CurrentState = ""; fixpoint = true; break; default: throw new ParsingException("Unexpected token.", new List<TokenType>()); } if (base.TokenStream.Done) { throw new ParsingException("Expected \"}\".", new List<TokenType> { TokenType.Entry, TokenType.Exit, TokenType.OnAction, TokenType.DeferEvent, TokenType.IgnoreEvent }); } } }
/// <summary> /// Visits the next intra-state declration. /// </summary> /// <param name="node">Node</param> private void VisitNextPSharpIntraStateDeclaration(StateDeclaration node) { bool fixpoint = false; while (!fixpoint) { var token = base.TokenStream.Peek(); switch (token.Type) { case TokenType.WhiteSpace: case TokenType.Comment: case TokenType.NewLine: base.TokenStream.Index++; break; case TokenType.CommentLine: case TokenType.Region: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.CommentStart: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.Entry: new StateEntryDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.OnAction: new StateActionDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.DeferEvent: new DeferEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.IgnoreEvent: new IgnoreEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.LeftSquareBracket: base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); new AttributeListVisitor(base.TokenStream).Visit(); base.TokenStream.Index++; break; case TokenType.RightCurlyBracket: base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateRightCurlyBracket)); node.RightCurlyBracketToken = base.TokenStream.Peek(); base.TokenStream.CurrentState = ""; fixpoint = true; break; case TokenType.Private: case TokenType.Protected: case TokenType.Internal: case TokenType.Public: throw new ParsingException("State actions cannot have modifiers.", new List<TokenType>()); case TokenType.Abstract: case TokenType.Virtual: throw new ParsingException("State actions cannot be abstract or virtual.", new List<TokenType>()); default: throw new ParsingException("Unexpected token.", new List<TokenType>()); } if (base.TokenStream.Done) { throw new ParsingException("Expected \"}\".", new List<TokenType> { TokenType.Entry, TokenType.Exit, TokenType.OnAction, TokenType.DeferEvent, TokenType.IgnoreEvent, TokenType.LeftSquareBracket, TokenType.RightCurlyBracket }); } } }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Containing machine</param> /// <param name="groupNode">Containing group</param> /// <param name="modSet">Modifier set</param> internal void Visit(MachineDeclaration parentNode, StateGroupDeclaration groupNode, ModifierSet modSet) { this.CheckMachineStateModifierSet(modSet); var node = new StateDeclaration(base.TokenStream.Program, parentNode, groupNode, modSet); node.StateKeyword = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", new List <TokenType> { TokenType.Identifier }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateIdentifier)); node.Identifier = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List <TokenType> { TokenType.LeftCurlyBracket }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateLeftCurlyBracket)); node.LeftCurlyBracketToken = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.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); } }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { if (parentNode.Machine.IsMonitor) { throw new ParsingException("Monitors cannot \"defer\".", new List <TokenType>()); } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); var nameVisitor = new NameVisitor(base.TokenStream); // Consumes multiple generic event names. var eventIdentifiers = nameVisitor.ConsumeMultipleNames(TokenType.EventIdentifier, tt => nameVisitor.ConsumeGenericEventName(tt)); var resolvedEventIdentifiers = new Dictionary <Token, List <Token> >(); foreach (var eventIdentifier in eventIdentifiers) { if (eventIdentifier.Count == 1) { // We don't want to collapse halt and default // events to event identifiers. resolvedEventIdentifiers.Add(eventIdentifier[0], eventIdentifier); } else { var identifierBuilder = new StringBuilder(); foreach (var token in eventIdentifier) { identifierBuilder.Append(token.TextUnit.Text); } TextUnit textUnit = new TextUnit(identifierBuilder.ToString(), eventIdentifier[0].TextUnit.Line); resolvedEventIdentifiers.Add(new Token(textUnit, TokenType.EventIdentifier), eventIdentifier); } } foreach (var kvp in resolvedEventIdentifiers) { if (!parentNode.AddDeferredEvent(kvp.Key, kvp.Value)) { throw new ParsingException("Unexpected defer declaration.", new List <TokenType>()); } } if (!base.TokenStream.Done && base.TokenStream.Peek().Type == TokenType.Identifier) { throw new ParsingException("Expected \",\".", new List <TokenType> { TokenType.Comma }); } if (!base.TokenStream.Done && (base.TokenStream.Peek().Type == TokenType.LeftAngleBracket || base.TokenStream.Peek().Type == TokenType.RightAngleBracket)) { throw new ParsingException("Invalid generic expression.", new List <TokenType> { }); } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } }
/// <summary> /// Visits the next intra-state declration. /// </summary> /// <param name="node">Node</param> private void VisitNextPSharpIntraStateDeclaration(StateDeclaration node) { bool fixpoint = false; while (!fixpoint) { var token = base.TokenStream.Peek(); switch (token.Type) { case TokenType.WhiteSpace: case TokenType.Comment: case TokenType.NewLine: base.TokenStream.Index++; break; case TokenType.Async: base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); token = base.TokenStream.Peek(); switch (token.Type) { case TokenType.Entry: new StateEntryDeclarationVisitor(base.TokenStream).Visit(node, isAsync: true); base.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(base.TokenStream).Visit(node, isAsync: true); base.TokenStream.Index++; break; default: throw new ParsingException("'async' was used in an incorrect context.", new List <TokenType>()); } break; case TokenType.CommentLine: case TokenType.Region: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.CommentStart: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.Entry: new StateEntryDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.OnAction: new StateActionDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.DeferEvent: new DeferEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.IgnoreEvent: new IgnoreEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.LeftSquareBracket: base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); new AttributeListVisitor(base.TokenStream).Visit(); base.TokenStream.Index++; break; case TokenType.RightCurlyBracket: base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateRightCurlyBracket)); node.RightCurlyBracketToken = base.TokenStream.Peek(); fixpoint = true; break; case TokenType.Private: case TokenType.Protected: case TokenType.Internal: case TokenType.Public: throw new ParsingException("State actions cannot have modifiers.", new List <TokenType>()); case TokenType.Abstract: case TokenType.Virtual: throw new ParsingException("State actions cannot be abstract or virtual.", new List <TokenType>()); default: throw new ParsingException("Unexpected token.", new List <TokenType>()); } if (base.TokenStream.Done) { throw new ParsingException("Expected \"}\".", new List <TokenType> { TokenType.Entry, TokenType.Exit, TokenType.OnAction, TokenType.DeferEvent, TokenType.IgnoreEvent, TokenType.LeftSquareBracket, TokenType.RightCurlyBracket }); } } }
/// <summary> /// Visits the next intra-state declration. /// </summary> /// <param name="node">Node</param> private void VisitNextPIntraStateDeclaration(StateDeclaration node) { bool fixpoint = false; while (!fixpoint) { var token = base.TokenStream.Peek(); switch (token.Type) { case TokenType.WhiteSpace: case TokenType.Comment: case TokenType.NewLine: base.TokenStream.Index++; break; case TokenType.CommentLine: case TokenType.Region: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.CommentStart: base.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.Entry: new StateEntryDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.OnAction: new StateActionDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.DeferEvent: new DeferEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.IgnoreEvent: new IgnoreEventsDeclarationVisitor(base.TokenStream).Visit(node); base.TokenStream.Index++; break; case TokenType.RightCurlyBracket: base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateRightCurlyBracket)); node.RightCurlyBracketToken = base.TokenStream.Peek(); fixpoint = true; break; default: throw new ParsingException("Unexpected token.", new List <TokenType>()); } if (base.TokenStream.Done) { throw new ParsingException("Expected \"}\".", new List <TokenType> { TokenType.Entry, TokenType.Exit, TokenType.OnAction, TokenType.DeferEvent, TokenType.IgnoreEvent }); } } }
/// <summary> /// Visits the next intra-state declration. /// </summary> private void VisitNextPIntraStateDeclaration(StateDeclaration node) { bool fixpoint = false; var tokenRange = new TokenRange(this.TokenStream); while (!fixpoint) { if (!this.TokenStream.Done) { var token = this.TokenStream.Peek(); switch (token.Type) { case TokenType.WhiteSpace: case TokenType.QuotedString: case TokenType.Comment: case TokenType.NewLine: this.TokenStream.Index++; break; case TokenType.CommentLine: case TokenType.Region: this.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.CommentStart: this.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.Entry: new StateEntryDeclarationVisitor(this.TokenStream).Visit(node, tokenRange.Start()); this.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(this.TokenStream).Visit(node, tokenRange.Start()); this.TokenStream.Index++; break; case TokenType.OnAction: new StateActionDeclarationVisitor(this.TokenStream).Visit(node); this.TokenStream.Index++; break; case TokenType.DeferEvent: new DeferEventsDeclarationVisitor(this.TokenStream).Visit(node); this.TokenStream.Index++; break; case TokenType.IgnoreEvent: new IgnoreEventsDeclarationVisitor(this.TokenStream).Visit(node); this.TokenStream.Index++; break; case TokenType.RightCurlyBracket: this.TokenStream.Swap(TokenType.StateRightCurlyBracket); node.RightCurlyBracketToken = this.TokenStream.Peek(); fixpoint = true; break; default: throw new ParsingException("Unexpected token.", this.TokenStream.Peek()); } } if (this.TokenStream.Done) { throw new ParsingException("Expected \"}\".", this.TokenStream.Peek(), TokenType.Entry, TokenType.Exit, TokenType.OnAction, TokenType.DeferEvent, TokenType.IgnoreEvent); } } }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent)) { throw new ParsingException("Expected event identifier.", new List <TokenType> { TokenType.Identifier, TokenType.HaltEvent, TokenType.DefaultEvent }); } var eventIdentifiers = new List <Token>(); bool expectsComma = false; while (!base.TokenStream.Done && base.TokenStream.Peek().Type != TokenType.DoAction && base.TokenStream.Peek().Type != TokenType.GotoState && base.TokenStream.Peek().Type != TokenType.PushState) { if ((!expectsComma && base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent) || (expectsComma && base.TokenStream.Peek().Type != TokenType.Comma)) { break; } if (base.TokenStream.Peek().Type == TokenType.Identifier || base.TokenStream.Peek().Type == TokenType.HaltEvent || base.TokenStream.Peek().Type == TokenType.DefaultEvent) { if (base.TokenStream.Peek().Type == TokenType.Identifier) { base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.EventIdentifier)); } eventIdentifiers.Add(base.TokenStream.Peek()); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); expectsComma = true; } else if (base.TokenStream.Peek().Type == TokenType.Comma) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); expectsComma = false; } } if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.DoAction && base.TokenStream.Peek().Type != TokenType.GotoState && base.TokenStream.Peek().Type != TokenType.PushState)) { throw new ParsingException("Expected \"do\", \"goto\" or \"push\".", new List <TokenType> { TokenType.DoAction, TokenType.GotoState, TokenType.PushState }); } if (base.TokenStream.Peek().Type == TokenType.DoAction) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket)) { throw new ParsingException("Expected action identifier.", new List <TokenType> { TokenType.Identifier }); } if (base.TokenStream.Peek().Type == TokenType.LeftCurlyBracket) { var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, null, parentNode.IsModel); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddActionBinding(eventIdentifier, blockNode)) { throw new ParsingException("Unexpected action handler.", new List <TokenType>()); } } } else { base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.ActionIdentifier)); var actionIdentifier = base.TokenStream.Peek(); foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddActionBinding(eventIdentifier, actionIdentifier)) { throw new ParsingException("Unexpected action handler.", new List <TokenType>()); } } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } } else if (base.TokenStream.Peek().Type == TokenType.GotoState) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", new List <TokenType> { TokenType.Identifier }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateIdentifier)); var stateIdentifier = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.WithExit && base.TokenStream.Peek().Type != TokenType.Semicolon)) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } if (base.TokenStream.Peek().Type == TokenType.WithExit) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List <TokenType> { TokenType.LeftCurlyBracket }); } var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, null, parentNode.IsModel); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddGotoStateTransition(eventIdentifier, stateIdentifier, blockNode)) { throw new ParsingException("Unexpected goto state transition.", new List <TokenType>()); } } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } } else { foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddGotoStateTransition(eventIdentifier, stateIdentifier)) { throw new ParsingException("Unexpected goto state transition.", new List <TokenType>()); } } } } else if (base.TokenStream.Peek().Type == TokenType.PushState) { if (parentNode.Machine.IsMonitor) { throw new ParsingException("Monitors cannot \"push\".", new List <TokenType>()); } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", new List <TokenType> { TokenType.Identifier }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateIdentifier)); var stateIdentifier = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddPushStateTransition(eventIdentifier, stateIdentifier)) { throw new ParsingException("Unexpected push state transition.", new List <TokenType>()); } } } }
/// <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); } }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent)) { throw new ParsingException("Expected event identifier.", new List<TokenType> { TokenType.Identifier, TokenType.HaltEvent, TokenType.DefaultEvent }); } var eventIdentifiers = new List<Token>(); bool expectsComma = false; while (!base.TokenStream.Done && base.TokenStream.Peek().Type != TokenType.DoAction && base.TokenStream.Peek().Type != TokenType.GotoState && base.TokenStream.Peek().Type != TokenType.PushState) { if ((!expectsComma && base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent) || (expectsComma && base.TokenStream.Peek().Type != TokenType.Comma)) { break; } if (base.TokenStream.Peek().Type == TokenType.Identifier || base.TokenStream.Peek().Type == TokenType.HaltEvent || base.TokenStream.Peek().Type == TokenType.DefaultEvent) { if (base.TokenStream.Peek().Type == TokenType.Identifier) { base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.EventIdentifier)); } eventIdentifiers.Add(base.TokenStream.Peek()); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); expectsComma = true; } else if (base.TokenStream.Peek().Type == TokenType.Comma) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); expectsComma = false; } } if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.DoAction && base.TokenStream.Peek().Type != TokenType.GotoState && base.TokenStream.Peek().Type != TokenType.PushState)) { throw new ParsingException("Expected \"do\", \"goto\" or \"push\".", new List<TokenType> { TokenType.DoAction, TokenType.GotoState, TokenType.PushState }); } if (base.TokenStream.Peek().Type == TokenType.DoAction) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket)) { throw new ParsingException("Expected action identifier.", new List<TokenType> { TokenType.Identifier }); } if (base.TokenStream.Peek().Type == TokenType.LeftCurlyBracket) { var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, null, parentNode.IsModel); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddActionBinding(eventIdentifier, blockNode)) { throw new ParsingException("Unexpected action handler.", new List<TokenType>()); } } } else { base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.ActionIdentifier)); var actionIdentifier = base.TokenStream.Peek(); foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddActionBinding(eventIdentifier, actionIdentifier)) { throw new ParsingException("Unexpected action handler.", new List<TokenType>()); } } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List<TokenType> { TokenType.Semicolon }); } } else if (base.TokenStream.Peek().Type == TokenType.GotoState) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", new List<TokenType> { TokenType.Identifier }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateIdentifier)); var stateIdentifier = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.WithExit && base.TokenStream.Peek().Type != TokenType.Semicolon)) { throw new ParsingException("Expected \";\".", new List<TokenType> { TokenType.Semicolon }); } if (base.TokenStream.Peek().Type == TokenType.WithExit) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket) { throw new ParsingException("Expected \"{\".", new List<TokenType> { TokenType.LeftCurlyBracket }); } var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, null, parentNode.IsModel); new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddGotoStateTransition(eventIdentifier, stateIdentifier, blockNode)) { throw new ParsingException("Unexpected goto state transition.", new List<TokenType>()); } } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List<TokenType> { TokenType.Semicolon }); } } else { foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddGotoStateTransition(eventIdentifier, stateIdentifier)) { throw new ParsingException("Unexpected goto state transition.", new List<TokenType>()); } } } } else if (base.TokenStream.Peek().Type == TokenType.PushState) { if (parentNode.Machine.IsMonitor) { throw new ParsingException("Monitors cannot \"push\".", new List<TokenType>()); } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Identifier) { throw new ParsingException("Expected state identifier.", new List<TokenType> { TokenType.Identifier }); } base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.StateIdentifier)); var stateIdentifier = base.TokenStream.Peek(); base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List<TokenType> { TokenType.Semicolon }); } foreach (var eventIdentifier in eventIdentifiers) { if (!parentNode.AddPushStateTransition(eventIdentifier, stateIdentifier)) { throw new ParsingException("Unexpected push state transition.", new List<TokenType>()); } } } }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent)) { throw new ParsingException("Expected event identifier.", new List<TokenType> { TokenType.Identifier, TokenType.HaltEvent, TokenType.DefaultEvent }); } bool expectsComma = false; while (!base.TokenStream.Done && base.TokenStream.Peek().Type != TokenType.Semicolon) { if (!expectsComma && (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent)) { throw new ParsingException("Expected event identifier.", new List<TokenType> { TokenType.Identifier, TokenType.HaltEvent, TokenType.DefaultEvent }); } if (expectsComma && base.TokenStream.Peek().Type != TokenType.Comma) { throw new ParsingException("Expected \",\".", new List<TokenType> { TokenType.Comma }); } if (base.TokenStream.Peek().Type == TokenType.Identifier) { base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.EventIdentifier)); if (!parentNode.AddIgnoredEvent(base.TokenStream.Peek())) { throw new ParsingException("Unexpected event identifier.", new List<TokenType>()); } expectsComma = true; } else if (base.TokenStream.Peek().Type == TokenType.HaltEvent || base.TokenStream.Peek().Type == TokenType.DefaultEvent) { if (!parentNode.AddDeferredEvent(base.TokenStream.Peek())) { throw new ParsingException("Unexpected event identifier.", new List<TokenType>()); } expectsComma = true; } else if (base.TokenStream.Peek().Type == TokenType.Comma) { expectsComma = false; } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List<TokenType> { TokenType.Semicolon }); } }
/// <summary> /// Visits the syntax node. /// </summary> /// <param name="parentNode">Node</param> internal void Visit(StateDeclaration parentNode) { base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); if (base.TokenStream.Done || (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent)) { throw new ParsingException("Expected event identifier.", new List <TokenType> { TokenType.Identifier, TokenType.HaltEvent, TokenType.DefaultEvent }); } bool expectsComma = false; while (!base.TokenStream.Done && base.TokenStream.Peek().Type != TokenType.Semicolon) { if (!expectsComma && (base.TokenStream.Peek().Type != TokenType.Identifier && base.TokenStream.Peek().Type != TokenType.HaltEvent && base.TokenStream.Peek().Type != TokenType.DefaultEvent)) { throw new ParsingException("Expected event identifier.", new List <TokenType> { TokenType.Identifier, TokenType.HaltEvent, TokenType.DefaultEvent }); } if (expectsComma && base.TokenStream.Peek().Type != TokenType.Comma) { throw new ParsingException("Expected \",\".", new List <TokenType> { TokenType.Comma }); } if (base.TokenStream.Peek().Type == TokenType.Identifier) { base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit, TokenType.EventIdentifier)); if (!parentNode.AddIgnoredEvent(base.TokenStream.Peek())) { throw new ParsingException("Unexpected event identifier.", new List <TokenType>()); } expectsComma = true; } else if (base.TokenStream.Peek().Type == TokenType.HaltEvent || base.TokenStream.Peek().Type == TokenType.DefaultEvent) { if (!parentNode.AddDeferredEvent(base.TokenStream.Peek())) { throw new ParsingException("Unexpected event identifier.", new List <TokenType>()); } expectsComma = true; } else if (base.TokenStream.Peek().Type == TokenType.Comma) { expectsComma = false; } base.TokenStream.Index++; base.TokenStream.SkipWhiteSpaceAndCommentTokens(); } if (base.TokenStream.Done || base.TokenStream.Peek().Type != TokenType.Semicolon) { throw new ParsingException("Expected \";\".", new List <TokenType> { TokenType.Semicolon }); } }
/// <summary> /// Visits the next intra-state declration. /// </summary> private void VisitNextPSharpIntraStateDeclaration(StateDeclaration node) { bool fixpoint = false; var tokenRange = new TokenRange(this.TokenStream); while (!fixpoint) { Token badToken = null; if (!this.TokenStream.Done) { var token = this.TokenStream.Peek(); switch (token.Type) { case TokenType.WhiteSpace: case TokenType.QuotedString: case TokenType.Comment: case TokenType.NewLine: this.TokenStream.Index++; break; case TokenType.Async: tokenRange.Start(); this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); token = this.TokenStream.Peek(); switch (token.Type) { case TokenType.Entry: new StateEntryDeclarationVisitor(this.TokenStream).Visit(node, tokenRange, isAsync: true); this.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(this.TokenStream).Visit(node, tokenRange, isAsync: true); this.TokenStream.Index++; break; default: throw new ParsingException("'async' was used in an incorrect context.", this.TokenStream.Peek()); } break; case TokenType.CommentLine: case TokenType.Region: this.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.CommentStart: this.TokenStream.SkipWhiteSpaceAndCommentTokens(); break; case TokenType.Entry: new StateEntryDeclarationVisitor(this.TokenStream).Visit(node, tokenRange.Start()); this.TokenStream.Index++; break; case TokenType.Exit: new StateExitDeclarationVisitor(this.TokenStream).Visit(node, tokenRange.Start()); this.TokenStream.Index++; break; case TokenType.OnAction: new StateActionDeclarationVisitor(this.TokenStream).Visit(node); this.TokenStream.Index++; break; case TokenType.DeferEvent: new DeferEventsDeclarationVisitor(this.TokenStream).Visit(node); this.TokenStream.Index++; break; case TokenType.IgnoreEvent: new IgnoreEventsDeclarationVisitor(this.TokenStream).Visit(node); this.TokenStream.Index++; break; case TokenType.LeftSquareBracket: this.TokenStream.Index++; this.TokenStream.SkipWhiteSpaceAndCommentTokens(); new AttributeListVisitor(this.TokenStream).Visit(); this.TokenStream.Index++; break; case TokenType.RightCurlyBracket: this.TokenStream.Swap(TokenType.StateRightCurlyBracket); node.RightCurlyBracketToken = this.TokenStream.Peek(); fixpoint = true; break; case TokenType.Private: case TokenType.Protected: case TokenType.Internal: case TokenType.Public: throw new ParsingException("State actions cannot have modifiers.", this.TokenStream.Peek()); case TokenType.Abstract: case TokenType.Virtual: throw new ParsingException("State actions cannot be abstract or virtual.", this.TokenStream.Peek()); default: badToken = token; break; } } if (this.TokenStream.Done || badToken != null) { throw new ParsingException($"Unexpected {(this.TokenStream.Done ? "end of file" : $"token: {badToken.Text}")}.", this.TokenStream.Peek(), TokenType.Entry, TokenType.Exit, TokenType.OnAction, TokenType.DeferEvent, TokenType.IgnoreEvent, TokenType.LeftSquareBracket, TokenType.RightCurlyBracket); } } }