Skip to content

Repository files navigation

Let

linuxmacoswindows

A simple demo language that builds upon FE.

Usage

USAGE:
let [-?|-h|--help] [-v|--version] [-d|--dump] [-e|--eval] [<file>]
Display usage information.
OPTIONS, ARGUMENTS:
-?, -h, --help
-v, --version Display version info and exit.
-d, --dump Dumps the let program again.
-e, --eval Evaluate the let program.
<file> Input file.
Use "-" as <file> to output to stdout.

Building

If you have a GitHub account setup with SSH, just do this:

git clone --recurse-submodules git@github.com:leissa/let.git

Otherwise, clone via HTTPS:

git clone --recurse-submodules https://github.com/leissa/let.git

Then, build with:

cdlet
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build -j $(nproc)

For a Release build simply use -DCMAKE_BUILD_TYPE=Release.

Invoke the interpreter like so:

./build/bin/let test/test.let -e

Grammar

p=s ... sEOF (*program*)
;
s=';' (*emptystatement*)
|'let'ID'='e';' (*letstatement*)
|'print'e';' (*printstatement*)
;
e=LIT (*literalexpression*)
|ID (*identifierexpression*)
|'('e')' (*parenthesizedexpression*)
|OP1e (*unaryexpression*)
|eOP2e (*binaryexpression*)
;

where

  • LIT = [0-9]+
  • ID = [a-zA-Z][a-zA-Z0-9]*
  • OP1 is one of: +, -
  • OP2 is one of: *, +, -, /

In addition, Let supports

  • /* C-style */ and
  • // C++-sytle comments.

For the sake of the demo, Let is case-insensitive: the lexer folds every identifier and keyword to lower case (so Foo, FOO, and foo denote the same name, and LET/Print are recognized as keywords). This deliberately exercises FE's case-normalizing lexer path (fe::Lexer::accept<Append::Lower>).

Precedence

Ambiguities in the expression productions are resolved according to the operator precedence that is summarized in the following table (strongest binding first):

OperatorDescription
+e, -eunary plus, unary minus
*, /multiplication, division
+, -addition, subtraction

All binary operators are left associative.

Semantics

All calculations use 64-bit unsigned integer wrap-around arithmetic. Division by zero yields zero. Reading an identifier that was never bound by a let statement is not an error: it evaluates to zero (the name is implicitly bound to 0 on first use).

About

A simple demo language that builds upon FE.

Resources

Stars

8 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages