Пример #1
0
        static void Main(string[] args)
        {
            string expr = "1+a*3";

            Dictionary <string, double> variables = new();

            List <ITokenAcceptor <IToken> > constantAcceptors = new();

            constantAcceptors.Add(new ConstantToken.Acceptor());
            constantAcceptors.Add(new VariableToken.Acceptor());

            List <ITokenAcceptor <IToken> > binaryAcceptors = new();

            binaryAcceptors.Add(new AddToken.Acceptor());
            binaryAcceptors.Add(new SubtractToken.Acceptor());
            binaryAcceptors.Add(new MultiplyToken.Acceptor());

            int index = 0;
            ITokenBuilder <IToken>?            root       = null;
            IBinaryTokenBuilder <IBinaryToken>?lastBinary = null;
            ITokenBuilder <IToken>?            _left      = null;
            List <ITokenAcceptor <IToken> >    acceptors  = constantAcceptors;

            while (index < expr.Length)
            {
                bool foundAcceptor = false;
                foreach (ITokenAcceptor <IToken> acceptor in acceptors)
                {
                    ITokenBuilder <IToken>?builder = acceptor.Accept(expr, ref index);
                    if (builder != null)
                    {
                        IBinaryTokenBuilder <IBinaryToken>?builderAsBinary = builder as IBinaryTokenBuilder <IBinaryToken>;
                        if (root == null)
                        {
                            if (builderAsBinary != null)
                            {
                                throw new Exception("First token cannot be a binary token");
                            }

                            root = builder;
                        }

                        if (builderAsBinary != null)
                        {
                            if (lastBinary == null || lastBinary.IsMultiply || !builderAsBinary.IsMultiply)
                            {
                                if (lastBinary != null)
                                {
                                    lastBinary.Right = _left;
                                }
                                builderAsBinary.Left = root;
                                root = builder;
                            }
                            else
                            {
                                builderAsBinary.Left = _left;
                                lastBinary.Right     = builder;
                            }
                            lastBinary = builderAsBinary;
                            _left      = null;
                            acceptors  = constantAcceptors;
                        }
                        else
                        {
                            _left     = builder;
                            acceptors = binaryAcceptors;

                            if (builder is VariableToken variableToken)
                            {
                                variables[variableToken.Name] = 0;
                            }
                        }

                        foundAcceptor = true;
                        break;
                    }
                }

                if (!foundAcceptor)
                {
                    Console.WriteLine($"Cannot determine token '{expr[index]}'");
                    Console.WriteLine(expr);
                    Console.WriteLine($"{new string(' ', index)}^{new string('-', expr.Length - index + 2)}");

                    root = null;
                    break;
                }
            }

            if (_left != null && lastBinary != null)
            {
                lastBinary.Right = _left;
            }

            if (root != null)
            {
                foreach (string key in variables.Keys)
                {
                    Console.WriteLine($"Define the value for {key}:");
                    while (true)
                    {
                        string answer = Console.ReadLine() ?? "";
                        if (double.TryParse(answer, out double result))
                        {
                            variables[key] = result;
                            break;
                        }
                        else
                        {
                            Console.WriteLine("Not a double!");
                        }
                    }
                }
                IToken rootToken = root.Build();
                PrintToken(rootToken, 0, variables);
                Console.WriteLine($"Calculated: {expr} = {rootToken.Calculate(variables)}");
            }
            else
            {
                Console.WriteLine("No token defined!");
            }
        }