Skip to content

A parser generator with a clean syntax. Transpiles to ANTLR4 grammar.

License

Notifications You must be signed in to change notification settings

johnryanmal/ctx2l

Repository files navigation

ctx2l

ctx2l (pronounced "contextual") is a parser generator intended for use in small projects and prototypes.

ctx2l is an abstraction on top of ANTLR. Its purpose is bind together parsing and evaluating in source code, so that both aspects can be written at the same time.

Rather than generating code directly, ctx2l is translated into a language agnostic ANTLR grammar and a language specific ANTLR visitor. The grammar is then compiled by ANTLR into code that works with the visitor. Because the parser generation is handled entirely by ANTLR, it may be more accurate to call ctx2l a "visitor generator."

Additionally, the name has another meaning: ctx2l can be read as "Context To Language." It is the intermediary step between parsing context and a target language.

Installation

Currently, only python as a target language is supported.

Python

  1. Install ANTLR4
pip install antlr4-python3-runtime
pip install antlr4-tools
  1. Clone the repository
git clone https://github.com/johnryanmal/ctx2l ~/ctx2l
  1. Update rc file

.zshrc

echo 'alias ctx2l="python ~/ctx2l/python/main.py"' >> ~/.zshrc

After restarting your shell, you should be able to use the ctx2l command.

Usage

Command Line

ctx2l <file> [<dir>]

Generates a lexer, parser, and visitor from a .ctx2l source file.

Option Description
file The .ctx2l file to generate from.
dir The directory where all output is generated.

Source

At minimum, three things are needed to generate a working program.

  • A ctx2l file (grammar)
  • An evaluator file (functionality)
  • An input (text)

Example (source)

calculator.ctx2l

expr:
| V=sum -> V

sum:
| V=prod -> V
| L=prod '+' R=sum -> $add(L, R)
| L=prod '-' R=sum -> $sub(L, R)

prod:
| V=pow -> V
| L=pow '*' R=prod -> $mul(L, R)
| L=pow '/' R=prod -> $div(L, R)

pow:
| V=value -> V
| L=value '**' R=pow -> $pow(L, R)

value:
| '(' V=expr ')' -> V
| V=DIGITS -> $num(V)

DIGITS:
| [0-9]+

WS >> skip:
| [ \t\r\n\f]+

calculatorEvaluator.py

from calculatorVisitorEvaluator import calculatorVisitorEvaluator

class calculatorEvaluator(calculatorVisitorEvaluator):
    def add(self, x, y):
        return x + y

    def sub(self, x, y):
        return x - y

    def mul(self, x, y):
        return x * y

    def div(self, x, y):
        return x / y

    def pow(self, x, y):
        return x ** y

    def num(self, str):
        return int(str)

sample.txt

14 / (2 + 5) - 7 * 3

With these three files in a single directory, a single command generates the needed files to make this work:

ctx2l calculator.ctx2l

The generated main.py file can be run like so:

python main.py sample.txt

And the correct output is given:

$ ctx2l calculator.ctx2l
$ python main.py sample.txt
-19.0

If you want to read from stdin instead, running main.py without any arguments will open up a simple repl:

$ python main.py
> 1 + 1
2
> 2 * 3
6
> text
    text
    ^
SyntaxError: token recognition error at: 't'

Executable

If you wish, you can make the script executable:

$ chmod +x main.py
$ ./main.py sample.txt
-19.0
$ ./main.py
> 1 + 1
2

And symlink it for your own use:

$ sudo ln -s "$PWD/main.py" /usr/local/bin/calculator
$ calculator sample.txt
-19.0
$ calculator
> 2 + 2
4

But if you're a little more ambitious, you can use a tool like PyInstaller and make an executable you can distribute to other people as well!

Updating

  1. Pull from the repository
git -C ~/ctx2l pull origin main

Uninstallation

Python

  1. Update rc file

.zshrc

grep -v 'alias ctx2l="python ~/ctx2l/python/main.py"' ~/.zshrc > /tmp/.zshrc
mv -f /tmp/.zshrc ~/.zshrc
  1. Remove the repository
rm -rf ~/ctx2l

About

A parser generator with a clean syntax. Transpiles to ANTLR4 grammar.

Topics

Resources

License

Stars

Watchers

Forks