Martin Helmich (typo3 at martin-helmich dot de)
This package contains a library offering a tokenizer and a parser for TYPO3's configuration language, "TypoScript".
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!).
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);
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();