Yep. I suck at naming things.
I wrote this for a game someone was making. I don’t remember if he ever finished it.
It’s been quite a while since I posted anything, so I thought I’d give you an update on what I’m working on. School is still a major time sink, so I don’t know when any of these things will be finished.
Wait, WordPress 3.3.1 is out already? My ancient custom theme only works on an ancient version of WordPress, so it’s about time for a new one. I have a design in mind, but I haven’t started building it yet.
The latest Opera 12.00 snapshots have a vastly improved Tabs and Windows API. Tab Vault was made when said API sucked (as of Opera 11.62, it still does). I’ve rewritten much of the backend code to be able to take advantage of the new features. Now I’m waiting for the bugs in the new API to get fixed.
I’m currently about 2/3 done transcribing βίος-δ (Bios-delta) from Guilty Crown. I may attempt to transcribe the piano version of Light My Fire from Shakugan no Shana Final next, though the only available audio clips I have are from the show with people talking over the song. (If anyone can help me find all the episodes and times where the song is played, that would be most helpful!)
So, it turns out writing a parser is hard. Who knew? My new plan is to use ANTLR to generate a parser. I now have a mostly-working grammar based on a grammar for Python. It doesn’t yet understand that
2 x y should be evaluated as
2*x*y, but I may insert the multiplication operators before sending the expression to the parser (as I’m already doing in GlassCalc 1.x) because making the parser recognize this seems to require backtracking, which is slow. Given the computing power of modern computers and that the average expression isn’t very long, (compared to say a C++ source code file) this slowdown might not make much a difference.
I am also trying to balance power with ease of use in the new syntax. For example, can the value of a variable be a function? If not,
(x + 1)(x + 2) would evaluate to
x2 + 3x + 2 as it has in GlassCalc 1.x. If so, it would mean “try to call the result of
(x+1) as a function and pass
x+2 as the only argument”. At the moment, I’m leaning towards functions not being able to be stored as variable values, as I think the alternative is very powerful, yet very confusing.
Here’s another transcription: The song is Affections from the Broken Blade (ブレイク ブレイド, a.k.a. Break Blade) soundtrack, a beautiful, classically styled piano piece. I hope you like 4 against 3.
This song is Affections from the Broken Blade (ブレイク ブレイド, a.k.a. Break Blade) soundtrack—a beautiful, classically styled piano piece. I hope you like 4 against 3.
Time for two more transcriptions:
The first is Inevitabilis from Puella Magi Madoka Magica, Mahou Shoujo Madoka Magika, 魔法少女まどか☆マギカ or whatever the heck else you want to call it. I uploaded this one about a week ago, but I never got around to posting about it. The second is I hope so… from Kami-sama no Memo-chou (神様のメモ帳). Here are the links:
This is I hope so… from Kami-sama no Memo-chou (神様のメモ帳).
This is Inevitabilis from Puella Magi Madoka Magica, Mahou Shoujo Madoka Magika, 魔法少女まどか☆マギカ or whatever the heck else you want to call it.
There is another transcription of this song available at Eternal Sonate. Our transcriptions differ slightly in a few places, but I couldn’t say which one is more correct.
As great as Mathieu Jacques’s MTParser is, it only supports double-precision floating point numbers and it only works with .NET through a COM interface, which means I have less control over the parser and I have to register the dll. Therefore, GlassCalc 2 will feature a new parser which I am writing from the ground up. I call this new parser GCParser. I am awesome at naming things.
Here is a fairly technical description of how GCParser will work:
Design Goals of GCParser
- The parser will operate on objects deriving from GCObject. This is a completely generic class, and in fact, the only function a GCObject must have converts the object to a string so it can be displayed.
- GCParser will have two types of GCObject out-of-the-metaphorical-box: numbers and arrays. Arrays are lists of GCObjects. This means GCParser will support vector operations, and since you can make arrays of arrays, probably matrix operations too.
a = [1, 2, 3]is a 3-element array.
aretrieves the first element of the array.
- GCObjects can have properties and functions. For instance, arrays will have x, y, and z properties to make 3d vector operations easy.
[1, 2, 3].xwill return
[2, 3, 1].sort()would return
[1, 2, 3].
- GCParser will be able to operate on multiple types at once. For instance, when executing
2 * [3, 4]the parser would search for a Multiply function taking two arguments of types GCNumber and GCArray. This expression would evaluate to
[6, 8]. If no function was found, the parser would throw a type error.
- GCParser will be extensible. Extensions will be able to define not only constants and functions, but new GCObject types as well. For instance, a complex numbers extension could define a GCComplexNumber class, functions for operating on complex numbers, and a constant i. Since the parser will only create numbers and arrays normally, the extension would also need to define a constructor function,
Complex(real, imag), to make complex numbers. If the extension defined functions for adding/multiplying numbers and complex numbers together, the expression
1 + 2iwould also work. The parser would interpret this as
(number: 1) + ((number: 2) * (complex: 0 + i)).
- I haven’t figured out how this would work yet, but I want GCParser to support expressions like
[1, 2, 3].sort((a,b) => b<a). This would send a predicate function to the sort function telling it how to sort—in this case, sort descending. Likewise,
Sum(n => 0.5^n, 1, 50)would sum 0.5n from n = 1 to 50.
- Parsing occurs in three stages: tokenization, parsing and evaluation. Tokenization takes the expression and figures out what all the individual parts mean. It also generates a structure which the syntax highlighter can use instead of the convoluted regular expression system GlassCalc currently uses. Parsing takes the tokenized expression and converts it into a binary tree of operations. Evaluation traverses the tree, running each operation until it gets a final result. Parsing and evaluation will not run on the UI thread, so the program won’t freeze up if you run a long calculation.
Things That Are Not Design Goals of GCParser
- Be really fast.
- GlassCalc 2 will have a new parser. It will be magic, rainbows and unicorns. It will calculate just about anything.
- If it can’t calculate something, you can probably write an extension so it can.
So, when will it be done? Eventually. I have the tokenizer mostly complete. I am waiting for .NET 4.5 to be released before I start work on the UI, as I will make use of its new asynchronous stuff.