Laden...

[gelöst] Boolscher Parser

Erstellt von HeinzTomato vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.584 Views
HeinzTomato Themenstarter:in
345 Beiträge seit 2005
vor 15 Jahren
[gelöst] Boolscher Parser

Hallo.

Ich würde gerne eine Bedingung in einen String packen und diesen dann auf boolsche Richtigkeit prüfen:

bool istrue=ChkIfTrue("123>4"); // true
istrue=ChkIfTrue("123==4"); // false
istrue=ChkIfTrue("23+8!=22+9"); // false

Ist so etwas überhaupt mit vertretbaren Aufwand möglich? Wie gehe da richtig ran?

Mein Haus, mein Viertel, mein Blog

1.002 Beiträge seit 2007
vor 15 Jahren

Hallo HeinzTomato,

sieh dir mal diesen Thread an: Boolsche Funktion zerlegen und auswerten.
m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

3.003 Beiträge seit 2006
vor 15 Jahren

Du müsstest den String parsen. Hilfreich ist vielleicht ein Blick auf das Interpreter-Pattern.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo HeinzTomato,

siehe auch [erledigt] StringToBool - Parser

herbivore

HeinzTomato Themenstarter:in
345 Beiträge seit 2005
vor 15 Jahren

Hat alles leider nur halb geholfen. Ich habe nun einen mathematischen parser (zu meiner Schande muss ich gestehen: Von Sourceforge) im einfache boolsche Operationen erweitert:

Parser prs = new Parser();
prs.parseBool("23+10==33&&12-5!=7"); // False:

  private bool? parseBoolDetail(string expression, string splitter)
        {
            double? left=null;
            double? right=null;
            if (expression.Contains(splitter))
            {
                string leftSide = expression.Substring(0, expression.IndexOf(splitter));
                string rightSide = expression.Substring(expression.IndexOf(splitter) + splitter.Length);
                if (this.Evaluate(leftSide))
                {
                    left = Value;
                }
                if (this.Evaluate(rightSide))
                {
                    right = Value;
                }
                if (left.HasValue && right.HasValue)
                {
                    switch (splitter)
                    {
                        case "!=":
                        case "<>":
                            return left != right;
                        case "==":
                            return left == right;
                        case "<=":
                            return left <= right;                            
                        case ">=":
                            return left >= right;
                        case "<":
                            return left < right;
                        case ">":
                            return left>right;
                        default:
                            return null;
                    }
                }
            }
            return null;
        }

        public bool? parseBool(string parseString)
        {
            // && und || geht, KLAMMERN aber nicht!
            bool? retVal = null;

            // ODER-Verknüpfung:
            string[] orParses = parseString.Split(new string[] { "||" }, StringSplitOptions.None);
            if (orParses.Length > 1)
            {
                retVal = false;
                for (int i = 0; i < orParses.Length; i++)
                {
                    retVal |= parseBool(orParses[i]);
                }
            }
            else
            {

                // UND-Verknüpfung
                string[] andParses = parseString.Split(new string[] { "&&" }, StringSplitOptions.None);
                if (andParses.Length > 1)
                {
                    retVal = true;
                    for (int i = 0; i < andParses.Length; i++)
                    {
                        retVal &= parseBool(andParses[i]);
                    }
                }
                else
                {
                    retVal=null;
                    retVal = retVal ?? parseBoolDetail(parseString, "!=");
                    retVal = retVal ?? parseBoolDetail(parseString, "==");
                    retVal = retVal ?? parseBoolDetail(parseString, "<>");
                    retVal = retVal ?? parseBoolDetail(parseString, ">=");
                    retVal = retVal ?? parseBoolDetail(parseString, "<=");
                    retVal = retVal ?? parseBoolDetail(parseString, "<");
                    retVal = retVal ?? parseBoolDetail(parseString, ">");
                }
            }
            return retVal;
        }

Wie man erkennen kann, relativ "händisch". Das erkennen von Klammern im boolschen Bereich habe ich nicht durchgeführt, da die Bedingungen eher simpel gestrickt sein sollen und notfalls einfach so umgestellt werden soll, dass die Klammer unnötig werden.

Mein Haus, mein Viertel, mein Blog

3.003 Beiträge seit 2006
vor 15 Jahren

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

1.346 Beiträge seit 2008
vor 15 Jahren

vieleicht code erzeugen, den ausführen, und dann das ergebnis abfangen

Gruß pdelvo

1.002 Beiträge seit 2007
vor 15 Jahren

Hallo pdelvo,

vieleicht code erzeugen, den ausführen, und dann das ergebnis abfangen

Zeig vielleicht mal ein Beispiel.

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

1.346 Beiträge seit 2008
vor 15 Jahren

Mal schnell mit einem Internetcode zusammengeschuhstert. Es funktioniert aber und erzeugt richtige ergebnisse:

using System;
using System.Reflection;
using System.CodeDom.Compiler;
using System.Text;

namespace TrueFalse
{
	class Program
	{
		static void Main(string[] args)
		{
			Console.Write("Enter text -> ");
			string textInput = Console.ReadLine();

			Assembly assembly = CompileCode(textInput);
			object o = assembly.CreateInstance("gfoidl.Code.Test");
			Type t = o.GetType();
			MethodInfo mi = t.GetMethod("Ergebnis");
			object result = mi.Invoke(o, new object[]{});
			Console.WriteLine(result);

			Console.ReadKey();
		}
		public static Assembly CompileCode(string inputCode)
		{
			CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

			CompilerParameters cp = new CompilerParameters();
			cp.ReferencedAssemblies.Add("system.dll");
			cp.CompilerOptions = "/t:library";
			cp.GenerateInMemory = true;

			StringBuilder sb = new StringBuilder();
			sb.AppendLine(@"using System;");
			sb.AppendLine(@"namespace gfoidl.Code{");
			sb.AppendLine(@"public class Test{");
			sb.AppendLine(@"public bool Ergebnis(){");
			sb.AppendLine("return " + inputCode + " ;");
			sb.AppendLine(@"}}}");

			CompilerResults cr =
				provider.CompileAssemblyFromSource(cp, sb.ToString());

			if (cr.Errors.Count > 0)
			{
				Console.WriteLine(cr.Errors[0].ErrorText);
				return null;
			}

			return cr.CompiledAssembly;
		}
	}
}


Gruß pdelvo

1.002 Beiträge seit 2007
vor 15 Jahren

Hallo pdelvo,

okay, per Reflection funktioniert das sicher, aber ich halte es weder für einen eleganten noch für einen performanten Ansatz.

m0rius

Mein Blog: blog.mariusschulz.com
Hochwertige Malerarbeiten in Magdeburg und Umgebung: M'Decor, Ihr Maler für Magdeburg

1.346 Beiträge seit 2008
vor 15 Jahren

Ich finde diese Lösung besser, als tausende Libs von Sourceforge und co runterzuladen, von welchen man nur einen Bruchteil der Funktionalitäten braucht. Es müssen beim Programstart diese Assemlies geladen. Das braucht auch Systemrecourcen. Außerdem wird die größe des Programms mit den ganzen dlls viel größer.

Gruß pdelvo

104 Beiträge seit 2004
vor 15 Jahren

Hallo,

der Parser kann imho auch boolsche Ausdrücke:
http://www.lundin.info/mathparser.aspx

Grüße

Schaut mal im IRC vorbei:
Server: irc.euirc.net
Channel: #C#

Hinweis von herbivore vor 10 Jahren

Siehe auch:
String in Bedingung umwandeln - elegante Lösung gesucht
Formelparser (kostenlose Komponente)
Parser für mathematische Formeln (kostenlose Komponente)