public void When_AssigmentParameterWithAssigmentParameters_Expect_Reference()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "v"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.WORD, "n1"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "2"),
                new SpiceToken(SpiceTokenType.WORD, "n3"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "3"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(vectorTokens, Symbols.Parameter);

            // Act
            ParseTreeEvaluator eval = new ParseTreeEvaluator();
            var spiceObject         = eval.Evaluate(tree);

            // Assert
            Assert.IsType <BracketParameter>(spiceObject);
            Assert.True(((BracketParameter)spiceObject).Name == "v");
            Assert.True(((BracketParameter)spiceObject).Parameters.Count == 2);
            Assert.True(((BracketParameter)spiceObject).Parameters[0] is AssignmentParameter);
            Assert.True(((BracketParameter)spiceObject).Parameters[1] is AssignmentParameter);
        }
        public void When_ParameterBracketWithMixedContentIsParsed_Expect_Reference()
        {
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "d"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.VALUE, "1"),
                new SpiceToken(SpiceTokenType.WORD, "tt"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "0.75ns"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode root = parser.GetParseTree(vectorTokens, Symbols.Parameter);

            var child = root.Children[0] as ParseTreeNonTerminalNode;

            Assert.NotNull(child);
            Assert.Equal(Symbols.ParameterBracket, child.Name);
            Assert.Equal(4, child.Children.Count);
            var parameters = (child.Children[2] as ParseTreeNonTerminalNode)?.Children[0] as ParseTreeNonTerminalNode;

            Assert.Equal(Symbols.Parameters, parameters?.Name);
            Assert.Equal(3, parameters?.Children.Count);
        }
        public void When_BracketParameterWithVector_Expect_Reference()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "v"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.WORD, "out"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.WORD, "0"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(vectorTokens, Symbols.Parameter);

            // Act
            ParseTreeEvaluator eval = new ParseTreeEvaluator();
            var spiceObject         = eval.Evaluate(tree);

            // Assert
            Assert.IsType <BracketParameter>(spiceObject);
            Assert.True(((BracketParameter)spiceObject).Name == "v");
            Assert.True(((BracketParameter)spiceObject).Parameters.Count == 1);
            Assert.True(((BracketParameter)spiceObject).Parameters[0] is VectorParameter);
            Assert.True((((BracketParameter)spiceObject).Parameters[0] as VectorParameter).Elements.Count == 2);
        }
        public void When_Component_Expect_Reference()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "L1"),
                new SpiceToken(SpiceTokenType.VALUE, "5"),
                new SpiceToken(SpiceTokenType.VALUE, "3"),
                new SpiceToken(SpiceTokenType.VALUE, "3MH"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(vectorTokens, Symbols.Component);

            // Act
            ParseTreeEvaluator eval = new ParseTreeEvaluator();
            var spiceObject         = eval.Evaluate(tree);

            // Assert
            Assert.IsType <Component>(spiceObject);
            Assert.True(((Component)spiceObject).Name == "L1");
            Assert.True(((Component)spiceObject).PinsAndParameters.Count == 3);
            Assert.True(((Component)spiceObject).PinsAndParameters[0] is ValueParameter);
            Assert.True(((Component)spiceObject).PinsAndParameters[1] is ValueParameter);
            Assert.True(((Component)spiceObject).PinsAndParameters[2] is ValueParameter);
        }
        public void When_AssigmentParameterWithVector_Expect_Reference()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "v"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.WORD, "out"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.WORD, "0"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "13"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(vectorTokens, Symbols.Parameter);

            // Act
            ParseTreeEvaluator eval = new ParseTreeEvaluator();
            var spiceObject         = eval.Evaluate(tree);

            // Assert
            Assert.IsType <AssignmentParameter>(spiceObject);
            Assert.True(((AssignmentParameter)spiceObject).Name == "v");
            Assert.True(((AssignmentParameter)spiceObject).Arguments.Count == 2);
            Assert.True(((AssignmentParameter)spiceObject).Value == "13");
        }
        public void When_BracketWithSingeParameters_Expect_Reference()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "pulse"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.VALUE, "1"),
                new SpiceToken(SpiceTokenType.VALUE, "2"),
                new SpiceToken(SpiceTokenType.VALUE, "3"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(vectorTokens, Symbols.Parameter);

            // Act
            ParseTreeEvaluator eval = new ParseTreeEvaluator();
            var spiceObject         = eval.Evaluate(tree);

            // Assert
            Assert.IsType <BracketParameter>(spiceObject);
            Assert.True(((BracketParameter)spiceObject).Name == "pulse");
            Assert.True(((BracketParameter)spiceObject).Parameters[0] is SingleParameter);
            Assert.True(((BracketParameter)spiceObject).Parameters[1] is SingleParameter);
            Assert.True(((BracketParameter)spiceObject).Parameters[2] is SingleParameter);
        }
        public void When_ParameterBracketWithMultipleParameterEqualEdgeCaseIsParsed_Expect_Reference()
        {
            var tokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "D"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.WORD, "Is"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "2.52e-9"),
                new SpiceToken(SpiceTokenType.WORD, "Rs"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "0.568"),
                new SpiceToken(SpiceTokenType.WORD, "N"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "1.752"),
                new SpiceToken(SpiceTokenType.WORD, "Cjo"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "4e-12"),
                new SpiceToken(SpiceTokenType.WORD, "M"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "0.4"),
                new SpiceToken(SpiceTokenType.WORD, "tt"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "20e-9"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(tokens, Symbols.Parameter);

            var child = tree.Children[0] as ParseTreeNonTerminalNode;

            Assert.NotNull(child);
            Assert.Equal(Symbols.ParameterBracket, child.Name);
        }
        public void When_ParameterEqualWithFourArgumentsIsParsed_Expect_Reference()
        {
            var tokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "fun"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.WORD, "out"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.VALUE, "1"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.VALUE, "1"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.VALUE, "1"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.WORD, "12"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode root = parser.GetParseTree(tokens, Symbols.Parameter);
            var child = root.Children[0] as ParseTreeNonTerminalNode;

            Assert.NotNull(child);
            Assert.Equal(Symbols.ParameterEqual, child.Name);
            Assert.Equal(6, child.Children.Count);
        }
        public void When_NetlistHasNewlineAfterEnd_Expect_NoException()
        {
            var tokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.END, ".end"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"), new SpiceToken(SpiceTokenType.EOF, string.Empty),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode root = parser.GetParseTree(tokens, Symbols.NetlistEnding);

            Assert.NotNull(root);
        }
        public void When_CommentStatementIsParsed_Expect_NoException()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.COMMENT, "*comment"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
            };

            var parser = new ParseTreeGenerator(true);

            parser.GetParseTree(vectorTokens, Symbols.Statement);
        }
        public void When_NetlistIsVerySimple_Expect_NoException()
        {
            var tokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.TITLE, "Example of title"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
                new SpiceToken(SpiceTokenType.END, ".end"),
                new SpiceToken(SpiceTokenType.EOF, null),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode root = parser.GetParseTree(tokens, Symbols.Netlist);

            Assert.NotNull(root);
        }
        public void When_ModelStatementIsParsed_Expect_NoException()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.DOT, "."),
                new SpiceToken(SpiceTokenType.WORD, "model"),
                new SpiceToken(SpiceTokenType.WORD, "npn"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
            };

            var parser = new ParseTreeGenerator(true);

            parser.GetParseTree(vectorTokens, Symbols.Statement);
        }
        public void When_ParameterBracketVectorIsParsed_Expect_NoException()
        {
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "v"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.WORD, "out"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.VALUE, "0"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
            };

            var parser = new ParseTreeGenerator(true);

            parser.GetParseTree(vectorTokens, Symbols.Parameter);
        }
        public void When_ComponentStatementIsParsed_Expect_NoException()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "L1"),
                new SpiceToken(SpiceTokenType.VALUE, "5"),
                new SpiceToken(SpiceTokenType.VALUE, "3"),
                new SpiceToken(SpiceTokenType.VALUE, "3MH"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
            };

            var parser = new ParseTreeGenerator(true);

            parser.GetParseTree(vectorTokens, Symbols.Statement);
        }
        public void When_ParameterBracketIsParsed_Expect_Reference()
        {
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "D1"),
                new SpiceToken(SpiceTokenType.DELIMITER, "("),
                new SpiceToken(SpiceTokenType.WORD, "BF"),
                new SpiceToken(SpiceTokenType.DELIMITER, ")"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(vectorTokens, Symbols.Parameter);

            var child = tree.Children[0] as ParseTreeNonTerminalNode;

            Assert.NotNull(child);
            Assert.Equal(Symbols.ParameterBracket, child.Name);
            Assert.Equal(4, child.Children.Count);
        }
        public void When_SubcktStatementIsParsed_Expect_NoException()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.DOT, "."),
                new SpiceToken(SpiceTokenType.WORD, "subckt"),
                new SpiceToken(SpiceTokenType.WORD, "amp"),
                new SpiceToken(SpiceTokenType.VALUE, "3"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
                new SpiceToken(SpiceTokenType.ENDS, ".ends"),
                new SpiceToken(SpiceTokenType.WORD, "amp"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
            };

            var parser = new ParseTreeGenerator(false);

            parser.GetParseTree(vectorTokens, Symbols.Statement);
        }
