Entwickler-Ecke
Open Source Projekte - GenPar - Ein generischer Parser
Kha - Di 28.03.06 22:23
Titel: GenPar - Ein generischer Parser
Dann will ich mich auch mal an diesem wirklich netten Forum beteiligen :wink2: .
(Für alle ohne Framework (und natürlich auch alle anderen) gibt es hier [http://aspspider.net/khabarakh/GenTest/default.aspx] eine Testseite)
GenPar
Assembly: GenPar.dll
Root-Namespace: Kha.GenPar
.NET-Version: 2.0.50727
Größe: 40,0 KB
Signed
Quelltext
1:
| cos(e * 12) / (2 * (e * 6,28 + 1)) |
Ein mathematischer Ausdruck, wie wir ihn lieben (oder auch nicht) und wie er von tausenden Parsern auf der ganzen Welt zerlegt werden kann. Ergo: Langweilig :zwinker:
Quelltext
1:
| (!Hugo xor pi > e ? cos(e * 12) / (2 * (e * 6,28 + 1)) : log(a; 3)) ^ 3 * 21 / 32 |
(Default-Expression der Testseite)
Hui, langsam wird es schon etwas außer- und ungewöhnlicher. Aber generisch ist daran noch nichts, das wird es erst beispielsweise mit so etwas:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35: 36: 37: 38: 39: 40: 41: 42: 43: 44: 45: 46: 47: 48: 49: 50: 51: 52: 53: 54: 55: 56: 57: 58: 59: 60: 61: 62: 63: 64:
| using System; using System.Collections.Generic; using System.Text; using Kha.GenPar; using Kha.GenPar.Infix; using System.Reflection;
namespace ConsoleApplication1 { class Program { interface IGreatForum { } class CSharpForum : Object, IGreatForum { } static void Main(string[] args) { InfixParser parser = new InfixParser(); parser.RegisteredTypes.IncludeTypes(typeof(Program)); parser.RegisteredTypes.Variables.Add(new Variable(typeof(IGreatForum), "great"));
parser.Parse("CSharpForum is great"); Console.WriteLine(parser.Root.Evaluate()); Console.ReadLine(); } static List<Type> classList = new List<Type>(Assembly.GetCallingAssembly().GetTypes());
[SimpleLiteral()] public static Type ToType(string s, out int length, out bool succeeded) { foreach (Type t in classList) if (s.StartsWith(t.Name)) { length = t.Name.Length; succeeded = true; return t; } length = 42; succeeded = false; return null; }
[InfixOperator(110, @"\a is \a")] public static bool Is(Type t1, Type t2) { return t2.IsAssignableFrom(t1); } } } |
Hmm. Wir haben sozusagen einen komplett neuen Parser geschrieben, und das mit genau 64 Zeilen, von denen die meisten aus Kommentaren bestehen. Nicht schlecht, würde ich mit wenigstens einem kleinem Bisschen Eigenlob sagen :angel: .
Zum Sourcecode: Da ich eigentlich nur OS-Projekte schreibe und die Assembly sowieso unter der GPL steht, ich gleichzeitig aber die erste verwendbare Version sofort ins Netz stellen wollte, ist der Sourcecode an manchen Stellen noch etwas - nun ja - "inoptimal" ;) . Zur Lektüre würde ich also lieber auf eine der nächsten Versionen warten, morgen werde ich mal FxCop drüberlaufen lassen. Wie gesagt, er läuft, aber in den nächsten Versionen wird das Ganze noch einmal um Einiges generischer werden (-> Plugins). Es sei mir verziehen, wenn man Stellen durch C# oder das Framework eigentlich viel eleganter hätte schreiben können, ich sharpe (^^) (leider) erst seit einem halben Jahr. Achja, irgendwelche Form von Doku lässt auch noch bis zur nächsten Version auf sich warten ;) .
TODO (nicht vollständig, einfach alles, was mir im Moment einfällt):
- Vektoren
- Komplexe Zahlen
- Ein UPN-Parser
- Ein Operator-Browser
- generische Variablen/Konstanten
- Ein Precompiler (konstante Teile des Ausdrucks)
- Optimierungen
- IL-Compiler (Reflection = schnarch)
(Wahrscheinlich wieder die Hälfte vergessen -.-)
GenPar.zip [
http://www.honoghr.de/up/GenPar.zip]
Christian S. - Di 28.03.06 22:56
Hallo!
Ich kann das wohl erst morgen ausführlich testen, aber es sieht wirklich gut aus! :zustimm:
Für alle, die auch noch testen wollen: Mal einen Blick in den Ordner "Packages" werfen ;-)
Tschuldige, dass ich jetzt nicht mehr schreibe, aber wie gesagt: getestet wird morgen :-)
Grüße
Christian
Kha - Di 18.04.06 19:08
@Christian: Lass dir Zeit ;) .
Version 1.1.2298.22751 ^^
- Hab mal mit der Dokumentation angefangen, der Attributes-Ordner ist soweit fertig.
- Alle Exceptions sind ab nun lokalisiert (deutsch + englisch).
- MethodLiteral-Klasse: ziemlich ähnlich wie SimpleLiteralAttribute, aber weniger Reflection (in alle Standard-Packages eingebaut).
- DefiningOperatorsAttribute-Klasse: Alle selbstdefinierten Operatoren ("operator XYZ") werden automatisch in den Parser übernommen.
- Noch ein paar neue InfixOperatorAttribute-ctors
- Komplexe Zahlen (Complex(Package)) und Vektoren (Vector2(Package), Vector3(Package))
Ein kleiner Bleistift zu den 3D-Vektoren:
C#-Quelltext
1: 2: 3: 4: 5: 6: 7:
| static void Main(string[] args) { InfixParser parser = new InfixParser(new Vector3Package()); parser.Parse("(1; 0; 0) x (0; 2; 0)"); Console.WriteLine(parser.Root.Evaluate()); Console.ReadLine(); } |
Christian S. - Di 18.04.06 19:12
Khabarakh hat folgendes geschrieben: |
@Christian: Lass dir Zeit ;) . |
:oops: Peinlich. Vielleicht denke ich heute abend dran ;-)
AXMD - Di 18.04.06 19:17
Sieht genial aus :). Mich würde interessieren, wozu das hier gut is (was es macht is mir klar) ^^
Delphi-Quelltext
1:
| this.justReal = Math.Abs(imaginary) < epsilon; |
Außerdem: warum hast du dieses justReal-Feld überhaupt? Ginge das nicht einfacher über eine Methode - muss ja nicht gleich ein Attribut sein ;)? Und wieso hast du die Multiplikation und Division derart kompliziert gelöst? Das ginge viel einfacher/schneller mit Betrag und Phase. Falls du noch mehr Funktionen brauchst (e^, log, sinh etc.) meld dich einfach mal per PN ;)
AXMD
Christian S. - Di 18.04.06 19:20
Sieht für mich so aus, als würde einem das sagen, ob die Zahl rein reell ist. Also der Im.teil = 0 (im Rahmen der Genauigkeit Epsilon).
AXMD - Di 18.04.06 19:27
Christian S. hat folgendes geschrieben: |
Sieht für mich so aus, als würde einem das sagen, ob die Zahl rein reell ist. Also der Im.teil = 0 (im Rahmen der Genauigkeit Epsilon). |
Ist klar, nur das würde doch viel besser in eine Methode passen - find ich zumindest ;). Aber gut, die Dikussion ist hier an der falschen Stelle ;)
AXMD
BenBE - Di 18.04.06 19:44
Kann es sein, dass die Testseite nicht funktioniert?
Kha - Di 18.04.06 19:53
AXMD hat folgendes geschrieben: |
Sieht genial aus :). |
Danke :D .
AXMD hat folgendes geschrieben: |
Mich würde interessieren, wozu das hier gut is (was es macht is mir klar) ^^
Delphi-Quelltext 1:
| this.justReal = Math.Abs(imaginary) < epsilon; | |
Epsilon habe ich eingefügt, damit wenigstens i^2 = -1 ist ;) . Und eine Methode wäre spätestens damit viel zu kostspielig gewesen.
AXMD hat folgendes geschrieben: |
Außerdem: warum hast du dieses justReal-Feld überhaupt? Ginge das nicht einfacher über eine Methode - muss ja nicht gleich ein Attribut sein ;)? Und wieso hast du die Multiplikation und Division derart kompliziert gelöst? Das ginge viel einfacher/schneller mit Betrag und Phase. Falls du noch mehr Funktionen brauchst (e^, log, sinh etc.) meld dich einfach mal per PN ;) |
So hab ich es eben gelernt ;) . Schneller wäre es durch die Umrechnung zwischen den zwei Systemen wahrscheinlich nicht, aber ich könnte testweise mal eine Klasse, die mit den Polarkoordinaten rechnet, einbauen.
Robert_G - Di 18.04.06 19:55
BenBE hat folgendes geschrieben: |
Kann es sein, dass die Testseite nicht funktioniert? |
Hast wahrscheinlich das gleiche Problem wie ich: englisches Windows. ;)
Wenn du im Browser die Sprache auf deutsch stellst gates...
ASPX verwendet die Localsettings des Browser um die UI-Culture des serverseitigen Threads festzulegen. Klaradings' Beispielformel enthält zum Bleistift , als Dezimaltrenner. Ein double.Parse dürfte dann wohl schiefgehen. ;)
BenBE - Di 18.04.06 20:13
Ne, englischen FF mit de als Preferred Setting ;-)
Jetzt ging's aber plötzlich ...
Aber Shakespeare mag der Parser trotzdem nicht:
Std + Int-Package
(2*b) or not (2*b)
Wird mit nem Lex-Fehler quittiert, nehm ich das Bool-Package rein, gibt's nen Parser-Fehler.
Mein Delphi sagt mir korrekt -1 (oder 2^32-1 bei Unsigned).
Verbessert werden sollt, dass er die genaue Stelle des Fehlers markiert.
Kha - Di 18.04.06 21:18
BenBE hat folgendes geschrieben: |
|
Bitweise Operatoren fand ich für einen in erster Linie mathematischen Parser unnötig. Aber ist natürlich kein Probelm, sie für die nächste Version einzufügen, damit er auch der Werke des Herrn Schüttelspeer mächtig ist ;) .
Die Lokalisierungsprobleme sind jetzt (hoffentlich) gelöst, der Beispielterm wird automatisch angepasst.
Zitat: |
Verbessert werden sollt, dass er die genaue Stelle des Fehlers markiert. |
Ist leider nicht annähernd so leicht wie bei einem statischen Parser :? . Wird aber auf jeden Fall noch kommen :) .
Entwickler-Ecke.de based on phpBB
Copyright 2002 - 2011 by Tino Teuber, Copyright 2011 - 2025 by Christian Stelzmann Alle Rechte vorbehalten.
Alle Beiträge stammen von dritten Personen und dürfen geltendes Recht nicht verletzen.
Entwickler-Ecke und die zugehörigen Webseiten distanzieren sich ausdrücklich von Fremdinhalten jeglicher Art!