Making a programming language Part 3 - adding features

Posted on August 31, 2012

Table of contentsWhole project on github

So now I have a repl that can evaluate stuff like

(2+3)*(7/2-1)

Not much of a programming language - more like a calculator, and not even a good one. Lets add some features!

Constants

Like pi, e and such. I have to change the grammar to match identifiers too.

Now I have

And I change that to

and I also added a new token type

and enabled this in evaluator

StdLib is just a map object. I went the python way - variables(and constants) are entries in a global dictionary. Just a decision I made while implementing this. As I said, I don’t have a plan, I don’t know what I’m doing and I don’t know how stuff is done. How hard can it be?! (Top Gear anyone?)

Exponentiation

Another math feature. It’s more of a test for myself to see if I understand grammars. Especially how to make a grammar not left-recursive. Because apparently such grammars don’t work with RDP. I turned out I don’t understand grammars.

The ||| operator is an ugly hack. It tries both sides and returns the longer match. By the time I was writing this I didn’t know that order is importat. If I just wrote exponent | value it would have worked, because expoenent would match a value anyway and then failed on missing ^.

Token and evaluation(uses math.pow) for this are quite trivial.

Function calls

Simple: function call is a name and list of expressions to evaluate for arguments(wrapped because even an expression list is an expression)

Parser:

Again, I was having trouble - parser just didn’t work and resorted to |||. functionCall should come before identifier.

Evaluating this is more interesting. I decided to make functions be values too for obvious reasons -> higher order functions(I’m into functional programming, remember?). So function values must be stored in same “namespace”. StdLib(the only “namespace”) required to become of type Map[String,Any]. I will have to do pattern matching anyway since this will be dynamic-typed language. (Yes this is a plan, I think it’s easier to implement. Static typing ftw, but that’s next project). And I needed a type for function values to pattern match on - I went with Any=>Any and sending in List(arg0,arg1,…) doing more pattern matching inside the function. Will be slow but hey…dynamic typing!

from evaluator

and and example function in StdLib

Conclusion

As clearly illustrated above, not planning your grammar results in constant changes in many places. So if you’re doing something serious just make the whole fricking grammar on a whiteboard beforehand. Seriously. 

Anyway..now I still only have a calculator, but a much more powerful one. I can write expressions like

e^piln(10+2)1+2*3/4^5-log(e)

But that’s nearly not enough. I want to be Touring-complete an ideally to be able to compile/interpret itself.

next: Hello World(strings, printing and interpreter)

Facebook Twitter Google Digg Reddit LinkedIn StumbleUpon Email
comments powered by Disqus