Ejemplo n.º 17
0
        /// <summary>
        /// Gets the parse tree.
        /// </summary>
        /// <param name="tokens">Array of tokens.</param>
        /// <param name="rootSymbol">Root symbol.</param>
        /// <param name="isDotStatementNameCaseSensitive">Specifies whether case is ignored for dot statements.</param>
        /// <returns>
        /// A reference to the root of parse tree.
        /// </returns>
        private ParseTreeNonTerminalNode GetParseTree(
            SpiceToken[] tokens,
            string rootSymbol,
            bool isDotStatementNameCaseSensitive)
        {
            if (tokens == null)
            {
                throw new ArgumentNullException(nameof(tokens));
            }

            if (rootSymbol == null)
            {
                throw new ArgumentNullException(nameof(rootSymbol));
            }

            var generator = new ParseTreeGenerator(isDotStatementNameCaseSensitive);

            return(generator.GetParseTree(tokens, rootSymbol));
        }
        public void When_Vector_Expect_Reference()
        {
            // Arrange
            var vectorTokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.VALUE, "1"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.VALUE, "2"),
                new SpiceToken(SpiceTokenType.COMMA, ","),
                new SpiceToken(SpiceTokenType.VALUE, "3"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode tree = parser.GetParseTree(vectorTokens, Symbols.Vector);

            // Act
            ParseTreeEvaluator eval = new ParseTreeEvaluator();
            var spiceObject         = eval.Evaluate(tree) as VectorParameter;

            Assert.Equal(3, spiceObject.Elements.Count);
        }
        public void When_EmptyComment_Expect_NoException()
        {
            // Arrange
            var tokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.TITLE, "Example of title"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
                new SpiceToken(SpiceTokenType.COMMENT, "*"),
                new SpiceToken(SpiceTokenType.NEWLINE, "\n"),
                new SpiceToken(SpiceTokenType.END, ".end"),
                new SpiceToken(SpiceTokenType.EOF, null),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode root = parser.GetParseTree(tokens, Symbols.Netlist);

            // Act
            ParseTreeEvaluator eval = new ParseTreeEvaluator();
            var spiceObject         = eval.Evaluate(root) as SpiceNetlist;

            Assert.NotNull(spiceObject);
        }
        public void When_ParameterEqualWithoutArgumentIsParsed_Expect_Reference()
        {
            var tokens = new SpiceToken[]
            {
                new SpiceToken(SpiceTokenType.WORD, "v"),
                new SpiceToken(SpiceTokenType.EQUAL, "="),
                new SpiceToken(SpiceTokenType.VALUE, "12"),
            };

            var parser = new ParseTreeGenerator(true);
            ParseTreeNonTerminalNode root = parser.GetParseTree(tokens, Symbols.Parameter);

            var child = root.Children[0] as ParseTreeNonTerminalNode;

            Assert.NotNull(child);
            Assert.Equal(Symbols.ParameterEqual, child.Name);
            Assert.Single(child.Children);
            var paramater_equal_single = (root.Children[0] as ParseTreeNonTerminalNode).Children[0] as ParseTreeNonTerminalNode;

            Assert.NotNull(paramater_equal_single);
            Assert.Equal(Symbols.ParameterEqualSingle, paramater_equal_single.Name);
        }
