/// <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);
        }
Beispiel #2
0
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        /// <param name="typeIdentifier">Type identifier</param>
        /// <param name="identifier">Identifier</param>
        /// <param name="modSet">Modifier set</param>
        internal void Visit(MachineDeclaration parentNode, Token typeIdentifier, Token identifier, ModifierSet modSet)
        {
            this.CheckMachineMethodModifierSet(modSet);

            var node = new MethodDeclaration(base.TokenStream.Program, parentNode);

            node.AccessModifier      = modSet.AccessModifier;
            node.InheritanceModifier = modSet.InheritanceModifier;
            node.TypeIdentifier      = typeIdentifier;
            node.Identifier          = identifier;
            node.IsAsync             = modSet.IsAsync;
            node.IsPartial           = modSet.IsPartial;

            node.LeftParenthesisToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            while (!base.TokenStream.Done &&
                   base.TokenStream.Peek().Type != TokenType.RightParenthesis)
            {
                base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit));

                node.Parameters.Add(base.TokenStream.Peek());

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();
            }

            node.RightParenthesisToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket &&
                 base.TokenStream.Peek().Type != TokenType.Semicolon))
            {
                throw new ParsingException("Expected \"{\" or \";\".",
                                           new List <TokenType>
                {
                    TokenType.LeftCurlyBracket,
                    TokenType.Semicolon
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.LeftCurlyBracket)
            {
                var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode, null);
                new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode);
                node.StatementBlock = blockNode;
            }
            else if (base.TokenStream.Peek().Type == TokenType.Semicolon)
            {
                node.SemicolonToken = base.TokenStream.Peek();
            }

            parentNode.MethodDeclarations.Add(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>
        /// <param name="parentNode">Node</param>
        /// <param name="modSet">Modifier set</param>
        internal void Visit(MachineDeclaration parentNode, ModifierSet modSet)
        {
            TextUnit textUnit = null;

            new TypeIdentifierVisitor(base.TokenStream).Visit(ref textUnit);
            var typeIdentifier = new Token(textUnit, TokenType.TypeIdentifier);

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                throw new ParsingException("Expected field or method identifier.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            var identifierToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                 base.TokenStream.Peek().Type != TokenType.Semicolon))
            {
                throw new ParsingException("Expected \"(\" or \";\".",
                                           new List <TokenType>
                {
                    TokenType.LeftParenthesis,
                    TokenType.Semicolon
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.LeftParenthesis)
            {
                new MachineMethodDeclarationVisitor(base.TokenStream).Visit(parentNode, typeIdentifier,
                                                                            identifierToken, modSet);
            }
            else if (base.TokenStream.Peek().Type == TokenType.Semicolon)
            {
                this.CheckMachineFieldModifierSet(modSet);

                var node = new FieldDeclaration(base.TokenStream.Program, parentNode, modSet);
                node.TypeIdentifier = typeIdentifier;
                node.Identifier     = identifierToken;
                node.SemicolonToken = base.TokenStream.Peek();

                parentNode.FieldDeclarations.Add(node);
            }
        }
Beispiel #5
0
        internal void VisitExternDeclaration(NamespaceDeclaration namespaceNode, MachineDeclaration machineNode)
        {
            // Skip over "extern".
            this.TokenStream.Index++;
            this.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (this.TokenStream.Done ||
                this.TokenStream.Peek().Type != TokenType.EventDecl)
            {
                throw new ParsingException("\"extern\" applies only to events and can have no access modifiers.", this.TokenStream.Peek(), TokenType.EventDecl);
            }

            this.VisitEventDeclaration(namespaceNode, machineNode, ModifierSet.CreateDefault(), isExtern: true);
        }
Beispiel #6
0
        /// <summary>
        /// True if the given syntax node is a machine field.
        /// </summary>
        /// <param name="node">SyntaxNode</param>
        /// <returns>Boolean value</returns>
        protected bool IsMachineField(SyntaxNode node)
        {
            var result = false;

            MachineDeclaration machine = null;

            if (!this.TryGetParentMachine(node, out machine))
            {
                return(result);
            }

            result = machine.FieldDeclarations.
                     Any(s => s.Identifier.TextUnit.Text.Equals(node.ToString()));

            return(result);
        }
Beispiel #7
0
        /// <summary>
        /// Rewrites the expression with a this expression.
        /// </summary>
        /// <param name="node">ThisExpressionSyntax</param>
        /// <returns>SyntaxNode</returns>
        private SyntaxNode RewriteExpression(ThisExpressionSyntax node)
        {
            SyntaxNode rewritten = node;

            MachineDeclaration machine = null;

            if (!base.TryGetParentMachine(rewritten, out machine))
            {
                return(rewritten);
            }

            var isMonitor = base.IsMonitor(machine.Identifier.TextUnit.Text);

            if (!isMonitor && (rewritten.Parent is ArgumentSyntax ||
                               (rewritten.Parent is AssignmentExpressionSyntax &&
                                (rewritten.Parent as AssignmentExpressionSyntax).Right.IsEquivalentTo(node))))
            {
                var text = "this.Id";

                rewritten = SyntaxFactory.ParseExpression(text);
                rewritten = rewritten.WithTriviaFrom(node);
            }
            else if (rewritten.Parent is MemberAccessExpressionSyntax &&
                     base.IsInStateScope(rewritten) &&
                     (base.IsMachineField((rewritten.Parent as MemberAccessExpressionSyntax).Name) ||
                      base.IsMachineMethod((rewritten.Parent as MemberAccessExpressionSyntax).Name)))
            {
                var text = "(";

                if (isMonitor)
                {
                    text += "this.Monitor";
                }
                else
                {
                    text += "this.Machine";
                }

                text += " as " + machine.Identifier.TextUnit.Text + ")";

                rewritten = SyntaxFactory.ParseExpression(text);
                rewritten = rewritten.WithTriviaFrom(node);
            }

            return(rewritten);
        }
        /// <summary>
        /// Visits a start state modifier.
        /// </summary>
        /// <param name="parentNode">Node</param>
        private void VisitStartStateModifier(MachineDeclaration parentNode)
        {
            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.StateDecl &&
                 base.TokenStream.Peek().Type != TokenType.ColdState &&
                 base.TokenStream.Peek().Type != TokenType.HotState))
            {
                throw new ParsingException("Expected state declaration.",
                                           new List <TokenType>
                {
                    TokenType.StateDecl
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.ColdState ||
                base.TokenStream.Peek().Type == TokenType.HotState)
            {
                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                if (base.TokenStream.Done ||
                    base.TokenStream.Peek().Type != TokenType.StateDecl)
                {
                    throw new ParsingException("Expected state declaration.",
                                               new List <TokenType>
                    {
                        TokenType.StateDecl
                    });
                }
            }

            new StateDeclarationVisitor(base.TokenStream).Visit(parentNode, true, AccessModifier.None);
        }
Beispiel #9
0
        /// <summary>
        /// Tries to return the parent machine identifier, if any.
        /// </summary>
        /// <param name="node">SyntaxNode</param>
        /// <param name="machine">MachineDeclaration</param>
        /// <returns>Boolean value</returns>
        protected bool TryGetParentMachine(SyntaxNode node, out MachineDeclaration machine)
        {
            var result = false;

            machine = null;

            var ancestors = node.Ancestors().OfType <ClassDeclarationSyntax>().ToList();

            foreach (var ancestor in ancestors)
            {
                machine = this.Project.PSharpPrograms.
                          SelectMany(p => p.NamespaceDeclarations).
                          SelectMany(n => n.MachineDeclarations).
                          FirstOrDefault(s => s.Identifier.TextUnit.Text.Equals(ancestor.Identifier.ValueText));

                if (machine != null)
                {
                    result = true;
                    break;
                }
            }

            return(result);
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        /// <param name="accMod">Access modifier</param>
        /// <param name="inhMod">Inheritance modifier</param>
        /// <param name="isAsync">Is async</param>
        /// <param name="isPartial">Is partial</param>
        internal void Visit(MachineDeclaration parentNode, AccessModifier accMod,
                            InheritanceModifier inhMod, bool isAsync, bool isPartial)
        {
            TextUnit textUnit = null;

            new TypeIdentifierVisitor(base.TokenStream).Visit(ref textUnit);
            var typeIdentifier = new Token(textUnit, TokenType.TypeIdentifier);

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                throw new ParsingException("Expected field or method identifier.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            var identifierToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                 base.TokenStream.Peek().Type != TokenType.Semicolon))
            {
                throw new ParsingException("Expected \"(\" or \";\".",
                                           new List <TokenType>
                {
                    TokenType.LeftParenthesis,
                    TokenType.Semicolon
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.LeftParenthesis)
            {
                new MethodDeclarationVisitor(base.TokenStream).Visit(parentNode, typeIdentifier,
                                                                     identifierToken, accMod, inhMod, isAsync, isPartial);
            }
            else if (base.TokenStream.Peek().Type == TokenType.Semicolon)
            {
                if (inhMod == InheritanceModifier.Abstract)
                {
                    throw new ParsingException("A field cannot be abstract.",
                                               new List <TokenType>());
                }
                else if (inhMod == InheritanceModifier.Virtual)
                {
                    throw new ParsingException("A field cannot be virtual.",
                                               new List <TokenType>());
                }
                else if (inhMod == InheritanceModifier.Override)
                {
                    throw new ParsingException("A field cannot be overriden.",
                                               new List <TokenType>());
                }

                if (isAsync)
                {
                    throw new ParsingException("A field cannot be async.",
                                               new List <TokenType>());
                }

                if (isPartial)
                {
                    throw new ParsingException("A field cannot be partial.",
                                               new List <TokenType>());
                }

                var node = new FieldDeclaration(base.TokenStream.Program, parentNode);
                node.AccessModifier = accMod;
                node.TypeIdentifier = typeIdentifier;
                node.Identifier     = identifierToken;
                node.SemicolonToken = base.TokenStream.Peek();

                parentNode.FieldDeclarations.Add(node);
            }
        }
Beispiel #11
0
        /// <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>
        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 a machine level declaration.
        /// </summary>
        private void VisitMachineLevelDeclaration(MachineDeclaration parentNode, TokenRange tokenRange)
        {
            var modSet = ModifierSet.CreateDefault();

            while (!this.TokenStream.Done &&
                   this.TokenStream.Peek().Type != TokenType.EventDecl &&
                   this.TokenStream.Peek().Type != TokenType.StateDecl &&
                   this.TokenStream.Peek().Type != TokenType.StateGroupDecl &&
                   this.TokenStream.Peek().Type != TokenType.MachineDecl &&
                   this.TokenStream.Peek().Type != TokenType.Void &&
                   this.TokenStream.Peek().Type != TokenType.Object &&
                   this.TokenStream.Peek().Type != TokenType.String &&
                   this.TokenStream.Peek().Type != TokenType.Sbyte &&
                   this.TokenStream.Peek().Type != TokenType.Byte &&
                   this.TokenStream.Peek().Type != TokenType.Short &&
                   this.TokenStream.Peek().Type != TokenType.Ushort &&
                   this.TokenStream.Peek().Type != TokenType.Int &&
                   this.TokenStream.Peek().Type != TokenType.Uint &&
                   this.TokenStream.Peek().Type != TokenType.Long &&
                   this.TokenStream.Peek().Type != TokenType.Ulong &&
                   this.TokenStream.Peek().Type != TokenType.Char &&
                   this.TokenStream.Peek().Type != TokenType.Bool &&
                   this.TokenStream.Peek().Type != TokenType.Decimal &&
                   this.TokenStream.Peek().Type != TokenType.Float &&
                   this.TokenStream.Peek().Type != TokenType.Double &&
                   this.TokenStream.Peek().Type != TokenType.Identifier)
            {
                new ModifierVisitor(this.TokenStream).Visit(modSet);

                this.TokenStream.Index++;
                this.TokenStream.SkipWhiteSpaceAndCommentTokens();
            }

            if (this.TokenStream.Done ||
                (this.TokenStream.Peek().Type != TokenType.EventDecl &&
                 this.TokenStream.Peek().Type != TokenType.StateDecl &&
                 this.TokenStream.Peek().Type != TokenType.StateGroupDecl &&
                 this.TokenStream.Peek().Type != TokenType.MachineDecl &&
                 this.TokenStream.Peek().Type != TokenType.Void &&
                 this.TokenStream.Peek().Type != TokenType.Object &&
                 this.TokenStream.Peek().Type != TokenType.String &&
                 this.TokenStream.Peek().Type != TokenType.Sbyte &&
                 this.TokenStream.Peek().Type != TokenType.Byte &&
                 this.TokenStream.Peek().Type != TokenType.Short &&
                 this.TokenStream.Peek().Type != TokenType.Ushort &&
                 this.TokenStream.Peek().Type != TokenType.Int &&
                 this.TokenStream.Peek().Type != TokenType.Uint &&
                 this.TokenStream.Peek().Type != TokenType.Long &&
                 this.TokenStream.Peek().Type != TokenType.Ulong &&
                 this.TokenStream.Peek().Type != TokenType.Char &&
                 this.TokenStream.Peek().Type != TokenType.Bool &&
                 this.TokenStream.Peek().Type != TokenType.Decimal &&
                 this.TokenStream.Peek().Type != TokenType.Float &&
                 this.TokenStream.Peek().Type != TokenType.Double &&
                 this.TokenStream.Peek().Type != TokenType.Identifier))
            {
                throw new ParsingException("Expected event, state, group or method declaration.", this.TokenStream.Peek(),
                                           TokenType.EventDecl,
                                           TokenType.StateDecl,
                                           TokenType.StateGroupDecl,
                                           TokenType.MachineDecl,
                                           TokenType.Void,
                                           TokenType.Object,
                                           TokenType.String,
                                           TokenType.Sbyte,
                                           TokenType.Byte,
                                           TokenType.Short,
                                           TokenType.Ushort,
                                           TokenType.Int,
                                           TokenType.Uint,
                                           TokenType.Long,
                                           TokenType.Ulong,
                                           TokenType.Char,
                                           TokenType.Bool,
                                           TokenType.Decimal,
                                           TokenType.Float,
                                           TokenType.Double,
                                           TokenType.Identifier);
            }

            if (this.TokenStream.Peek().Type == TokenType.EventDecl)
            {
                new EventDeclarationVisitor(this.TokenStream).Visit(parentNode.Namespace, parentNode, modSet);
            }
            else if (this.TokenStream.Peek().Type == TokenType.StateDecl)
            {
                new StateDeclarationVisitor(this.TokenStream).Visit(parentNode, null, modSet, tokenRange.Start());
            }
            else if (this.TokenStream.Peek().Type == TokenType.StateGroupDecl)
            {
                new StateGroupDeclarationVisitor(this.TokenStream).Visit(parentNode, null, modSet, tokenRange.Start());
            }
            else
            {
                new MachineMemberDeclarationVisitor(this.TokenStream).Visit(parentNode, modSet);
            }
        }
        /// <summary>
        /// Visits the next intra-machine declaration.
        /// </summary>
        private void VisitNextPSharpIntraMachineDeclaration(MachineDeclaration 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.ExternDecl:
                        new EventDeclarationVisitor(this.TokenStream).VisitExternDeclaration(node.Namespace, node);
                        this.TokenStream.Index++;
                        break;

                    case TokenType.Abstract:
                    case TokenType.StartState:
                    case TokenType.HotState:
                    case TokenType.ColdState:
                    case TokenType.EventDecl:
                    case TokenType.StateDecl:
                    case TokenType.StateGroupDecl:
                    case TokenType.Void:
                    case TokenType.MachineDecl:
                    case TokenType.Object:
                    case TokenType.String:
                    case TokenType.Sbyte:
                    case TokenType.Byte:
                    case TokenType.Short:
                    case TokenType.Ushort:
                    case TokenType.Int:
                    case TokenType.Uint:
                    case TokenType.Long:
                    case TokenType.Ulong:
                    case TokenType.Char:
                    case TokenType.Bool:
                    case TokenType.Decimal:
                    case TokenType.Float:
                    case TokenType.Double:
                    case TokenType.Identifier:
                    case TokenType.Private:
                    case TokenType.Protected:
                    case TokenType.Internal:
                    case TokenType.Public:
                    case TokenType.Async:
                    case TokenType.Partial:
                        this.VisitMachineLevelDeclaration(node, tokenRange.Start());
                        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.MachineRightCurlyBracket);
                        node.RightCurlyBracketToken = this.TokenStream.Peek();
                        fixpoint = true;
                        break;

                    default:
                        throw new ParsingException($"Unexpected token '{this.TokenStream.Peek().TextUnit.Text}'.", this.TokenStream.Peek());
                    }
                }

                if (this.TokenStream.Done)
                {
                    throw new ParsingException("Expected \"}\".", this.TokenStream.Peek(),
                                               TokenType.Private,
                                               TokenType.Protected,
                                               TokenType.StartState,
                                               TokenType.HotState,
                                               TokenType.ColdState,
                                               TokenType.StateDecl,
                                               TokenType.StateGroupDecl,
                                               TokenType.LeftSquareBracket,
                                               TokenType.RightCurlyBracket);
                }
            }
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        internal void Visit(MachineDeclaration parentNode)
        {
            var nodes        = new List <PFieldDeclaration>();
            var fieldKeyword = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                throw new ParsingException("Expected identifier.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            nodes.Add(new PFieldDeclaration(base.TokenStream.Program, parentNode,
                                            parentNode.IsModel));
            nodes[nodes.Count - 1].FieldKeyword = fieldKeyword;
            nodes[nodes.Count - 1].Identifier   = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            bool expectsComma = true;

            while (!base.TokenStream.Done &&
                   base.TokenStream.Peek().Type != TokenType.Colon)
            {
                if ((!expectsComma &&
                     base.TokenStream.Peek().Type != TokenType.Identifier) ||
                    (expectsComma && base.TokenStream.Peek().Type != TokenType.Comma))
                {
                    break;
                }

                if (base.TokenStream.Peek().Type == TokenType.Identifier)
                {
                    nodes.Add(new PFieldDeclaration(base.TokenStream.Program, parentNode,
                                                    parentNode.IsModel));
                    nodes[nodes.Count - 1].FieldKeyword = fieldKeyword;
                    nodes[nodes.Count - 1].Identifier   = 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.Colon)
            {
                throw new ParsingException("Expected \":\".",
                                           new List <TokenType>
                {
                    TokenType.Colon
                });
            }

            foreach (var node in nodes)
            {
                node.ColonToken = base.TokenStream.Peek();
            }

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            PBaseType type = null;

            new TypeIdentifierVisitor(base.TokenStream).Visit(ref type);

            foreach (var node in nodes)
            {
                node.Type = type;
            }

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Semicolon)
            {
                throw new ParsingException("Expected \";\".",
                                           new List <TokenType>
                {
                    TokenType.Semicolon
                });
            }

            foreach (var node in nodes)
            {
                node.SemicolonToken = base.TokenStream.Peek();
                parentNode.FieldDeclarations.Add(node);
            }
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="namespaceNode">Containing namespace</param>
        /// <param name="machineNode">Containing machine</param>
        /// <param name="modSet">Modifier set</param>
        internal void Visit(NamespaceDeclaration namespaceNode, MachineDeclaration machineNode, ModifierSet modSet)
        {
            this.CheckEventModifierSet(modSet, (machineNode != null));

            var node = new EventDeclaration(base.TokenStream.Program, machineNode, modSet);

            node.EventKeyword = base.TokenStream.Peek();

            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
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.Identifier)
            {
                base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                                                TokenType.EventIdentifier));
            }

            node.Identifier = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.Assert &&
                 base.TokenStream.Peek().Type != TokenType.Assume &&
                 base.TokenStream.Peek().Type != TokenType.LeftAngleBracket &&
                 base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                 base.TokenStream.Peek().Type != TokenType.Semicolon))
            {
                throw new ParsingException("Expected \"(\" or \";\".",
                                           new List <TokenType>
                {
                    TokenType.Assert,
                    TokenType.Assume,
                    TokenType.LeftParenthesis,
                    TokenType.Semicolon
                });
            }

            int genericCount = 0;

            while (!base.TokenStream.Done &&
                   base.TokenStream.Peek().Type != TokenType.Assert &&
                   base.TokenStream.Peek().Type != TokenType.Assume &&
                   base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                   base.TokenStream.Peek().Type != TokenType.Semicolon)
            {
                if (base.TokenStream.Peek().Type != TokenType.Identifier &&
                    base.TokenStream.Peek().Type != TokenType.Dot &&
                    base.TokenStream.Peek().Type != TokenType.Comma &&
                    base.TokenStream.Peek().Type != TokenType.LeftAngleBracket &&
                    base.TokenStream.Peek().Type != TokenType.RightAngleBracket &&
                    base.TokenStream.Peek().Type != TokenType.Object &&
                    base.TokenStream.Peek().Type != TokenType.String &&
                    base.TokenStream.Peek().Type != TokenType.Sbyte &&
                    base.TokenStream.Peek().Type != TokenType.Byte &&
                    base.TokenStream.Peek().Type != TokenType.Short &&
                    base.TokenStream.Peek().Type != TokenType.Ushort &&
                    base.TokenStream.Peek().Type != TokenType.Int &&
                    base.TokenStream.Peek().Type != TokenType.Uint &&
                    base.TokenStream.Peek().Type != TokenType.Long &&
                    base.TokenStream.Peek().Type != TokenType.Ulong &&
                    base.TokenStream.Peek().Type != TokenType.Char &&
                    base.TokenStream.Peek().Type != TokenType.Bool &&
                    base.TokenStream.Peek().Type != TokenType.Decimal &&
                    base.TokenStream.Peek().Type != TokenType.Float &&
                    base.TokenStream.Peek().Type != TokenType.Double)
                {
                    break;
                }

                if (genericCount == 0 &&
                    base.TokenStream.Peek().Type == TokenType.Comma)
                {
                    throw new ParsingException("Expected generic type.",
                                               new List <TokenType>
                    {
                        TokenType.Identifier
                    });
                }
                else if (base.TokenStream.Peek().Type == TokenType.LeftAngleBracket)
                {
                    node.GenericType.Add(base.TokenStream.Peek());
                    genericCount++;
                }
                else if (base.TokenStream.Peek().Type == TokenType.RightAngleBracket)
                {
                    if (genericCount == 0)
                    {
                        throw new ParsingException("Invalid generic expression.",
                                                   new List <TokenType>
                        {
                            TokenType.Identifier
                        });
                    }

                    node.GenericType.Add(base.TokenStream.Peek());
                    genericCount--;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Identifier)
                {
                    base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                                                    TokenType.EventIdentifier));
                    node.GenericType.Add(base.TokenStream.Peek());
                }
                else if (base.TokenStream.Peek().Type == TokenType.Dot ||
                         base.TokenStream.Peek().Type == TokenType.Comma ||
                         base.TokenStream.Peek().Type == TokenType.Object ||
                         base.TokenStream.Peek().Type == TokenType.String ||
                         base.TokenStream.Peek().Type == TokenType.Sbyte ||
                         base.TokenStream.Peek().Type == TokenType.Byte ||
                         base.TokenStream.Peek().Type == TokenType.Short ||
                         base.TokenStream.Peek().Type == TokenType.Ushort ||
                         base.TokenStream.Peek().Type == TokenType.Int ||
                         base.TokenStream.Peek().Type == TokenType.Uint ||
                         base.TokenStream.Peek().Type == TokenType.Long ||
                         base.TokenStream.Peek().Type == TokenType.Ulong ||
                         base.TokenStream.Peek().Type == TokenType.Char ||
                         base.TokenStream.Peek().Type == TokenType.Bool ||
                         base.TokenStream.Peek().Type == TokenType.Decimal ||
                         base.TokenStream.Peek().Type == TokenType.Float ||
                         base.TokenStream.Peek().Type == TokenType.Double)
                {
                    node.GenericType.Add(base.TokenStream.Peek());
                }

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();
            }

            if (genericCount > 0)
            {
                throw new ParsingException("Invalid generic expression.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.Assert &&
                 base.TokenStream.Peek().Type != TokenType.Assume &&
                 base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                 base.TokenStream.Peek().Type != TokenType.Semicolon))
            {
                throw new ParsingException("Expected \"(\" or \";\".",
                                           new List <TokenType>
                {
                    TokenType.Assert,
                    TokenType.Assume,
                    TokenType.LeftParenthesis,
                    TokenType.Semicolon
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.Assert ||
                base.TokenStream.Peek().Type == TokenType.Assume)
            {
                bool isAssert = true;
                if (base.TokenStream.Peek().Type == TokenType.Assert)
                {
                    node.AssertKeyword = base.TokenStream.Peek();
                }
                else
                {
                    node.AssumeKeyword = base.TokenStream.Peek();
                    isAssert           = false;
                }

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                if (base.TokenStream.Done ||
                    base.TokenStream.Peek().Type != TokenType.Identifier)
                {
                    throw new ParsingException("Expected integer.",
                                               new List <TokenType>
                    {
                        TokenType.Identifier
                    });
                }

                int value;
                if (!int.TryParse(base.TokenStream.Peek().TextUnit.Text, out value))
                {
                    throw new ParsingException("Expected integer.",
                                               new List <TokenType>
                    {
                        TokenType.Identifier
                    });
                }

                if (isAssert)
                {
                    node.AssertValue = value;
                }
                else
                {
                    node.AssumeValue = value;
                }

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                if (base.TokenStream.Done ||
                    (base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                     base.TokenStream.Peek().Type != TokenType.Semicolon))
                {
                    throw new ParsingException("Expected \"(\" or \";\".",
                                               new List <TokenType>
                    {
                        TokenType.LeftParenthesis,
                        TokenType.Semicolon
                    });
                }
            }

            if (base.TokenStream.Peek().Type == TokenType.LeftParenthesis)
            {
                node.LeftParenthesis = base.TokenStream.Peek();

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                bool isType = false;
                while (!base.TokenStream.Done &&
                       base.TokenStream.Peek().Type != TokenType.RightParenthesis)
                {
                    if (isType &&
                        base.TokenStream.Peek().Type != TokenType.Colon &&
                        base.TokenStream.Peek().Type != TokenType.Comma)
                    {
                        TextUnit textUnit = null;
                        new TypeIdentifierVisitor(base.TokenStream).Visit(ref textUnit);
                        var typeIdentifier = new Token(textUnit, TokenType.TypeIdentifier);
                        node.PayloadTypes.Add(typeIdentifier);
                    }
                    else if (base.TokenStream.Peek().Type != TokenType.Colon &&
                             base.TokenStream.Peek().Type != TokenType.Comma)
                    {
                        node.PayloadIdentifiers.Add(base.TokenStream.Peek());

                        isType = true;
                        base.TokenStream.Index++;
                        base.TokenStream.SkipWhiteSpaceAndCommentTokens();
                    }

                    if (base.TokenStream.Peek().Type == TokenType.Comma)
                    {
                        isType = false;
                        base.TokenStream.Index++;
                        base.TokenStream.SkipWhiteSpaceAndCommentTokens();
                    }
                    else if (base.TokenStream.Peek().Type == TokenType.Colon)
                    {
                        base.TokenStream.Index++;
                        base.TokenStream.SkipWhiteSpaceAndCommentTokens();
                    }
                }

                if (node.PayloadIdentifiers.Count != node.PayloadTypes.Count)
                {
                    throw new ParsingException("The payload type of event '" + node.Identifier.TextUnit.Text +
                                               "' was not declared correctly.\n" +
                                               "  You must declare both a type and a name identifier, for example:\n\n" +
                                               "    event e (a:int, b:bool)\n",
                                               new List <TokenType>
                    {
                        TokenType.RightParenthesis
                    });
                }

                if (base.TokenStream.Done ||
                    base.TokenStream.Peek().Type != TokenType.RightParenthesis)
                {
                    throw new ParsingException("Expected \")\".",
                                               new List <TokenType>
                    {
                        TokenType.RightParenthesis
                    });
                }

                node.RightParenthesis = 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
                });
            }

            node.SemicolonToken = base.TokenStream.Peek();

            // Insert into (immediately) containing namespace or machine declaration.
            if (machineNode != null)
            {
                machineNode.EventDeclarations.Add(node);
            }
            else
            {
                namespaceNode.EventDeclarations.Add(node);
            }
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Containing machine</param>
        /// <param name="groupNode">Containing group</param>
        /// <param name="accMod">Access modifier</param>
        internal void Visit(MachineDeclaration parentNode, StateGroupDeclaration groupNode, AccessModifier accMod)
        {
            var node = new StateGroupDeclaration(base.TokenStream.Program, parentNode, groupNode);

            node.AccessModifier    = accMod;
            node.StateGroupKeyword = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                throw new ParsingException("Expected state group identifier.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                                            TokenType.StateGroupIdentifier));

            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.StateGroupLeftCurlyBracket));

            node.LeftCurlyBracketToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            this.VisitNextPSharpIntraGroupDeclaration(node);

            if (groupNode == 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.",
                                           new List <TokenType>());
            }
        }
        private EventDeclaration VisitEventDeclaration(NamespaceDeclaration namespaceNode, MachineDeclaration machineNode, ModifierSet modSet, bool isExtern)
        {
            // Lookup or Insert into (immediately) containing namespace or machine declaration.
            var declarations = (machineNode != null) ? machineNode.EventDeclarations : namespaceNode.EventDeclarations;
            var node         = new EventDeclaration(base.TokenStream.Program, machineNode, modSet)
            {
                EventKeyword = base.TokenStream.Peek()
            };

            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
                });
            }

            node.Identifier = NameVisitor.VisitSimpleQualifiedName(base.TokenStream, TokenType.EventIdentifier);

            if (declarations.Find(node.Identifier.Text, out var existingDecl))
            {
                var details = existingDecl.IsExtern ? "declared \"extern\"" : "defined";
                throw new ParsingException($"Event {node.Identifier.Text} has already been {details} earlier in this file.",
                                           new List <TokenType> {
                });
            }

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.Assert &&
                 base.TokenStream.Peek().Type != TokenType.Assume &&
                 base.TokenStream.Peek().Type != TokenType.LeftAngleBracket &&
                 base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                 base.TokenStream.Peek().Type != TokenType.Colon &&
                 base.TokenStream.Peek().Type != TokenType.Semicolon))
            {
                // TODO: Create an overload of ParsingException ctor that generates the message with a predefined format enum.
                var expectedTokenTypes = new List <TokenType>
                {
                    TokenType.Assert,
                    TokenType.Assume,
                    TokenType.LeftAngleBracket,
                    TokenType.LeftParenthesis,
                    TokenType.Semicolon,
                    TokenType.Colon
                };
                var itemsString = string.Join("\", \"", expectedTokenTypes.Select(l => TokenTypeRegistry.GetText(l)).ToArray());
                throw new ParsingException($"Expected one of: \"{itemsString}\".", expectedTokenTypes);
            }

            VisitGenericType(node);
            VisitBaseEventDeclaration(node, declarations);

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.Assert &&
                 base.TokenStream.Peek().Type != TokenType.Assume &&
                 base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                 base.TokenStream.Peek().Type != TokenType.Semicolon))
            {
                throw new ParsingException("Expected \"(\" or \";\".",
                                           new List <TokenType>
                {
                    TokenType.Assert,
                    TokenType.Assume,
                    TokenType.LeftParenthesis,
                    TokenType.Semicolon
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.Assert ||
                base.TokenStream.Peek().Type == TokenType.Assume)
            {
                if (isExtern)
                {
                    throw new ParsingException("\"extern\" cannot have an Assert or Assume specification.",
                                               new List <TokenType> {
                    });
                }
                bool isAssert = true;
                if (base.TokenStream.Peek().Type == TokenType.Assert)
                {
                    node.AssertKeyword = base.TokenStream.Peek();
                }
                else
                {
                    node.AssumeKeyword = base.TokenStream.Peek();
                    isAssert           = false;
                }

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                if (base.TokenStream.Done ||
                    base.TokenStream.Peek().Type != TokenType.Identifier ||
                    !int.TryParse(base.TokenStream.Peek().TextUnit.Text, out int value))
                {
                    throw new ParsingException("Expected integer.",
                                               new List <TokenType>
                    {
                        TokenType.Identifier
                    });
                }

                if (isAssert)
                {
                    node.AssertValue = value;
                }
                else
                {
                    node.AssumeValue = value;
                }

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                if (base.TokenStream.Done ||
                    (base.TokenStream.Peek().Type != TokenType.LeftParenthesis &&
                     base.TokenStream.Peek().Type != TokenType.Semicolon))
                {
                    throw new ParsingException("Expected \"(\" or \";\".",
                                               new List <TokenType>
                    {
                        TokenType.LeftParenthesis,
                        TokenType.Semicolon
                    });
                }
            }

            if (base.TokenStream.Peek().Type == TokenType.LeftParenthesis)
            {
                node.LeftParenthesis = base.TokenStream.Peek();

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                bool isType = false;
                while (!base.TokenStream.Done &&
                       base.TokenStream.Peek().Type != TokenType.RightParenthesis)
                {
                    if (isType &&
                        base.TokenStream.Peek().Type != TokenType.Colon &&
                        base.TokenStream.Peek().Type != TokenType.Comma)
                    {
                        TextUnit textUnit = null;
                        new TypeIdentifierVisitor(base.TokenStream).Visit(ref textUnit);
                        var typeIdentifier = new Token(textUnit, TokenType.TypeIdentifier);
                        node.PayloadTypes.Add(typeIdentifier);
                    }
                    else if (base.TokenStream.Peek().Type != TokenType.Colon &&
                             base.TokenStream.Peek().Type != TokenType.Comma)
                    {
                        node.PayloadIdentifiers.Add(base.TokenStream.Peek());

                        isType = true;
                        base.TokenStream.Index++;
                        base.TokenStream.SkipWhiteSpaceAndCommentTokens();
                    }

                    if (!base.TokenStream.Done)
                    {
                        if (base.TokenStream.Peek().Type == TokenType.Comma)
                        {
                            isType = false;
                            base.TokenStream.Index++;
                            base.TokenStream.SkipWhiteSpaceAndCommentTokens();
                        }
                        else if (base.TokenStream.Peek().Type == TokenType.Colon)
                        {
                            base.TokenStream.Index++;
                            base.TokenStream.SkipWhiteSpaceAndCommentTokens();
                        }
                    }
                }

                if (node.PayloadIdentifiers.Count != node.PayloadTypes.Count)
                {
                    throw new ParsingException("The payload type of event '" + node.Identifier.TextUnit.Text +
                                               "' was not declared correctly.\n" +
                                               "  You must declare both a type and a name identifier, for example:\n\n" +
                                               "    event e (a:int, b:bool)\n",
                                               new List <TokenType>
                    {
                        TokenType.RightParenthesis
                    });
                }

                if (base.TokenStream.Done ||
                    base.TokenStream.Peek().Type != TokenType.RightParenthesis)
                {
                    throw new ParsingException("Expected \")\".",
                                               new List <TokenType>
                    {
                        TokenType.RightParenthesis
                    });
                }

                node.RightParenthesis = 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
                });
            }

            node.SemicolonToken = base.TokenStream.Peek();
            declarations.Add(node, isExtern);
            return(node);
        }
 /// <summary>
 /// Visits the syntax node.
 /// </summary>
 /// <param name="namespaceNode">Containing namespace</param>
 /// <param name="machineNode">Containing machine</param>
 /// <param name="modSet">Modifier set</param>
 internal void Visit(NamespaceDeclaration namespaceNode, MachineDeclaration machineNode, ModifierSet modSet)
 {
     this.CheckEventModifierSet(modSet, (machineNode != null));
     var node = VisitEventDeclaration(namespaceNode, machineNode, modSet, isExtern: false);
 }
