dayton-outar / smpl

SMPL is a small, but expressive math programming language.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool


a simple math programming language

SMPL

SMPL is a small, but expressive math programming language.

I was introduced to Compiler Design by Prof. Daniel Coore in my final year while doing Undergraduate studies for Computer Science and Electronics degree at the University of the West Indies, Mona. It's the most memorable project that I have had while studying at the university. Herein is an updated version of building that project. I have made a few modification to the original specification provided by Prof. Coore and the result of the modifications are found here.

Prof. Coore mentioned that his initial specification was inspired by Scheme. Scheme is inspired by Lisp. Some of the modifications are inspired by JavaScript. The plan is to maintain the language as loosely typed language.

This compiler project is built on the Java platform and uses JFlex and CUP tools. While conducting researching and developing the project, I was fascinated by other compiler design tools such as the Lex & Yacc tools (or, better yet, Flex & Bison+). Apparently JFlex and CUP was modeled off flex and bison (formerly lex and yacc) that is, in my opinion, far more superior than any other tool in this genre simply because of the language used: C. With C, you can build more native machine applications rather than depending on a virtual machine or language runtime environment.

ANTLR [+] also caught my attention. It's main selling point seems to be that it can be used in many of the popular programming languages. Nonetheless, for the experienced programmer, this isn't enough to influence a decision to use it.

Requirements

Java CUP

Apache Ant

Installation

Download your preferred version of smpl-coore-outar-x-x-x.jar file in the releases section. Transfer that file into your lib folder from which your Java compiler will read and understand.

For Java Projects created in VS Code such as this, you can transfer the file into the lib folder found at the root of the project.

When compiling in the terminal, reference must be made to this jar file and the java-cup-11b.jar file in the javac command. For example,

javac -cp lib/smpl-coore-outar-1.0.1.jar src/App.java

You will also need to make reference to these dependecies To run the generated class file as follows,

java -cp lib/smpl-coore-outar-1.0.1.jar src/App

N.B. For version 1.0.0, reference must be made to the java-cup-11b.jar file. Since version 1.0.1, the java-cup-11b.jar file has been bundled into smpl-coore-outar-x.x.x.jar file.

Usage

SMPL can be used through an interactive shell or by passing a folder path or a set of file paths to the App class. All the class and function definitions can be accessed from the SMPL (smpl-coore-outar-x-x-x.jar) library.

Getting Started

Once you have completed installation of SMPL (smpl-coore-outar-x-x-x.jar) library, you can try the snippet of Java code shown below,

import java.io.InputStream;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.io.ByteArrayInputStream;
import java.util.Hashtable;

import java_cup.runtime.Symbol;
import smpl.lang.SMPLLexer;
import smpl.lang.SMPLParser;
import smpl.sys.Program;
import smpl.sys.values.IValue;

public class App {
    public static void main(String[] args) throws Exception {
        System.out.println("Hello, World! Trying out SMPL");

        Hashtable<String, IValue> heap = new Hashtable<String, IValue>();
        
        String myExpression = "v = 8; :> v * 4;"; // Output: 32

        InputStream in = new ByteArrayInputStream(myExpression.getBytes(StandardCharsets.UTF_8));
        SMPLLexer lexer = new SMPLLexer( new InputStreamReader(in) );
        SMPLParser p = new SMPLParser(lexer);
        
        Symbol parseResult = p.parse();
        
        Program program = (Program)parseResult.value;
        program.execute( heap );
    }
}

Now, once this works well for you, you can begin tinkering with SMPL by trying out the examples listed and documented here.

A few examples of using SMPL syntax can be seen in the snippet below, which was extracted from examples,

fact = (:n) { (n <= 1) ? 1 : n * fact( n - 1 ); }

// To get a better approximation for cos(r), you need more terms in your Taylor polynomial.
sin = (:n) {
    r = ( n / 180.0 ) * π;
    v = r - ( (r**3)/fact(3) ) + ( (r**5)/fact(5) ) - ( (r**7)/fact(7) ) + ( (r**9)/fact(9) ) - ( (r**11)/fact(11) );
    v;
}

cos = (:n) {
    r = ( n / 180.0 ) * π;
    v = 1 - ( (r**2)/fact(2) ) + ( (r**4)/fact(4) ) - ( (r**6)/fact(6) ) + ( (r**8)/fact(8) ) - ( (r**10)/fact(10) );
    v;
}

tan = (:n) {
    t = sin(n) ÷ √( 1 - sin(n)**2 );
    t;
}

:> "Sine of 30 degrees is ${ sin(30) }\n";

:> "Cosine of 30 degrees is ${ cos(30) }\n";

:> "Tangent of 30 degrees is ${ tan(30) }\n";

Yet another snippet extracted from examples can be seen below.

:> "Step by 1\n";
(i = 1; i <= 9; i++) {
    :> i * (3 + i);:> "\n";
}

