Пример #1
0
        private Node ParseTerminal(ILexer lexer)
        {
            Node result;

            switch (lexer.Token)
            {
            // Nested
            case TokenType.LeftParenthesis:
                lexer.ReadToken();
                result = ParseConditional(lexer);
                if (lexer.Token != TokenType.RightParenthesis)
                {
                    throw new Exception("Unclosed parenthesis");
                }
                lexer.ReadToken();
                break;

            // A number
            case TokenType.Number:
                result = Node.Constant(SpiceHelper.ParseNumber(lexer.Content));
                lexer.ReadToken();
                break;

            // Can be a variable or a function call
            case TokenType.Identifier:
                string name = lexer.Content;
                lexer.ReadToken();
                if (lexer.Token == TokenType.LeftParenthesis)
                {
                    // Function call!
                    string function = null;
                    switch (name.ToLowerInvariant())
                    {
                    case "vr":
                        function = "real"; goto case "v";

                    case "vi":
                        function = "imag"; goto case "v";

                    case "vm":
                        function = "abs"; goto case "v";

                    case "vdb":
                        function = "db"; goto case "v";

                    case "vph":
                        function = "phase"; goto case "v";

                    case "v":
                        // Read the nodes
                        lexer.ReadNode();
                        result = Node.Voltage(lexer.Content);
                        lexer.ReadToken();
                        if (lexer.Token == TokenType.Comma)
                        {
                            lexer.ReadNode();
                            result = Node.Subtract(result, Node.Voltage(lexer.Content));
                            lexer.ReadToken();
                        }
                        if (lexer.Token != TokenType.RightParenthesis)
                        {
                            throw new Exception("Invalid voltage specifier");
                        }
                        lexer.ReadToken();
                        break;

                    case "ir":
                        function = "real"; goto case "i";

                    case "ii":
                        function = "imag"; goto case "i";

                    case "im":
                        function = "abs"; goto case "i";

                    case "idb":
                        function = "db"; goto case "i";

                    case "iph":
                        function = "phase"; goto case "i";

                    case "i":
                        // Read the name
                        lexer.ReadNode();
                        result = Node.Current(lexer.Content);
                        lexer.ReadToken();
                        if (lexer.Token != TokenType.RightParenthesis)
                        {
                            throw new Exception("Invalid current specifier");
                        }
                        lexer.ReadToken();
                        break;

                    default:
                        var arguments = new List <Node>(2);

                        // Let's go to the first token after the function call
                        lexer.ReadToken();
                        while (lexer.Token != TokenType.RightParenthesis)
                        {
                            // Read the argument
                            arguments.Add(ParseConditional(lexer));

                            // Continue with another argument
                            if (lexer.Token == TokenType.Comma)
                            {
                                lexer.ReadToken();
                            }
                            else if (lexer.Token != TokenType.RightParenthesis)
                            {
                                throw new Exception("Invalid function call");
                            }
                        }
                        result = Node.Function(name, arguments);
                        lexer.ReadToken();
                        break;
                    }
                    if (function != null)
                    {
                        result = Node.Function(function, new[] { result });
                    }
                }
                else
                {
                    result = Node.Variable(name);
                    // We already read the next token, no need to do it here again...
                }
                break;

            case TokenType.At:
                lexer.ReadNode();
                name = lexer.Content;
                lexer.ReadToken();
                if (lexer.Token != TokenType.LeftIndex)
                {
                    throw new Exception("Invalid property identifier");
                }
                lexer.ReadNode();
                result = Node.Property(name, lexer.Content);
                lexer.ReadToken();
                if (lexer.Token != TokenType.RightIndex)
                {
                    throw new Exception("Invalid property identifier");
                }
                lexer.ReadToken();
                break;

            // There is no level below this, so let's throw an exception
            default:
                throw new Exception("Invalid value");
            }
            return(result);
        }
        private static Node ParseTerminal(Lexer lexer)
        {
            Node result;

            switch (lexer.Type)
            {
            case TokenType.LeftParenthesis:
                lexer.Next();
                result = ParseConditional(lexer);
                if (lexer.Type != TokenType.RightParenthesis)
                {
                    throw new ParserException("Expected closing parenthesis, but found '{0}'".FormatString(lexer.Content));
                }
                lexer.Next();
                break;

            case TokenType.Number:
                result = SpiceHelper.ParseNumber(lexer.Content);
                lexer.Next();
                break;

            case TokenType.Identifier:
                string name = lexer.Content;
                lexer.Next();
                if (lexer.Type == TokenType.LeftParenthesis)
                {
                    // Function call!
                    lexer.Next();

                    string function = null;
                    switch (name.ToLowerInvariant())
                    {
                    case "vr":
                        function = "real";
                        goto case "v";

                    case "vi":
                        function = "imag";
                        goto case "v";

                    case "vm":
                        function = "abs";
                        goto case "v";

                    case "vdb":
                        function = "db";
                        goto case "v";

                    case "vp":
                        function = "arg";
                        goto case "v";

                    case "v":
                        // Read the nodes
                        lexer.ContinueWhileNode();
                        result = Node.Voltage(lexer.Content);
                        lexer.Next();
                        if (lexer.Type == TokenType.Comma)
                        {
                            lexer.Next(); lexer.ContinueWhileNode();
                            result = Node.Subtract(result, Node.Voltage(lexer.Content));
                            lexer.Next();
                        }
                        if (lexer.Type != TokenType.RightParenthesis)
                        {
                            throw new ParserException(lexer, "Expected closing parenthesis but found '{0}'".FormatString(lexer.Content));
                        }
                        lexer.Next();
                        break;

                    case "ir":
                        function = "real";
                        goto case "i";

                    case "ii":
                        function = "imag";
                        goto case "i";

                    case "im":
                        function = "abs";
                        goto case "i";

                    case "idb":
                        function = "db";
                        goto case "i";

                    case "ip":
                        function = "arg";
                        goto case "i";

                    case "i":
                        // Read the nodes
                        lexer.ContinueWhileNode();
                        result = Node.Current(lexer.Content);
                        lexer.Next();
                        if (lexer.Type != TokenType.RightParenthesis)
                        {
                            throw new ParserException("Expected closing parenthesis but found '{0}'".FormatString(lexer.Content));
                        }
                        lexer.Next();
                        break;

                    default:
                        var arguments = new List <Node>(2);
                        while (lexer.Type != TokenType.RightParenthesis)
                        {
                            arguments.Add(ParseConditional(lexer));

                            // continue
                            if (lexer.Type == TokenType.Comma)
                            {
                                lexer.Next();
                            }
                            else if (lexer.Type != TokenType.RightParenthesis)
                            {
                                throw new ParserException("Expected closing parenthesis but found '{0}'".FormatString(lexer.Content));
                            }
                        }
                        result = Node.Function(name, arguments);
                        lexer.Next();
                        break;
                    }
                    if (function != null)
                    {
                        Node.Function(function, new[] { result });
                    }
                }
                else
                {
                    result = Node.Variable(name);
                }
                break;

            case TokenType.At:
                lexer.Next();
                lexer.ContinueWhileNode();
                name = lexer.Content;
                lexer.Next();
                if (lexer.Type != TokenType.LeftIndex)
                {
                    throw new ParserException("Expected property indexing, but found '{0}'".FormatString(lexer.Content));
                }
                lexer.Next();
                lexer.ContinueWhileNode();
                result = Node.Property(name, lexer.Content);
                if (lexer.Type != TokenType.RightIndex)
                {
                    throw new ParserException("Expected closing indexer, but found '{0}'".FormatString(lexer.Content));
                }
                break;

            default:
                throw new ParserException("Invalid value");
            }
            return(result);
        }