Skip to main content

IEC 61131-3 Structured Text grammar for tree-sitter (standard, dialect-extensible)

Project description

tree-sitter-iec61131-3-st

ci release npm crates.io PyPI license tree-sitter IEC 61131-3

A tree-sitter grammar for IEC 61131-3 Structured Text (ST) — the standard programming language for industrial PLCs. Standard-compliant first; vendor dialects (Beckhoff TwinCAT, Codesys, B&R Automation Studio, Siemens TIA, Rockwell) are deferred to separate dialect grammars that extend this base.

About the name — IEC 61131 is the umbrella PLC-programming standard. Part 3 (IEC 61131-3) defines the programming languages: ST (Structured Text), LD (Ladder Diagram), FBD (Function Block Diagram), IL (Instruction List, deprecated), and SFC (Sequential Function Chart). This repo covers ST only — the -3-st suffix encodes both: Part 3 of the standard, ST language specifically.

tree-sitter-iec61131-3-st demo — playground showing the parse tree for a state machine

Features

  • IEC 61131-3 (3rd edition, 2013) Structured Text — POUs, all VAR blocks, every elementary / derived / generic type, every operator with correct precedence, every statement, full OOP (METHOD / PROPERTY / EXTENDS / IMPLEMENTS / INTERFACE), namespaces, configuration / resource / task.
  • Case-insensitive keywords (IF, if, If all parse as the same keyword) implemented at the lexer level.
  • Error-tolerant: produces a useful tree even on partial or broken input — usable in editors during typing.
  • Dialect-extensible: the base grammar exposes named hidden rules (_declaration, _statement, _expression, _type_specifier, _var_block) so dialect grammars can add vendor-specific constructs via grammar(base, {…}) without forking. See EXTENDING.md.
  • Editor-ready queries: highlights.scm, locals.scm, tags.scm, folds.scm, indents.scm, injections.scm. Standard tree-sitter capture vocabulary.
  • Bindings for Node, Rust, Python, Go.

Quick demo

FUNCTION_BLOCK PID
VAR_INPUT
    setpoint, process_var : REAL;
    Kp, Ki, Kd            : REAL;
END_VAR
VAR_OUTPUT
    output : REAL;
END_VAR
VAR
    error, prev_error, integral : REAL;
END_VAR

error := setpoint - process_var;
integral := integral + error;
output := Kp * error + Ki * integral + Kd * (error - prev_error);
prev_error := error;
END_FUNCTION_BLOCK

Parsing this with tree-sitter parse produces a clean tree with function_block_declarationvar_input / var_output / var_block → assignments with binary_expression operands at the right precedence.

Install

Node

npm install tree-sitter tree-sitter-iec61131-3-st

Rust

# Cargo.toml
[dependencies]
tree-sitter = "0.25"
tree-sitter-iec61131-3-st = "0.0"

Python

pip install tree-sitter tree-sitter-iec61131-3-st
import tree_sitter, tree_sitter_iec61131_3_st
language = tree_sitter.Language(tree_sitter_iec61131_3_st.language())
parser = tree_sitter.Parser(language)
tree = parser.parse(b"PROGRAM Hello END_PROGRAM")

Go

import (
    sitter "github.com/tree-sitter/go-tree-sitter"
    iec61131_3_st "github.com/HeytalePazguato/tree-sitter-iec61131-3-st/bindings/go"
)

Editor setup

Neovim with nvim-treesitter

require('nvim-treesitter.configs').setup {
  ensure_installed = { 'iec61131_3_st' },   -- once published; pre-publish, install from local path
  highlight = { enable = true },
  indent    = { enable = true },
  fold      = { enable = true },
}

For a local development install before the parser is on the npm/CDN registry, add to your init.lua:

local parser_config = require'nvim-treesitter.parsers'.get_parser_configs()
parser_config.iec61131_3_st = {
  install_info = {
    url = 'https://github.com/HeytalePazguato/tree-sitter-iec61131-3-st',
    files = { 'src/parser.c' },
    branch = 'main',
  },
  filetype = 'st',
}

Helix

languages.toml:

[[language]]
name = "iec61131-3-st"
scope = "source.iec61131-3.st"
file-types = ["st", "iecst"]
roots = []
comment-token = "//"
indent = { tab-width = 4, unit = "    " }

[[grammar]]
name = "iec61131_3_st"
source = { git = "https://github.com/HeytalePazguato/tree-sitter-iec61131-3-st", rev = "main" }

Zed

Zed picks up tree-sitter grammars from extensions; see Zed's docs for the current recommended packaging path.

VSCode

VSCode does not natively use tree-sitter for grammar parsing — its highlighting comes from TextMate grammars and its semantic tokens come from language servers. A future companion repo will provide a VSCode extension that loads this grammar via the vscode-tree-sitter integration.

What's covered, what's not

