Skip to content

Commit

Permalink
Added documentation in a series of README.md files.
Browse files Browse the repository at this point in the history
  • Loading branch information
rkanagy committed Jan 11, 2022
1 parent 3ebdd09 commit 681ec3c
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 0 deletions.
77 changes: 77 additions & 0 deletions BasicEvaluatorInterpreter/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# Basic Evaluator Interpreter source code

The grammar for the programming language being implemented is in the file
[BasicEvaluator.g4](BasicEvaluator.g4).

After any changes to the grammar file, the lexer and parser code needs to be
rebuilt using the following command in Linux:

```
antlr4 -no-listener -visitor -Dlanguage=CSharp BasicEvaluator.g4
```

The command antlr4 is an alias in Linux set to:
```
java -jar /usr/local/lib/antlr-4.9.3-complete.jar
```

The antlr4 command will rebuild the Lexer and Parser,
consisting of the following files:
- [BasicEvaluator.interp](BasicEvaluator.interp)
- [BasicEvaluator.tokens](BasicEvaluator.tokens)
- [BasicEvaluatorBaseVisitor.cs](BasicEvaluatorBaseVisitor.cs)
- [BasicEvaluatorLexer.cs](BasicEvaluatorLexer.cs)
- [BasicEvaluatorLexer.interp](BasicEvaluatorLexer.interp)
- [BasicEvaluatorLexer.tokens](BasicEvaluatorLexer.tokens)
- [BasicEvaluatorParser.cs](BasicEvaluatorParser.cs)
- [BasicEvaluatorVisitor.cs](BasicEvaluatorVisitor.cs)

The following files were created to implement the Interpreter:
- [BasicEvaluatorVisitorImpl.cs](BasicEvaluatorVisitorImpl.cs) - the
implementation of the visitor which implements the main part of the Interpreter. The class inherits from the auto-generated generic BasicEvaluatorBaseVisitor class.
- [BasicEvaluatorInfo.cs](BasicEvaluatorInfo.cs) - the class of the object that
is returned from each visitor function, consisting of either the name of the
function definition or the value of the expression being evaluated
- [Memory.cs](Memory.cs) - contains the collections of variable values for
both the global and local environments (as a stack), as well as the function
definitions
- [ValueEnvironment.cs](ValueEnvironment.cs) - the class containing the Map of
variable names to values for a single environment
- [FunctionDefinition.cs](FunctionDefinition.cs) - the class containing a
function definition
- [Value.cs](Value.cs) - the class containing a value (an Integer)
- [Parser.cs](Parser.cs) - the entry-point into the parser and interpreter, providing the functions parseDefinition method, which returns the function definition name, and the parseExpression method, which returns the evaluated value of the expression.

The BasicEvaluator programming language consists of values and function
definitions. It only supports one type of value and that is an Integer. Variables
are stored in the global environment. Variable names can contain any character
except spaces, open and close parentheses, a semicolon, or tabs, carriage returns,
or line feeds. Parentheses are used to delimit expressions and function
expressions, much like it does in the family of programming languages based on LISP.
Semicolons are used to start a comment which goes to the end of the current line.
When a function is called, the actual arguments passed to the function are
evaluated to a value, and then the formal arguments of the function are set to
these actual argument values inside a local environment for that function. The
**visitFunctionExpr** method in the [BasicEvaluatorVisitorImpl.java](BasicEvaluatorVisitorImpl.java)
file shows this logic, which is the only complicated part of the Interpreter.
All other visitor functions used to implement the Interpreter are pretty
straightforward. The use of a stack for the local environments fully support
recursive function calls. The last function definition in the [test01.lp](test01.lp)
file is a recursive function definition for the Greatest Common Divisor
algorithm (gcd).

### TODO
1. Better handling of parser errors
2. Add a **read** function to the language that reads input from the prompt
3. Add a **for** loop operation to the language
4. Experiment with passing values by reference during function calls, instead
of by value, as it currently does.
5. Add a **load** function to the REPL that loads a file to be evaluated
6. Add local variables to functions
7. Add real numbers to the language
8. Implement static type-checking to the language as well as type-checking to
distinguish between *statements* and *expressions* and between *procedures*
and *functions*
9. Updates to the REPL: a) history of commands and use of up/down arrow keys to
go through history, b) auto-indent, c) better editing capabilities for multi-
line command entry to edit lines above or below current line in command.
25 changes: 25 additions & 0 deletions BasicEvaluatorRepl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Basic Evaluator Read-Eval-Print Loop source code

The function main is located in the file [BasicEvaluatorRepl.cs](BasicEvaluatorRepl.cs).
This file contains the main Read-Eval-Print Loop which gets input from the user,
that consists of a set of lines containing one expression or function definition.
The expressions or function definitions entered by the user are then parsed and
evaluated. See the methods named **parseDefinition**, **parseExpression**, in the Parser.cs file in the BasicEvaluatorInterpreter project to see how to use ANTLR to parse this language from the
string entered by the user at the REPL prompt.

Expressions are evaluated to a single Integer value and displayed as
output. Function definitions are parsed and then added to a list of function
definitions available to subsequent expressions entered, and its name is displayed
as output.

To run the evaluator from the Rider terminal, run the following command from
the **bin/Debug/net6.0** folder, after building the project from
within the IDE:
```
./BasicEvaluator
```

This will then display a prompt for the user to enter a function definition or
an expression to be evaluated. The file [test01.lp](test01.lp) contains a set
of expressions and function definitions that can be entered at the prompt to
test the Interpreter.
33 changes: 33 additions & 0 deletions BasicEvaluatorRepl/test01.lp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
3
(+ 4 7)
(set x 4)
(+ x x)
(print x)
(set y 5)
(begin (print x) (print y) (* x y))
(if (> y 0) 5 10)
(while (> y 0) (begin (set x (+ x x)) (set y (- y 1))))
x
(define +1 (x) (+ x 1))
(+1 4)
(define double (x) (+ x x))
(double 4)
x
(define setx (x y) (begin (set x (+ x y)) x))
(setx x 1)
x
(define not (boolval) (if boolval 0 1))
(define <> (x y) (not (= x y)))
(define mod (m n) (- m (* n (/ m n))))
(define gcd (m n)
(begin
(set r (mod m n))
(while (<> r 0)
(begin
(set m n)
(set n r)
(set r (mod m n))))
n))
(gcd 6 15)
(define gcd (m n)
(if (= n 0) m (gcd n (mod m n))))
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Basic Evaluator

This project is a rewrite, using C# and ANTLR, of the **Basic Evaluator**
presented in Chapter 1 of the book **Programming Languages: An Interpreter-Based
Approach (PLAIBA)**, by Samuel N. Kamin, originally written in ISO Pascal.

The following tools were used in the implementation:
- JetBrains Rider 2021.3.2
- .NET Core 6
- ANTLR 4.9.3
- Antlr4.Runtime.Standard 4.9.3 NuGet package
- Ubuntu Linux 21.10

The project was configured using the following libraries:
- .NET Core 6
- Antlr4.Runtime.Standard 4.9.3 NuGet package

The source code and grammar for the parser and interpreter is located in the
**BasicEvaluatorInterpreter** project folder. When the project is compiled from Rider,
the output assemblies are located in the **bin/Debug/net6.0** folder of the BasicEvaluatorRepl
project.

0 comments on commit 681ec3c

Please sign in to comment.