helmich/typo3-typoscript-parser

Parser for the TYPO3 configuration language TypoScript.

v2.3.1 2021-05-19 07:51 UTC

README

Build Status Code Climate Test Coverage Dependabot Status

Author

Martin Helmich (typo3 at martin-helmich dot de)

Synopsis

This package contains a library offering a tokenizer and a parser for TYPO3's configuration language, "TypoScript".

Why?

Just as typoscript-lint, this project started of as a simple programming excercise. Tokenizer and parser could probably implemented in a better way (it's open source, go for it!).

Usage

Parsing TypoScript

You can use the Helmich\TypoScriptParser\Parser\Parser class to generate a syntax tree from source code input. The class requires an instance of the Helmich\TypoScriptParser\Tokenizer\Tokenizer class as dependency. When using the Symfony DependencyInjection component, you can simply use the service parser for this.

use Helmich\TypoScriptParser\Parser\Parser,
    Helmich\TypoScriptParser\Tokenizer\Tokenizer;

$typoscript = file_get_contents('path/to/typoscript.ts');
$parser     = new Parser(new Tokenizer());
$statements = $parser->parse($typoscript);

Analyzing TypoScript

You can analyze the generated syntax tree by implementing visitors. For example, let's implement a check that checks for non-CGL-compliant variable names (there's probably no use case for that, just as a simple example):

First, we need the respective visitor implementation:

use Helmich\TypoScriptParser\Parser\Traverser\Visitor,
    Helmich\TypoScriptParser\Parser\AST\Statement,
    Helmich\TypoScriptParser\Parser\AST\Operator\Assignment,
    Helmich\TypoScriptParser\Parser\AST\NestedAssignment;

class VariableNamingCheckVisitor implements Visitor {
    public function enterTree(array $statements) {}
    public function enterNode(Statement $statement) {
        if ($statement instanceof Assignment || $statement instanceof NestedAssignment) {
            if (!preg_match(',^[0-9]+$,', $statement->object->relativePath)) {
                throw new \Exception('Variable names must be numbers only!');
            }
        }
    }
    public function exitNode(Statement $statement) {}
    public function exitTree(array $statements) {}
}

Then traverse the syntax tree:

use Helmich\TypoScriptParser\Parser\Traverser\Traverser;

$traverser = new Traverser($statements);
$traverser->addVisitor(new VariableNamingCheckVisitor());
$traverser->walk();