Beispiel #20
0
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="program">Program</param>
        /// <param name="parentNode">Node</param>
        /// <param name="isMonitor">Is a monitor</param>
        /// <param name="modSet">Modifier set</param>
        internal void Visit(IPSharpProgram program, NamespaceDeclaration parentNode, bool isMonitor, ModifierSet modSet)
        {
            if (isMonitor)
            {
                this.CheckMonitorModifierSet(modSet);
            }
            else
            {
                this.CheckMachineModifierSet(modSet);
            }

            var node = new MachineDeclaration(base.TokenStream.Program, parentNode, isMonitor, modSet);

            node.MachineKeyword = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                throw new ParsingException("Expected machine identifier.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                                            TokenType.MachineIdentifier));

            node.Identifier = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Program is PSharpProgram)
            {
                if (base.TokenStream.Done ||
                    (base.TokenStream.Peek().Type != TokenType.Colon &&
                     base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket))
                {
                    throw new ParsingException("Expected \":\" or \"{\".",
                                               new List <TokenType>
                    {
                        TokenType.Colon,
                        TokenType.LeftCurlyBracket
                    });
                }

                if (base.TokenStream.Peek().Type == TokenType.Colon)
                {
                    node.ColonToken = base.TokenStream.Peek();

                    base.TokenStream.Index++;
                    base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                    if (base.TokenStream.Done ||
                        base.TokenStream.Peek().Type != TokenType.Identifier)
                    {
                        throw new ParsingException("Expected base machine identifier.",
                                                   new List <TokenType>
                        {
                            TokenType.Identifier
                        });
                    }

                    while (!base.TokenStream.Done &&
                           base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket)
                    {
                        if (base.TokenStream.Peek().Type != TokenType.Identifier &&
                            base.TokenStream.Peek().Type != TokenType.Dot &&
                            base.TokenStream.Peek().Type != TokenType.NewLine)
                        {
                            throw new ParsingException("Expected base machine identifier.",
                                                       new List <TokenType>
                            {
                                TokenType.Identifier,
                                TokenType.Dot
                            });
                        }
                        else
                        {
                            node.BaseNameTokens.Add(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.MachineLeftCurlyBracket));

            node.LeftCurlyBracketToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.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.",
                                           new List <TokenType>());
            }

            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.",
                                           new List <TokenType>());
            }
            else if (startStates.Count > 1)
            {
                throw new ParsingException("A machine can declare only a single start state.",
                                           new List <TokenType>());
            }
        }
        /// <summary>
        /// Visits the next intra-machine declration.
        /// </summary>
        /// <param name="node">Node</param>
        private void VisitNextPIntraMachineDeclaration(MachineDeclaration 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.StartState:
                    this.VisitStartStateModifier(node);
                    base.TokenStream.Index++;
                    break;

                case TokenType.StateDecl:
                    new StateDeclarationVisitor(base.TokenStream).Visit(node, false, AccessModifier.None);
                    base.TokenStream.Index++;
                    break;

                case TokenType.ModelDecl:
                    new FunctionDeclarationVisitor(base.TokenStream).Visit(node, true);
                    base.TokenStream.Index++;
                    break;

                case TokenType.FunDecl:
                    new FunctionDeclarationVisitor(base.TokenStream).Visit(node, false);
                    base.TokenStream.Index++;
                    break;

                case TokenType.Var:
                    new FieldDeclarationVisitor(base.TokenStream).Visit(node);
                    base.TokenStream.Index++;
                    break;

                case TokenType.ColdState:
                case TokenType.HotState:
                    base.TokenStream.Index++;
                    break;

                case TokenType.RightCurlyBracket:
                    base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                                                    TokenType.MachineRightCurlyBracket));
                    node.RightCurlyBracketToken     = base.TokenStream.Peek();
                    base.TokenStream.CurrentMachine = "";
                    fixpoint = true;
                    break;

                default:
                    throw new ParsingException("Unexpected token.",
                                               new List <TokenType>());
                }

                if (base.TokenStream.Done)
                {
                    throw new ParsingException("Expected \"}\".",
                                               new List <TokenType>
                    {
                        TokenType.StartState,
                        TokenType.StateDecl,
                        TokenType.FunDecl,
                        TokenType.Var
                    });
                }
            }
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="program">Program</param>
        /// <param name="parentNode">Node</param>
        /// <param name="isMain">Is main machine</param>
        /// <param name="isModel">Is a model</param>
        /// <param name="isMonitor">Is a monitor</param>
        /// <param name="accMod">Access modifier</param>
        /// <param name="inhMod">Inheritance modifier</param>
        internal void Visit(IPSharpProgram program, NamespaceDeclaration parentNode, bool isMain,
                            bool isModel, bool isMonitor, AccessModifier accMod, InheritanceModifier inhMod)
        {
            var node = new MachineDeclaration(base.TokenStream.Program, isMain, isModel, isMonitor);

            node.AccessModifier      = accMod;
            node.InheritanceModifier = inhMod;
            node.MachineKeyword      = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                throw new ParsingException("Expected machine identifier.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            base.TokenStream.CurrentMachine = base.TokenStream.Peek().Text;
            base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                                            TokenType.MachineIdentifier));

            node.Identifier = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Program is PSharpProgram)
            {
                if (base.TokenStream.Done ||
                    (base.TokenStream.Peek().Type != TokenType.Colon &&
                     base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket))
                {
                    throw new ParsingException("Expected \":\" or \"{\".",
                                               new List <TokenType>
                    {
                        TokenType.Colon,
                        TokenType.LeftCurlyBracket
                    });
                }

                if (base.TokenStream.Peek().Type == TokenType.Colon)
                {
                    node.ColonToken = base.TokenStream.Peek();

                    base.TokenStream.Index++;
                    base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                    if (base.TokenStream.Done ||
                        base.TokenStream.Peek().Type != TokenType.Identifier)
                    {
                        throw new ParsingException("Expected base machine identifier.",
                                                   new List <TokenType>
                        {
                            TokenType.Identifier
                        });
                    }

                    while (!base.TokenStream.Done &&
                           base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket)
                    {
                        if (base.TokenStream.Peek().Type != TokenType.Identifier &&
                            base.TokenStream.Peek().Type != TokenType.Dot &&
                            base.TokenStream.Peek().Type != TokenType.NewLine)
                        {
                            throw new ParsingException("Expected base machine identifier.",
                                                       new List <TokenType>
                            {
                                TokenType.Identifier,
                                TokenType.Dot
                            });
                        }
                        else
                        {
                            node.BaseNameTokens.Add(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.MachineLeftCurlyBracket));

            node.LeftCurlyBracketToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Program is PSharpProgram)
            {
                this.VisitNextPSharpIntraMachineDeclaration(node);
                parentNode.MachineDeclarations.Add(node);
            }
            else
            {
                this.VisitNextPIntraMachineDeclaration(node);
                (program as PProgram).MachineDeclarations.Add(node);
            }

            if (node.StateDeclarations.Count == 0 && node.BaseNameTokens.Count == 0)
            {
                throw new ParsingException("A machine must declare at least one state.",
                                           new List <TokenType>());
            }

            var initialStates = node.StateDeclarations.FindAll(s => s.IsInitial);

            if (initialStates.Count == 0 && node.BaseNameTokens.Count == 0)
            {
                throw new ParsingException("A machine must declare a start state.",
                                           new List <TokenType>());
            }
            else if (initialStates.Count > 1)
            {
                throw new ParsingException("A machine can declare only a single start state.",
                                           new List <TokenType>());
            }
        }
        /// <summary>
        /// Visits a machine level declaration.
        /// </summary>
        /// <param name="parentNode">Node</param>
        private void VisitMachineLevelDeclaration(MachineDeclaration parentNode)
        {
            AccessModifier      am = AccessModifier.None;
            InheritanceModifier im = InheritanceModifier.None;
            bool isStart           = false;
            bool isModel           = false;
            bool isAsync           = false;

            while (!base.TokenStream.Done &&
                   base.TokenStream.Peek().Type != TokenType.StateDecl &&
                   base.TokenStream.Peek().Type != TokenType.MachineDecl &&
                   base.TokenStream.Peek().Type != TokenType.Void &&
                   base.TokenStream.Peek().Type != TokenType.Object &&
                   base.TokenStream.Peek().Type != TokenType.String &&
                   base.TokenStream.Peek().Type != TokenType.Sbyte &&
                   base.TokenStream.Peek().Type != TokenType.Byte &&
                   base.TokenStream.Peek().Type != TokenType.Short &&
                   base.TokenStream.Peek().Type != TokenType.Ushort &&
                   base.TokenStream.Peek().Type != TokenType.Int &&
                   base.TokenStream.Peek().Type != TokenType.Uint &&
                   base.TokenStream.Peek().Type != TokenType.Long &&
                   base.TokenStream.Peek().Type != TokenType.Ulong &&
                   base.TokenStream.Peek().Type != TokenType.Char &&
                   base.TokenStream.Peek().Type != TokenType.Bool &&
                   base.TokenStream.Peek().Type != TokenType.Decimal &&
                   base.TokenStream.Peek().Type != TokenType.Float &&
                   base.TokenStream.Peek().Type != TokenType.Double &&
                   base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                if (am != AccessModifier.None &&
                    (base.TokenStream.Peek().Type == TokenType.Public ||
                     base.TokenStream.Peek().Type == TokenType.Private ||
                     base.TokenStream.Peek().Type == TokenType.Protected ||
                     base.TokenStream.Peek().Type == TokenType.Internal))
                {
                    throw new ParsingException("More than one protection modifier.",
                                               new List <TokenType>());
                }
                else if (im != InheritanceModifier.None &&
                         base.TokenStream.Peek().Type == TokenType.Abstract)
                {
                    throw new ParsingException("Duplicate abstract modifier.",
                                               new List <TokenType>());
                }
                else if (isStart &&
                         base.TokenStream.Peek().Type == TokenType.StartState)
                {
                    throw new ParsingException("Duplicate start state modifier.",
                                               new List <TokenType>());
                }
                else if (isModel &&
                         base.TokenStream.Peek().Type == TokenType.ModelDecl)
                {
                    throw new ParsingException("Duplicate model method modifier.",
                                               new List <TokenType>());
                }
                else if (isAsync &&
                         base.TokenStream.Peek().Type == TokenType.Async)
                {
                    throw new ParsingException("Duplicate async method modifier.",
                                               new List <TokenType>());
                }

                if (base.TokenStream.Peek().Type == TokenType.Public)
                {
                    am = AccessModifier.Public;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Private)
                {
                    am = AccessModifier.Private;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Protected)
                {
                    am = AccessModifier.Protected;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Internal)
                {
                    am = AccessModifier.Internal;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Abstract)
                {
                    im = InheritanceModifier.Abstract;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Virtual)
                {
                    im = InheritanceModifier.Virtual;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Override)
                {
                    im = InheritanceModifier.Override;
                }
                else if (base.TokenStream.Peek().Type == TokenType.StartState)
                {
                    isStart = true;
                }
                else if (base.TokenStream.Peek().Type == TokenType.ModelDecl)
                {
                    isModel = true;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Async)
                {
                    isAsync = true;
                }

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();
            }

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.StateDecl &&
                 base.TokenStream.Peek().Type != TokenType.MachineDecl &&
                 base.TokenStream.Peek().Type != TokenType.Void &&
                 base.TokenStream.Peek().Type != TokenType.Object &&
                 base.TokenStream.Peek().Type != TokenType.String &&
                 base.TokenStream.Peek().Type != TokenType.Sbyte &&
                 base.TokenStream.Peek().Type != TokenType.Byte &&
                 base.TokenStream.Peek().Type != TokenType.Short &&
                 base.TokenStream.Peek().Type != TokenType.Ushort &&
                 base.TokenStream.Peek().Type != TokenType.Int &&
                 base.TokenStream.Peek().Type != TokenType.Uint &&
                 base.TokenStream.Peek().Type != TokenType.Long &&
                 base.TokenStream.Peek().Type != TokenType.Ulong &&
                 base.TokenStream.Peek().Type != TokenType.Char &&
                 base.TokenStream.Peek().Type != TokenType.Bool &&
                 base.TokenStream.Peek().Type != TokenType.Decimal &&
                 base.TokenStream.Peek().Type != TokenType.Float &&
                 base.TokenStream.Peek().Type != TokenType.Double &&
                 base.TokenStream.Peek().Type != TokenType.Identifier))
            {
                throw new ParsingException("Expected state or method declaration.",
                                           new List <TokenType>
                {
                    TokenType.StateDecl,
                    TokenType.MachineDecl,
                    TokenType.Void,
                    TokenType.Object,
                    TokenType.String,
                    TokenType.Sbyte,
                    TokenType.Byte,
                    TokenType.Short,
                    TokenType.Ushort,
                    TokenType.Int,
                    TokenType.Uint,
                    TokenType.Long,
                    TokenType.Ulong,
                    TokenType.Char,
                    TokenType.Bool,
                    TokenType.Decimal,
                    TokenType.Float,
                    TokenType.Double,
                    TokenType.Identifier
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.StateDecl)
            {
                if (am == AccessModifier.Public)
                {
                    throw new ParsingException("A state cannot be public.",
                                               new List <TokenType>());
                }
                else if (am == AccessModifier.Internal)
                {
                    throw new ParsingException("A state cannot be internal.",
                                               new List <TokenType>());
                }

                if (im == InheritanceModifier.Abstract)
                {
                    throw new ParsingException("A state cannot be abstract.",
                                               new List <TokenType>());
                }
                else if (im == InheritanceModifier.Virtual)
                {
                    throw new ParsingException("A state cannot be virtual.",
                                               new List <TokenType>());
                }
                else if (im == InheritanceModifier.Override)
                {
                    throw new ParsingException("A state cannot be overriden.",
                                               new List <TokenType>());
                }

                if (isModel)
                {
                    throw new ParsingException("A state cannot be a model.",
                                               new List <TokenType>());
                }

                if (isAsync)
                {
                    throw new ParsingException("A state cannot be async.",
                                               new List <TokenType>());
                }

                new StateDeclarationVisitor(base.TokenStream).Visit(parentNode, isStart, am);
            }
            else
            {
                if (am == AccessModifier.Public)
                {
                    throw new ParsingException("A field or method cannot be public.",
                                               new List <TokenType>());
                }
                else if (am == AccessModifier.Internal)
                {
                    throw new ParsingException("A field or method cannot be internal.",
                                               new List <TokenType>());
                }

                new FieldOrMethodDeclarationVisitor(base.TokenStream).Visit(parentNode,
                                                                            isModel, am, im, isAsync);
            }
        }
        /// <summary>
        /// Visits the next intra-machine declration.
        /// </summary>
        /// <param name="node">Node</param>
        private void VisitNextPSharpIntraMachineDeclaration(MachineDeclaration 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.StartState:
                case TokenType.StateDecl:
                case TokenType.ModelDecl:
                case TokenType.Void:
                case TokenType.MachineDecl:
                case TokenType.Object:
                case TokenType.String:
                case TokenType.Sbyte:
                case TokenType.Byte:
                case TokenType.Short:
                case TokenType.Ushort:
                case TokenType.Int:
                case TokenType.Uint:
                case TokenType.Long:
                case TokenType.Ulong:
                case TokenType.Char:
                case TokenType.Bool:
                case TokenType.Decimal:
                case TokenType.Float:
                case TokenType.Double:
                case TokenType.Identifier:
                case TokenType.Private:
                case TokenType.Protected:
                case TokenType.Internal:
                case TokenType.Public:
                case TokenType.Async:
                    this.VisitMachineLevelDeclaration(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.MachineRightCurlyBracket));
                    node.RightCurlyBracketToken     = base.TokenStream.Peek();
                    base.TokenStream.CurrentMachine = "";
                    fixpoint = true;
                    break;

                default:
                    throw new ParsingException("Unexpected token.",
                                               new List <TokenType>());
                }

                if (base.TokenStream.Done)
                {
                    throw new ParsingException("Expected \"}\".",
                                               new List <TokenType>
                    {
                        TokenType.Private,
                        TokenType.Protected,
                        TokenType.StartState,
                        TokenType.StateDecl,
                        TokenType.ModelDecl,
                        TokenType.LeftSquareBracket,
                        TokenType.RightCurlyBracket
                    });
                }
            }
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        /// <param name="isModel">Is model</param>
        internal void Visit(MachineDeclaration parentNode, bool isModel)
        {
            var node = new PFunctionDeclaration(base.TokenStream.Program,
                                                parentNode.IsModel || isModel);

            if (isModel)
            {
                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                if (base.TokenStream.Done ||
                    base.TokenStream.Peek().Type != TokenType.FunDecl)
                {
                    throw new ParsingException("Expected function declaration.",
                                               new List <TokenType>
                    {
                        TokenType.FunDecl
                    });
                }
            }

            node.FunctionKeyword = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.Identifier)
            {
                throw new ParsingException("Expected identifier.",
                                           new List <TokenType>
                {
                    TokenType.Identifier
                });
            }

            node.Identifier = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                base.TokenStream.Peek().Type != TokenType.LeftParenthesis)
            {
                throw new ParsingException("Expected \"(\".",
                                           new List <TokenType>
                {
                    TokenType.LeftParenthesis
                });
            }

            node.LeftParenthesisToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            bool expectsColon = false;
            bool expectsType  = false;
            bool expectsComma = false;

            while (!base.TokenStream.Done &&
                   base.TokenStream.Peek().Type != TokenType.RightParenthesis)
            {
                if ((!expectsColon && !expectsComma && !expectsType &&
                     base.TokenStream.Peek().Type != TokenType.Identifier) ||
                    (!expectsColon && !expectsComma && expectsType &&
                     base.TokenStream.Peek().Type != TokenType.MachineDecl &&
                     base.TokenStream.Peek().Type != TokenType.Int &&
                     base.TokenStream.Peek().Type != TokenType.Bool &&
                     base.TokenStream.Peek().Type != TokenType.Seq &&
                     base.TokenStream.Peek().Type != TokenType.Map &&
                     base.TokenStream.Peek().Type != TokenType.LeftParenthesis) ||
                    (expectsColon && base.TokenStream.Peek().Type != TokenType.Colon) ||
                    (expectsComma && base.TokenStream.Peek().Type != TokenType.Comma))
                {
                    break;
                }

                if (!expectsType &&
                    base.TokenStream.Peek().Type == TokenType.Identifier)
                {
                    node.Parameters.Add(base.TokenStream.Peek());

                    base.TokenStream.Index++;
                    base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                    expectsColon = true;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Colon)
                {
                    base.TokenStream.Index++;
                    base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                    expectsColon = false;
                    expectsType  = true;
                }
                else if (expectsType &&
                         (base.TokenStream.Peek().Type == TokenType.MachineDecl ||
                          base.TokenStream.Peek().Type == TokenType.Int ||
                          base.TokenStream.Peek().Type == TokenType.Bool ||
                          base.TokenStream.Peek().Type == TokenType.Seq ||
                          base.TokenStream.Peek().Type == TokenType.Map ||
                          base.TokenStream.Peek().Type == TokenType.LeftParenthesis))
                {
                    PBaseType type = null;
                    new TypeIdentifierVisitor(base.TokenStream).Visit(ref type);
                    node.ParameterTypes.Add(type);

                    expectsType  = false;
                    expectsComma = true;
                }
                else if (base.TokenStream.Peek().Type == TokenType.Comma)
                {
                    base.TokenStream.Index++;
                    base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                    expectsComma = false;
                }
            }

            node.RightParenthesisToken = base.TokenStream.Peek();

            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.Colon &&
                 base.TokenStream.Peek().Type != TokenType.LeftSquareBracket &&
                 base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket))
            {
                throw new ParsingException("Expected \":\" or \"{\".",
                                           new List <TokenType>
                {
                    TokenType.Colon,
                    TokenType.LeftCurlyBracket
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.Colon)
            {
                node.ColonToken = base.TokenStream.Peek();

                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

                PBaseType type = null;
                new TypeIdentifierVisitor(base.TokenStream).Visit(ref type);
                node.ReturnType = type;
            }

            if (base.TokenStream.Peek().Type == TokenType.LeftSquareBracket)
            {
                while (!base.TokenStream.Done &&
                       base.TokenStream.Peek().Type != TokenType.LeftCurlyBracket)
                {
                    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,
                                            null, node.IsModel);

            new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode);
            node.StatementBlock = blockNode;

            parentNode.FunctionDeclarations.Add(node);
        }
Beispiel #26
0
        /// <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);
            }
        }