Skip to main content

Narex

Narex logo

License: MIT made-with-python

If you have ever used regular expressions, then you know how difficult they can be. Some people, when confronted with a problem, think “I know, I’ll use regular expressions.” Now they have two problems [1].

Challenges of using regular expressions:

  • Expressions easily become unreadable, as they are extremely dense.
  • No standardization or cross-engine compatibility. Depending on the engine, it can vary significantly. Supported features and syntax often differ.
  • Unnatural pattern memorization. Humans quickly forget the syntax, as it is not intuitive.
  • The learning curve is steep, especially for non-tech users. Even though many non-tech users need data processing, regular expressions remain out of reach for them.

Roadmap

The ultimate goal is to produce a DSL that uses natural language and enables cross-engine compatibility.

The main use case is for the user to define the desired engine (Perl, Python, etc.) and write a regular expression using natural language. The output will be raw regular expression, which can be directly used within the specified engine.

This DSL can be widely used by people from different backgrounds, as it uses natural language. Tricky regular expressions are abstracted, and a universal tool for cross-engine support is provided. Learning this DSL frees you from ever having to remember regular expression syntax again.

The biggest issues are the vast number of engines, subtle differences, and partially supported advanced features. Due to the complexity of implementing a DSL that handles advanced features and multiple engine engines, support will be added gradually. Currently, only Python engine is supported.

Quick intro

Before we start, consider that more examples can be found in examples directory, while the full rules specification with many small examples can be found in docs/rules_specification.

Match phone number

""" 
    MATCH: +381 62 123 4567
    MATCH: 062/123-4567
    MATCH: 062-123-4567
    MATCH: 0621234567
    MATCH: 062 123 4567
    SKIP:  062.123.4567
"""

carrier {
      digit repeat 2 times
}

state {
      '+'
      digit between 1 and 9
      digit repeat 2 to 3 times
}

no_state {
      '0'
}

separator {
      maybe either '/' or '-' or whitespace
}

local {
      digit repeat 3 times
      separator
      digit repeat 4 times
}

phone_number {
      starts
      either state or no_state
      separator
      carrier
      separator
      local
      ends
}

flags:
      global match,
      multiline

engine:
      python

tests:
      "+381 62 123 4567",
      "062/123-4567",
      "062-123-4567",
      "0621234567",
      "062 123 4567",
      "062.123.4567"

target:
      phone_number 

User defines sub-regexes within clauses. The better the clause naming is, the easier it is for anyone to understand the regex. Therefore, the clause is the main concept. Each clause can contain multiple sub-clauses, which must be defined first, and each clause must contain at least one rule. Understanding the rules is quite simple, as they are already known from regex. Besides clauses, the user can also test the regular expression by using tests, define desired flags with flags, and specify the desired engine using engine. The last required keyword is target which holds one of the defined clause references.

Generated code:

##############################################################
######################### Raw regex ########################## 
##############################################################
#
#  ^(\+[1-9]\d{2,3}|0)((\/|-|\s))?\d{2}((\/|-|\s))?\d{3}((\/|-|\s))?\d{4}$
#
##############################################################
########################### Engine ########################### 
##############################################################
#
#  Python
#
##############################################################
########################### Tests ############################ 
##############################################################
#
#  test 1:
#      pattern: 
#              +381 62 123 4567
#      match 1: 
#              +381 62 123 4567
#          group 1: 
#               ...
#
#  test 2:
#      pattern: 
#              062/123-4567
#      match 1: 
#              062/123-4567
#          group 1: 
#               ...
#
#  test 3:
#      pattern: 
#              062-123-4567
#      match 1: 
#              062-123-4567
#          group 1: 
#               ...
#
#  test 4:
#      pattern: 
#              0621234567
#      match 1: 
#              0621234567
#          group 1: 
#               ...
#
#  test 5:
#      pattern: 
#              062 123 4567
#      match 1: 
#              062 123 4567
#          group 1: 
#               ...
#
#  test 6:
#      pattern: 
#              062.123.4567
#      No matches
#
##############################################################
####################### Generated code ####################### 
##############################################################
import re