Ejemplo n.º 21
0
        public static bool TryParse(string formula, out ComplexFunction.ComplexFunction complexFunction)
        {
            var    expressionQueue = new ParseTreeGenerator();
            var    operatorStack   = new Stack <string>();
            string lastExpression  = string.Empty;
            string expression      = string.Empty;

            complexFunction = null;
            bool delayUntilLast = false;
            int  deepness       = 0;

            // remove all whitespace characters
            formula = Regex.Replace(formula, @"\s+", "");

            try
            {
                for (int cursor = 0; cursor < formula.Length; cursor++)
                {
                    expression += formula[cursor].ToString().ToLower();

                    if (!expressionQueue.TryParseExpression(expression, out _, false))
                    {
                        continue;
                    }

                    var lastPossibility = cursor == formula.Length - 1 || !expressionQueue.TryParseExpression(expression + formula[cursor + 1], out _, false);

                    // nonoperator should be interpreted lazily
                    // operators should be treated firstly

                    // first successful encounter
                    if (!delayUntilLast)
                    {
                        delayUntilLast = true;
                        // succeeded interpreting the first time// if able to parse, but no further (lazy evaluation)
                        if (operators.ContainsKey(expression))
                        {
                            if (expression == "-")
                            {
                                if (operators.ContainsKey(lastExpression))
                                {
                                    if (operators[lastExpression].IsOpening || lastExpression != ")")
                                    {
                                        // "sin(-" "acos(-" "(-" "*-" "--" "+-" "^-"
                                        // interpret as negation
                                        // carry on to last interpretation]

                                        // consider replacing "-" with "(-1)*" or "i*i*"
                                        switch (expression)
                                        {
                                        case "-":
                                            // important negation
                                            formula = formula.Remove(cursor, 1).Insert(cursor, "_&");
                                            break;
                                            //case "+":
                                            //    formula = formula.Remove(cursor, 1);
                                            //    break;
                                        }
                                        cursor    -= expression.Length;
                                        expression = string.Empty;
                                        continue;
                                    }
                                    else
                                    {
                                        // )-
                                        // interpret as subtraction
                                    }
                                }
                                else
                                {
                                    // a variable
                                    // 1234-
                                    // z-
                                    // could be 123+456-
                                    // interpret as subtraction
                                }
                            }
                        }
                        // expression is not an operator
                        else if (lastExpression != string.Empty && !operators.ContainsKey(lastExpression))
                        {
                            // should not be the case that nonoperator follows another nonoperator (as if it was implicit multiplication)
                            return(false);
                        }
                        else
                        {
                            // last time I've interpreted an operator
                            // it is alwright
                            if (!lastPossibility)
                            {
                                continue;
                            }
                        }
                    }
                    else if (!lastPossibility)
                    {
                        continue;
                    }
                    // other cases consider subsequent (not first) succsessful interpretation

                    if (operators.ContainsKey(expression))
                    {
                        if (expression == ",")
                        {
                            // crush to another "," or to "sin("
                        }
                        else if (expression == ")")
                        {
                            // crushing until "(" or "sin(" found
                            while (operatorStack.Count > 0 && !operators[operatorStack.Peek()].IsOpening)
                            {
                                expressionQueue.Enqueue(operatorStack.Pop());
                            }

                            // no "(" nor "sin(" found that is an error!
                            if (operatorStack.Count == 0)
                            {
                                return(false);
                            }

                            var openingOperator = operatorStack.Pop();

                            // an opening operator that is not "(" should carry useful information with it, let's keep it!
                            if (openingOperator != "(")
                            {
                                expressionQueue.Enqueue(openingOperator);
                            }

                            --deepness;
                        }
                        else if (operators[expression].IsOpening)
                        {
                            // highest priority when adding yet lowest when already inside (to stop propagating)
                            operatorStack.Push(expression);
                            ++deepness;
                        }
                        else
                        {
                            // > and >= shoud be differentiated when computing from the right or from the left
                            // rightmost evaluation works ONLY for supported operators and ONLY if the are neighbouring to each other
                            // leftmost evaluation pops more often
                            while (operatorStack.Count > 0 &&
                                   !operators[operatorStack.Peek()].IsOpening &&
                                   operators[operatorStack.Peek()].Priority >= operators[expression].Priority)
                            {
                                expressionQueue.Enqueue(operatorStack.Pop());
                            }

                            operatorStack.Push(expression);
                        }
                    }
                    else
                    {
                        // a constant value like "12345", or argument "z"
                        expressionQueue.Enqueue(expression);
                    }

                    lastExpression = expression;
                    // clear the expression before proceeding
                    expression     = string.Empty;
                    delayUntilLast = false;
                }

                if (deepness != 0 || expression != string.Empty)
                {
                    return(false);
                }

                while (operatorStack.Count > 0)
                {
                    expressionQueue.Enqueue(operatorStack.Pop());
                }

                return(expressionQueue.TryParseTree(out complexFunction));
            }
            catch (ArgumentException e)
            {
                // incorrect formula
                return(false);
            }
        }