RAMEL

Introduction

RAMEL is a programming language written using Lex, Yacc, and C by yours truly with (a lot of) guidence from Dan Tappan in the CS Department at ISU. This is probably the most difficult program I’ve ever written. It runs on a Java virtual program. RAMEL is more or less useless, but it did help clear up how a compiler can actually work.

Syntax – Lex

Lex is a tool for parsing regular expressions. RAMEL is similar to C, so it is parsed similarly. The syntax of Lex is fairly straightforward, but it helps to look over the documentation. Regular expressions are a subset of context free languages which can be generated using YACC.

Some things, such as strings, are passed modified using some code (such as stripping off the quotes).

Here is a link to the ramel.lex.

It was compiled using flex and generated lex.yy.c which was compiled using gcc.

References:

Semantics – Yacc and C

The Yacc was a bit more complicated than the Lex. It takes care of the semantics of declaring variables, algebra operations, symbol tables, etc. It also keeps track of all sorts of rules like a string cannot be added to an integer.

Here are links to the source code:

ramel.yacc
symbolTable.h
symbolTable.cpp
semantics.h

This was compiled using Bison and gcc.

References:

Target Code Generation

The code generation involves several passes through (more than necessary, some of the steps could be condensed). This generates code that is closer to the machine. Below is the source code:

targetCodeGenerator.h
targetCodeGenerator.cpp

In this case, our machine is just a virtual machine, but it would still be similar if there were actual hardware.

Virtual Machine

The virtual computer takes the generated code (generated by the target code generator) as a text file (cs451.txt) and produces an executable.  Below is the source code:

execute.java

This is written and compiled in Java.

Example Run

Take the example RAMEL code. Again, the syntax is similar to C it should be readable.

{
int x;
x = 17;
if((x > 17))
{
write(x);
}
}

Now use the target code generator. It outputs all x passes to the screen. The final pass generates the necessary code for the virtual machine.

0000 LDVR 5 17
0004 LDRA 500 5
0008 LDAR 2 500
0012 LDVR 3 17
0016 CGT 4 2 3
0020 JMPF 10 4
0024 LDAR 6 500
0028 OUTI 6
0030 NOP
0031 HALT

This code is saved in the same directory as cs481.rml and Execute.java.

java
Execute
More Example RAMEL Programs

The below program demonstrates a conditional written in RAMEL. Note the write function just utilizes the java output.

{
int x;
x = 17;
if((x > 17))
{
write(x);
}
else
{
x = (x + 1);
}
}

The program below demonstrates a loop in RAMEL

{
int x;
x = 0;
while((x < 100))
{
if((x > 17))
{
break;
}
else
{
x = (x + 1);
write(x);
}
x = (x*2);
}
}

If I ever receive any feedback on this I’ll give more examples

Analysis

The reasons RAMEL is not practical – just to name a few:

  • It is extremely slow. It relies on something like 13 passes to generate target code. It basically goes through all this trouble just to write java code that is interpreted and realistically has to be interpreted down to your machine from there.
  • It does nothing new. There is nothing RAMEL gives that has not already been done – much better.
  • The code seems a little buggy. Although it seems to work ok on my laptop, it had an error running on the school’s machines. This bug was fixed. However, RAMEL has never really been tested, so if it were ever to be really used (which it probably never should be other than for educational purposes) some debugging may be necessary.
  • No one uses it so it doesn’t have any libraries – so even the most trivial tasks can be difficult.

Despite these disadvantages, there are, believe it or not, advantages. At least I think there are:

  • RAMEL is extremely simple as far as compilers go. Compilers are complicated devices, and this lets the observer see how one could realistically work.
  • RAMEL is easy to read due to simplicity, so it should be fairly familiar.


Matching Regular Expressions that don’t end with…

Regular expressions do not mix well with syntax that requires memory, such as XML. I was trying to add a <br /> tag to every line that did not have a </p> tag. so for example I can print the strings I want with grep -v ‘^.*</P>’

Anyway, this turns out to be a bear, because (?!expression) just isn’t working for me with sed, although I think google says it should.

So what do I do? I make two!

s/(w.*</p>)/1<br />/g

adds a <br /> to every line with a word.

s/(.*</p>)<br />/1/g

take off the <br /> for lines that have a </p>

The good thing about this is it should work with all standard regular expressions, unlike that look ahead stuff which may only work with certain utilities.

You could run this with sed, vim, perl, python, whatever, and it will work.