text = ""   # empty
regex = '^(\\+[1-9]\\d{2,3}|0)((\\/|-|\\s))?\\d{2}((\\/|-|\\s))?\\d{3}((\\/|-|\\s))?\\d{4}$'

match_strings = re.findall(
    regex, 
    text, 
    flags=re.MULTILINE
)
match_objects = re.finditer(
    regex, 
    text, 
    flags=re.MULTILINE
)

As we can see, the chosen engine is Python, hence we got generated code for Python. The generated code file has comments separated into sections. We have the raw regex output, which can be useful for easier debugging by comparing it with the written model. Then we have information about the chosen engine. Finally, we have concrete code which is specific to the engine and supported libraries. This output depends on the chosen flags.

Structure

Narex/
|
├── src/narex/
|         ├── validators/
|         ├── generators/
|         ├── grammar/
|         ├── utils/
|         ├── cli/
|
├── extension/
├── examples/
├── tests/
├── docs/
|
├── .github/workflows/
├── pyproject.toml
├── LICENSE
├── README.md

Getting started:

Prerequsities:

  • Python 3

Check pyproject.toml for more info.

NOTE: Don't activate the extension yet. If you already did, check VSCode extension section.

Regular user workflow

  1. Create a virtual environment:
python -m venv .venv
  1. Activate the virtual environment (Windows):
.\.venv\Scripts\activate 
  1. Install dependencies:
pip install git+https://github.com/Vasilijez/Narex.git
  1. Run VSCode from activated terminal:
code .

Pulling of the source code is optional.

If you are a contributor, check the developer workflow.

Using

You can use either of the two CLIs, Narex or textX. This is possible as Narex belongs to the textX ecosystem. They share logic, although the commands are slightly different.

Run the project:

i. You can optionally validate the model before running:

narex validate --path=<path>  # i.  Narex
textx check <path>            # ii. textX

ii. You can just run (includes validation):

narex run --path=<path> --cli-only        # i.  Narex    
textx generate <path> --target <engine>   # ii. textX

Flags

  1. Please use --help flag at the beginning to understand all possible flags for certain command within concrete CLI.
  2. --path and --output-path flags support both absolute and relative paths. For instance:
--path=C:\Users\...\model.nx
--path=./model.nx
  1. --cli-only flag provides only the raw regex within CLI. In contrast, when the flag is omitted, the full code is generated in a standalone file.
  2. --overwrite flag provides overwriting the file if already exists.
  3. --output-path flag is used for specifing the output directory path of the generated file.
  4. --engine (Narex) or --target (textX) flag provides an engine selection. Engine can be defined within model clause engine: as well. Engine defined by using parameter has higher priority than the engine defined by using the model.

One example with as many flags as possible:

narex run --path=input.nx --output-path=./dir --engine=python --overwrite     # i.  Narex
textx generate input.nx --target python --output-path=./dir --overwrite       # ii. textX

VSCode extension