Implemented in v0.0.1:

  • POU declarations: PROGRAM, FUNCTION (with return type), FUNCTION_BLOCK, INTERFACE, TYPE, NAMESPACE, CONFIGURATION, RESOURCE.
  • All VAR_* block kinds with CONSTANT / RETAIN / NON_RETAIN qualifiers, AT %{I,Q,M}{X,B,W,D,L} direct addresses, initial values.
  • All elementary types, generic ANY_* types, STRING(N) / WSTRING(N), ARRAY [a..b, …] OF, structures, enumerations, subranges, POINTER TO, REF_TO.
  • All literals: integers (plain, 2#…, 8#…, 16#…, with _ separators), reals with exponent, strings with $ escapes, T#…, D#…, TOD#…, DT#…, typed-prefixed (INT#42, REAL#3.14, etc).
  • All statements: assignment (:=), reference assignment (REF=), function/method calls with positional and named (:= / =>) arguments, IF/ELSIF/ELSE/END_IF, CASE with single, list, range values + ELSE, FOR … TO … BY … DO … END_FOR, WHILE, REPEAT, EXIT, CONTINUE, RETURN.
  • All operators with IEC 61131-3 §6.6.5 precedence: parentheses, calls, indexing […,…], member access, dereference ^, ADR(), unary - / + / NOT, right-associative **, * / / / MOD, + / -, comparisons, equality, AND / &, XOR, OR.
  • OOP (3rd edition): METHOD / END_METHOD, PROPERTY with GET / SET accessor bodies, EXTENDS, IMPLEMENTS, INTERFACE, ABSTRACT / FINAL / OVERRIDE, PUBLIC / PRIVATE / PROTECTED / INTERNAL, THIS / SUPER.
  • Comments ((* … *), //) and pragmas ({ … }, opaque body).

Out of scope for v0.0.1:

  • Vendor dialect extensions (TwinCAT __VERSION, Codesys structured pragmas, B&R ACTION, etc.) — those will live in dialect repos that extend this grammar.
  • Other IEC 61131-3 languages — Ladder Diagram, Function Block Diagram, Instruction List, Sequential Function Chart.
  • Type checking, symbol resolution, code generation, formatting — this is a parser, not a compiler.

Performance

The CI benchmark parses a synthetic ~10 000-line ST file (200× the combined PID + conveyor + state-machine examples) and fails the build if the parse exceeds 200 ms on a ubuntu-latest runner. Typical run is well under that.

Development

# Install tree-sitter-cli and a C compiler.
npm install -g tree-sitter-cli

# Generate the parser (writes src/parser.c).
tree-sitter generate

# Run the corpus.
tree-sitter test

# Parse a single file.
tree-sitter parse examples/blink.st

See the project's BLUEPRINT.md for branch / release conventions: develop → release/<version> → main, semver from a single VERSION file.

Roadmap

Future repos that will extend this base grammar:

  • tree-sitter-iec61131-3-st-twincat — Beckhoff TwinCAT 3 (TwinCAT-specific pragmas, S= / R= set/reset, OR_ELSE / AND_THEN short-circuit operators, conditional compilation, ACTION blocks).
  • tree-sitter-iec61131-3-st-codesys — Codesys 3 (attribute pragmas with structured contents, action / transition blocks).
  • tree-sitter-iec61131-3-st-br — B&R Automation Studio (ACTION, task-specific extensions).
  • tree-sitter-iec61131-3-st-siemens — Siemens TIA Portal SCL.
  • tree-sitter-iec61131-3-st-rockwell — Rockwell Studio 5000 ST.

Pull requests welcome — see CONTRIBUTING.md and EXTENDING.md.

Acknowledgments

Patterns, organization, and corpus references from prior work in the ecosystem (all MIT or otherwise permissively licensed):

  • tmatijevich/tree-sitter-structured-text — B&R-leaning partial grammar; this project's literal regex shape and basic precedence layout drew from it.
  • teunreyniers/tree-sitter-structured-text — generic ST grammar; informed the named-precedence-table approach and VAR-block factoring.
  • klauer/blark — Lark-based TwinCAT parser; the most comprehensive open-source IEC 61131-3 grammar. Used as a reference for the rule organization, the OOP/extension surface, and which features are truly TwinCAT-only vs. standard.

License

MIT — see LICENSE.

Project details


Download files

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

Source Distribution

tree_sitter_iec61131_3_st-0.1.0.tar.gz (80.8 kB view details)

Uploaded Source

File details

Details for the file tree_sitter_iec61131_3_st-0.1.0.tar.gz.

File metadata

File hashes

Hashes for tree_sitter_iec61131_3_st-0.1.0.tar.gz
Algorithm Hash digest
SHA256 c921e2338d8780331f7d28a6a249a24f70b946e7e9543412859346119d90894a
MD5 ac53f4b5b769992603a266d0a7fa2f7a
BLAKE2b-256 e10e7975a5c1c06bf1dda790366beb07bde07adaa3d828aeed111e456560ae3d

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page