/// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        internal void Visit(StateDeclaration parentNode)
        {
            if (parentNode.ExitDeclaration != null)
            {
                throw new ParsingException("Duplicate exit declaration.",
                    new List<TokenType>());
            }

            var node = new ExitDeclaration(base.TokenStream.Program, parentNode.IsModel);
            node.ExitKeyword = base.TokenStream.Peek();

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

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

            var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine,
                parentNode, node.IsModel);
            new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode);
            node.StatementBlock = blockNode;

            parentNode.ExitDeclaration = node;
        }
Beispiel #2
0
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        internal void Visit(BlockSyntax node)
        {
            node.OpenBraceToken = base.TokenStream.Peek();

            var text = "";

            int counter = 0;
            while (!base.TokenStream.Done)
            {
                text += base.TokenStream.Peek().TextUnit.Text;

                if (base.TokenStream.Peek().Type == TokenType.LeftCurlyBracket)
                {
                    counter++;
                }
                else if (base.TokenStream.Peek().Type == TokenType.RightCurlyBracket)
                {
                    counter--;
                }

                if (counter == 0)
                {
                    break;
                }

                base.TokenStream.Index++;
            }

            node.Block = CSharpSyntaxTree.ParseText(text);
        }
Beispiel #3
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="program">Program</param>
 /// <param name="node">Node</param>
 internal ExpressionNode(IPSharpProgram program, BlockSyntax node)
     : base(program, node.IsModel)
 {
     this.Parent = node;
     this.StmtTokens = new List<Token>();
     this.RewrittenStmtTokens = new List<Token>();
 }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="program">Program</param>
 /// <param name="node">Node</param>
 internal PExpressionNode(IPSharpProgram program, BlockSyntax node)
     : base(program, node)
 {
     this.Payloads = new List<PPayloadReceiveNode>();
     this.PendingPayloads = new List<PPayloadReceiveNode>();
 }
Beispiel #5
0
        /// <summary>
        /// Adds a goto state transition.
        /// </summary>
        /// <param name="eventIdentifier">Token</param>
        /// <param name="eventIdentifierTokens">Tokens</param>
        /// <param name="stateIdentifiers">Token list</param>
        /// <param name="stmtBlock">Statement block</param>
        /// <returns>Boolean</returns>
        internal bool AddGotoStateTransition(Token eventIdentifier, List<Token> eventIdentifierTokens,
            List<Token> stateIdentifiers, BlockSyntax stmtBlock = null)
        {
            if (this.GotoStateTransitions.ContainsKey(eventIdentifier) ||
                this.PushStateTransitions.ContainsKey(eventIdentifier) ||
                this.ActionBindings.ContainsKey(eventIdentifier))
            {
                return false;
            }

            this.GotoStateTransitions.Add(eventIdentifier, stateIdentifiers);
            if (stmtBlock != null)
            {
                this.TransitionsOnExitActions.Add(eventIdentifier, stmtBlock);
            }

            this.ResolvedEventIdentifierTokens[eventIdentifier] = Tuple.Create(
                eventIdentifierTokens, this.ResolvedEventIdentifierTokens.Count);

            return true;
        }
Beispiel #6
0
        /// <summary>
        /// Adds an action binding.
        /// </summary>
        /// <param name="eventIdentifier">Token</param>
        /// <param name="eventIdentifierTokens">Tokens</param>
        /// <param name="stmtBlock">BlockSyntax</param>
        /// <returns>Boolean</returns>
        internal bool AddActionBinding(Token eventIdentifier, List<Token> eventIdentifierTokens,
            BlockSyntax stmtBlock)
        {
            if (this.GotoStateTransitions.ContainsKey(eventIdentifier) ||
                this.PushStateTransitions.ContainsKey(eventIdentifier) ||
                this.ActionBindings.ContainsKey(eventIdentifier))
            {
                return false;
            }

            this.ActionBindings.Add(eventIdentifier, null);
            this.ActionHandlers.Add(eventIdentifier, stmtBlock);
            this.ResolvedEventIdentifierTokens[eventIdentifier] = Tuple.Create(
                eventIdentifierTokens, this.ResolvedEventIdentifierTokens.Count);

            return true;
        }