Prerequisites:

  • Python VSCode extension (don't care now, it will be prompted if missing).

Before activating the extension, be sure to follow getting started either for regular user or for developer, as the extension requires all dependencies to be installed. If something goes wrong, check Troubleshooting.

Installation

  1. Navigate to the extension directory in order to find the narex-x.y.z.vsix extension file.
  2. Install the extension by choosing the Install from VSIX option.

alt text

Troubleshooting

Skip this section if the extension works fine for you. Continue if you still have headaches.

You must choose Python from one of the following:

  • i. Virtual environment from an already running VSCode instance.
  • ii. Global Python from an already running VSCode instance.
  • iii. Terminal with an activated virtual environment used to open VSCode (explained earlier).

Therefore, your setup must have all Narex dependencies installed in order for the extension to work properly. The main hurdle is buggy VSCode behavior. For instance, you may create a virtual environment and install all dependencies, but the extension still may not work. Activating the virtual environment can be done by command, but sometimes VSCode refuses to choose Python from the virtual environment, even if the virtual environment is activated in the terminal.

Try restarting the extension by sequentially clicking the Disable, Restart Extensions, and Enable button, then check the Python path selected by VSCode. The Python path will be explicitly shown each time you rerun the extension. If you don't see something like: Selected Python: c:\Users\John\Documents\GitHub\test\.venv\Scripts\python.exe then you definitely didn't activate the virtual environment inside VSCode (green (.venv) is not enough). You will very likely see the path to the global Python .exe, where you don't have the required dependencies installed.

The solution is to press CTRL + SHIFT + P, choose Select Interpreter: ..., and select python.exe from the .venv/Scripts directory.

Contributing

As this project is open source, everyone is welcome to contribute. If you have any suggestions, feel free to propose them by opening an issue. The most interesting ones can be analyzed and placed within the /docs directory. Like, Reverse engineering analysis.

Developer workflow (getting started)

  1. Clone the project:
git clone https://github.com/Vasilijez/Narex.git
  1. Change directory to Narex:
cd Narex
  1. Create and activate the virtual environment (Windows):
python -m venv .venv
.\.venv\Scripts\activate
  1. Install mandatory dependencies:
pip install -e .
  1. Optionally, if developer needs all dependencies (e.g. tests):
pip install -e ".[dev]"
  1. Run VSCode from activated terminal:
code .

VSCode extension

  1. If you want to play with the extension, open the extension subproject in VSCode and run the following command:
npm install
  1. Press the F5 key in Windows to start extension debugging.

  2. If you made some changes, don't forget to re-run the command from 1.

  3. Packaging is possible by running the following:

vsce package
  1. After packaging, the extension's .vsix file will be available.

Releasing

You can automatically trigger the release process by pushing a tag that starts with the letter v. For instance, v1.2.3.

  1. Navigate to the main branch:
git checkout main
  1. Make sure to pull the changes before tagging:
git pull
  1. Create a new tag:
git tag <tag-name>
  1. Push the tag to the remote repository:
git push origin <tag-name>

Static analysis

You can do it on your own.

Run the static analysis locally:

mypy --strict <file-name>

Caveat: Static analysis is triggered automatically by GitHub Actions. Therefore, it is smart to run a type checker from time to time before creating a pull request.

References:

[1] Source of the famous “Now you have two problems” quote (Author: Jeffrey Friedl, Accessed: July 19, 2025)

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

narex-1.0.1.tar.gz (20.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

narex-1.0.1-py3-none-any.whl (19.2 kB view details)

Uploaded Python 3

File details

Details for the file narex-1.0.1.tar.gz.

File metadata

  • Download URL: narex-1.0.1.tar.gz
  • Upload date:
  • Size: 20.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for narex-1.0.1.tar.gz
Algorithm Hash digest
SHA256 198305b210dbcac4956e9a29d837ba944e6e81ee8ff2ecdfe54882281054f42a
MD5 fae02874b344d7f24c081412efa30371
BLAKE2b-256 54df769417d9ea5442f4b0878aa2d49739c6e858289650663306d7a9f522d4c0

See more details on using hashes here.

Provenance

The following attestation bundles were made for narex-1.0.1.tar.gz:

Publisher: deploy_to_pypi.yml on Vasilijez/Narex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file narex-1.0.1-py3-none-any.whl.

File metadata

  • Download URL: narex-1.0.1-py3-none-any.whl
  • Upload date:
  • Size: 19.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for narex-1.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 19dcae9de4d5730f1f6b40c0e2cc6db97a39572811bff4bedf62805cd80e82ec
MD5 d010be303d2965d6e6d2736d0a0d2f5f
BLAKE2b-256 f5ea7d58e18cb4c9f776a012ae49f7b7ed40301ea9dd487518ecf041063ab18a

See more details on using hashes here.

Provenance

The following attestation bundles were made for narex-1.0.1-py3-none-any.whl:

Publisher: deploy_to_pypi.yml on Vasilijez/Narex

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

1.0.2

2 files

This release

1.0.1 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page