:> "Step by 2\n";
(i = 1; i < 9; i+=2) {
    :> i * (3 + i);:> "\n";
}

q = 5;
(; q > 1; q--) {
    :> "Rebel ${q}";
    :> "\n";
}

q = 3;
(; q > 1;) {
    :> "Boom ... ${q}";
    :> "\n";

    q--;
}

/*
(;;) {
    :> "Ooh lala"; :> "\n";
}
*/

To use the SMPL interactive shell, you must perform the following command (assuming that the dependencies are in a lib folder within the folder that you are running the command),

java -cp lib/smpl-coore-outar-1.0.1.jar App

You can exit the interactive shell by entering exitor quit and then press ENTER.

To read a folder containing text files with extension .smpl, perform the following command (assuming examples is the path of folder within the folder that you are running the command),

java -cp lib/smpl-coore-outar-1.0.1.jar App examples

To read a file containing SMPL syntax (no strict filtering done for file path arguments), perform the following command,

java -cp lib/smpl-coore-outar-1.0.1.jar App myplayground.smpl

For multiple files,

java -cp lib/smpl-coore-outar-1.0.1.jar App identifiers.smpl hypotenuse.smpl

Contributing

Contributions are welcomed to this project. It is expected that you make a fork of this repo, make the changes that you request and then create a pull request, where your changes can be reviewed for merging into the main branch.

It is expected that prospective contributors acquaint themselves with an understanding of the code convention, the application's architecture and the way how this software works before contributing via pull request. There should be enough documentation in this repo through README files that can inform the prospective contributor.

Folder Structure

The workspace contains several folders, where:

  • src: all source code
    • smpl: core functions for the SMPL interpreter
    • tests: contains SMPL JUnit tests
  • examples: contains several documented examples and snippets of SMPL syntax in .smpl text files
  • lib: maintains dependencies
  • bin: contains generated class files from compilation
  • docs: contains generated HTML and XML files from javadoc and junitreport
  • .attachments: contains media for README documentation
  • .vscode: VS Code configuration
  • .github: GitHub Actions CI workflow

The JAVA DEPENDENCIES view allows you to manage your dependencies. More details can be found here.

The Lexer

JFlex is found in the Aptitude package repository and can be downloaded for use on Ubuntu/Debian machines by performing the following command,

sudo apt install jflex

If making changes to the lexer to add or modify a new token, the Java file can be generated by navigating to the src folder and performing the following command,

jflex src/smpl/lang/SMPLLexer.flex -d src/smpl/lang

Details of using JFlex can be found here.

Details for using the CLI are accessible by performing the following,

jflex --help

The Parser

If changes are required to the grammar, the contributor can look at the .cup file, acquaint themself with the LALR CUP language found here and perform the following command to generate the new Parser,

java -jar lib/java-cup-11b.jar -interface -destdir src/smpl/lang -parser SMPLParser src/smpl/lang/SMPLParser.cup

Details for using the CLI are accessible by performing the following,

java -jar lib/java-cup-11b.jar -help

Compiling the Project

The Ant build tool is used to automate a number of possibilities. The build.xml is configured to:

  • Generate the lexer
  • Generate the parser
  • Compile the core source code
  • Generate a new smpl-coore-outar-x-x-x.jar file
  • Generate updated HTML documentation
  • Perform unit tests
  • Generate unit tests reports
  • Perform SMPL examples

Before we can use ant, ensure that it is installed by performing the following,

ant --version

If it is not installed, you can install ant on Ubuntu/Debian machine by performing the following,

sudo apt-get install ant

In order to perform all the possibilities, perform the following in the root folder that contains build.xml,

ant

For just compiling the project, perform the following,

ant compile

To generate the class library, smpl-coore-outar-x-x-x.jar, perform the following,

ant build-lib

For performing the unit tests, perform the following,

ant test

To remove the generated bin and docs folder, perform the following,

ant clean

Miscelaneous Notes

Run JUnit tests 😓 🧪

java -jar lib/junit-platform-console-standalone-1.8.0.jar -cp bin --include-engine=junit-jupiter --scan-classpath

Further Reading

  1. Compilers: Principles, Techniques and Tools by Alfred V. Aho, Ravi Sethi and Jeffrey D. Ullman
  2. Compiler Design in C by Allen I. Hobub
  3. flex & bison by John Levine
  4. Implementing String Interpolation in Flex & Bison - StackOverflow
  5. Ant: The Definitive Guide by Steve Holzner
  6. Building and testing Java with Ant

Video Tutorial References

  1. How to use the GitHub Package Registry
  2. How to use Github Packages with Maven Java Project
  3. 25 VS Code Productivity Tips and Speed Hacks

About

SMPL is a small, but expressive math programming language.

License:GNU General Public License v3.0


Languages

Language:Java 97.5%Language:Lex 2.5%