Beispiel #7
0
        /// <summary>
        /// Adds a goto state transition.
        /// </summary>
        /// <param name="eventIdentifier">Token</param>
        /// <param name="stateIdentifier">Token</param>
        /// <param name="stmtBlock">Statement block</param>
        /// <returns>Boolean value</returns>
        internal bool AddGotoStateTransition(Token eventIdentifier, Token stateIdentifier,
            BlockSyntax stmtBlock = null)
        {
            if (this.GotoStateTransitions.ContainsKey(eventIdentifier) ||
                this.PushStateTransitions.ContainsKey(eventIdentifier) ||
                this.ActionBindings.ContainsKey(eventIdentifier))
            {
                return false;
            }

            this.GotoStateTransitions.Add(eventIdentifier, stateIdentifier);
            if (stmtBlock != null)
            {
                this.TransitionsOnExitActions.Add(eventIdentifier, stmtBlock);
            }

            return true;
        }
Beispiel #8
0
        /// <summary>
        /// Adds an action binding.
        /// </summary>
        /// <param name="eventIdentifier">Token</param>
        /// <param name="stateIdentifier">Token</param>
        /// <returns>Boolean value</returns>
        internal bool AddActionBinding(Token eventIdentifier, BlockSyntax stmtBlock)
        {
            if (this.GotoStateTransitions.ContainsKey(eventIdentifier) ||
                this.PushStateTransitions.ContainsKey(eventIdentifier) ||
                this.ActionBindings.ContainsKey(eventIdentifier))
            {
                return false;
            }

            this.ActionBindings.Add(eventIdentifier, null);
            this.ActionHandlers.Add(eventIdentifier, stmtBlock);

            return true;
        }
        /// <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);
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        /// <param name="typeIdentifier">Type identifier</param>
        /// <param name="identifier">Identifier</param>
        /// <param name="isModel">Is model</param>
        /// <param name="accMod">Access modifier</param>
        /// <param name="inhMod">Inheritance modifier</param>
        /// <param name="isAsync">Is async</param>
        internal void Visit(MachineDeclaration parentNode, Token typeIdentifier, Token identifier,
            bool isModel, AccessModifier accMod, InheritanceModifier inhMod, bool isAsync)
        {
            if (parentNode.IsModel)
            {
                isModel = true;
            }

            var node = new MethodDeclaration(base.TokenStream.Program, isModel);
            node.AccessModifier = accMod;
            node.InheritanceModifier = inhMod;
            node.TypeIdentifier = typeIdentifier;
            node.Identifier = identifier;
            node.IsAsync = isAsync;

            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, parentNode.IsModel);
                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>
 /// Constructor.
 /// </summary>
 /// <param name="program">Program</param>
 /// <param name="node">Node</param>
 internal PPayloadSendExpressionNode(IPSharpProgram program, BlockSyntax node)
     : base(program, node)
 {
 }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        internal void Visit(StateDeclaration parentNode)
        {
            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

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

            var eventIdentifiers = new List<Token>();

            bool expectsComma = false;
            while (!base.TokenStream.Done &&
                base.TokenStream.Peek().Type != TokenType.DoAction &&
                base.TokenStream.Peek().Type != TokenType.GotoState &&
                base.TokenStream.Peek().Type != TokenType.PushState)
            {
                if ((!expectsComma &&
                    base.TokenStream.Peek().Type != TokenType.Identifier &&
                    base.TokenStream.Peek().Type != TokenType.HaltEvent &&
                    base.TokenStream.Peek().Type != TokenType.DefaultEvent) ||
                    (expectsComma && base.TokenStream.Peek().Type != TokenType.Comma))
                {
                    break;
                }

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

                    eventIdentifiers.Add(base.TokenStream.Peek());

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

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

                    expectsComma = false;
                }
            }

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.DoAction &&
                base.TokenStream.Peek().Type != TokenType.GotoState &&
                base.TokenStream.Peek().Type != TokenType.PushState))
            {
                throw new ParsingException("Expected \"do\", \"goto\" or \"push\".",
                    new List<TokenType>
                {
                    TokenType.DoAction,
                    TokenType.GotoState,
                    TokenType.PushState
                });
            }

            if (base.TokenStream.Peek().Type == TokenType.DoAction)
            {
                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

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

                if (base.TokenStream.Peek().Type == TokenType.LeftCurlyBracket)
                {
                    var blockNode = new BlockSyntax(base.TokenStream.Program,
                        parentNode.Machine, null, parentNode.IsModel);
                    new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode);

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

                    foreach (var eventIdentifier in eventIdentifiers)
                    {
                        if (!parentNode.AddActionBinding(eventIdentifier, blockNode))
                        {
                            throw new ParsingException("Unexpected action handler.",
                                new List<TokenType>());
                        }
                    }
                }
                else
                {
                    base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                    TokenType.ActionIdentifier));

                    var actionIdentifier = base.TokenStream.Peek();
                    foreach (var eventIdentifier in eventIdentifiers)
                    {
                        if (!parentNode.AddActionBinding(eventIdentifier, actionIdentifier))
                        {
                            throw new ParsingException("Unexpected action handler.",
                                new List<TokenType>());
                        }
                    }

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

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

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

                base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                    TokenType.StateIdentifier));
                var stateIdentifier = base.TokenStream.Peek();

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

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

                if (base.TokenStream.Peek().Type == TokenType.WithExit)
                {
                    base.TokenStream.Index++;
                    base.TokenStream.SkipWhiteSpaceAndCommentTokens();

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

                    var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine,
                        null, parentNode.IsModel);
                    new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode);

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

                    foreach (var eventIdentifier in eventIdentifiers)
                    {
                        if (!parentNode.AddGotoStateTransition(eventIdentifier, stateIdentifier, blockNode))
                        {
                            throw new ParsingException("Unexpected goto state transition.",
                                new List<TokenType>());
                        }
                    }

                    if (base.TokenStream.Done ||
                        base.TokenStream.Peek().Type != TokenType.Semicolon)
                    {
                        throw new ParsingException("Expected \";\".",
                            new List<TokenType>
                        {
                            TokenType.Semicolon
                        });
                    }
                }
                else
                {
                    foreach (var eventIdentifier in eventIdentifiers)
                    {
                        if (!parentNode.AddGotoStateTransition(eventIdentifier, stateIdentifier))
                        {
                            throw new ParsingException("Unexpected goto state transition.",
                                new List<TokenType>());
                        }
                    }
                }
            }
            else if (base.TokenStream.Peek().Type == TokenType.PushState)
            {
                if (parentNode.Machine.IsMonitor)
                {
                    throw new ParsingException("Monitors cannot \"push\".",
                        new List<TokenType>());
                }

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

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

                base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                    TokenType.StateIdentifier));
                var stateIdentifier = base.TokenStream.Peek();

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

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

                foreach (var eventIdentifier in eventIdentifiers)
                {
                    if (!parentNode.AddPushStateTransition(eventIdentifier, stateIdentifier))
                    {
                        throw new ParsingException("Unexpected push state transition.",
                            new List<TokenType>());
                    }
                }
            }
        }
        /// <summary>
        /// Visits the syntax node.
        /// </summary>
        /// <param name="parentNode">Node</param>
        internal void Visit(StateDeclaration parentNode)
        {
            base.TokenStream.Index++;
            base.TokenStream.SkipWhiteSpaceAndCommentTokens();

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

            var nameVisitor = new NameVisitor(base.TokenStream);

            // Consumes multiple generic event names.
            var eventIdentifiers =
                nameVisitor.ConsumeMultipleNames(TokenType.EventIdentifier,
                tt => nameVisitor.ConsumeGenericEventName(tt));

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

            if (!base.TokenStream.Done &&
                (base.TokenStream.Peek().Type == TokenType.LeftAngleBracket ||
                 base.TokenStream.Peek().Type == TokenType.RightAngleBracket))
            {
                throw new ParsingException("Invalid generic expression.",
                    new List<TokenType> { });
            }

            if (base.TokenStream.Done ||
                (base.TokenStream.Peek().Type != TokenType.DoAction &&
                base.TokenStream.Peek().Type != TokenType.GotoState &&
                base.TokenStream.Peek().Type != TokenType.PushState))
            {
                throw new ParsingException("Expected \"do\", \"goto\" or \"push\".",
                    new List<TokenType>
                {
                    TokenType.DoAction,
                    TokenType.GotoState,
                    TokenType.PushState
                });
            }

            var resolvedEventIdentifiers = new Dictionary<Token, List<Token>>();
            foreach (var eventIdentifier in eventIdentifiers)
            {
                if (eventIdentifier.Count == 1)
                {
                    // We don't want to collapse halt and default
                    // events to event identifiers.
                    resolvedEventIdentifiers.Add(eventIdentifier[0], eventIdentifier);
                }
                else
                {
                    var identifierBuilder = new StringBuilder();
                    foreach (var token in eventIdentifier)
                    {
                        identifierBuilder.Append(token.TextUnit.Text);
                    }

                    TextUnit textUnit = new TextUnit(identifierBuilder.ToString(),
                        eventIdentifier[0].TextUnit.Line);
                    resolvedEventIdentifiers.Add(new Token(textUnit, TokenType.EventIdentifier),
                        eventIdentifier);
                }
            }

            if (base.TokenStream.Peek().Type == TokenType.DoAction)
            {
                base.TokenStream.Index++;
                base.TokenStream.SkipWhiteSpaceAndCommentTokens();

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

                if (base.TokenStream.Peek().Type == TokenType.LeftCurlyBracket)
                {
                    var blockNode = new BlockSyntax(base.TokenStream.Program,
                        parentNode.Machine, null);
                    new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode);

                    foreach (var kvp in resolvedEventIdentifiers)
                    {
                        if (!parentNode.AddActionBinding(kvp.Key, kvp.Value, blockNode))
                        {
                            throw new ParsingException("Unexpected action handler.",
                                new List<TokenType>());
                        }
                    }
                }
                else
                {
                    base.TokenStream.Swap(new Token(base.TokenStream.Peek().TextUnit,
                    TokenType.ActionIdentifier));

                    var actionIdentifier = base.TokenStream.Peek();
                    foreach (var kvp in resolvedEventIdentifiers)
                    {
                        if (!parentNode.AddActionBinding(kvp.Key, kvp.Value, actionIdentifier))
                        {
                            throw new ParsingException("Unexpected action handler.",
                                new List<TokenType>());
                        }
                    }

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

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

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

                if (base.TokenStream.Peek().Type == TokenType.WithExit)
                {
                    base.TokenStream.Index++;
                    base.TokenStream.SkipWhiteSpaceAndCommentTokens();

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

                    var blockNode = new BlockSyntax(base.TokenStream.Program, parentNode.Machine, null);
                    new BlockSyntaxVisitor(base.TokenStream).Visit(blockNode);

                    foreach (var kvp in resolvedEventIdentifiers)
                    {
                        if (!parentNode.AddGotoStateTransition(kvp.Key, kvp.Value, stateIdentifiers, blockNode))
                        {
                            throw new ParsingException("Unexpected goto state transition.",
                                new List<TokenType>());
                        }
                    }
                }
                else
                {
                    foreach (var kvp in resolvedEventIdentifiers)
                    {
                        if (!parentNode.AddGotoStateTransition(kvp.Key, kvp.Value, stateIdentifiers))
                        {
                            throw new ParsingException("Unexpected goto state transition.",
                                new List<TokenType>());
                        }
                    }
                }
            }
            else if (base.TokenStream.Peek().Type == TokenType.PushState)
            {
                if (parentNode.Machine.IsMonitor)
                {
                    throw new ParsingException("Monitors cannot \"push\".",
                        new List<TokenType>());
                }

                var stateIdentifiers = this.ConsumeState();

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

                foreach (var kvp in resolvedEventIdentifiers)
                {
                    if (!parentNode.AddPushStateTransition(kvp.Key, kvp.Value, stateIdentifiers))
                    {
                        throw new ParsingException("Unexpected push state transition.",
                            new List<TokenType>());
                    }
                }
            }
        }
Beispiel #14
0
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="program">Program</param>
 /// <param name="node">Node</param>
 internal PExpressionNode(IPSharpProgram program, BlockSyntax node)
     : base(program, node)
 {
     this.Payloads        = new List <PPayloadReceiveNode>();
     this.PendingPayloads = new List <PPayloadReceiveNode>();
 }