forked from jasder/antlr
111 lines
3.0 KiB
Markdown
111 lines
3.0 KiB
Markdown
|
# ANTLR4 Runtime for PHP
|
||
|
|
||
|
### First steps
|
||
|
|
||
|
#### 1. Install ANTLR4
|
||
|
|
||
|
[The getting started guide](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md)
|
||
|
should get you started.
|
||
|
|
||
|
#### 2. Install the PHP ANTLR runtime
|
||
|
|
||
|
Each target language for ANTLR has a runtime package for running parser
|
||
|
generated by ANTLR4. The runtime provides a common set of tools for using your parser.
|
||
|
|
||
|
Install the runtime with Composer:
|
||
|
|
||
|
```bash
|
||
|
composer install antlr/antlr4
|
||
|
```
|
||
|
|
||
|
#### 3. Generate your parser
|
||
|
|
||
|
You use the ANTLR4 "tool" to generate a parser. These will reference the ANTLR
|
||
|
runtime, installed above.
|
||
|
|
||
|
Suppose you're using a UNIX system and have set up an alias for the ANTLR4 tool
|
||
|
as described in [the getting started guide](https://github.com/antlr/antlr4/blob/master/doc/getting-started.md).
|
||
|
To generate your PHP parser, run the following command:
|
||
|
|
||
|
```bash
|
||
|
antlr4 -Dlanguage=PHP MyGrammar.g4
|
||
|
```
|
||
|
|
||
|
For a full list of antlr4 tool options, please visit the
|
||
|
[tool documentation page](https://github.com/antlr/antlr4/blob/master/doc/tool-options.md).
|
||
|
|
||
|
### Complete example
|
||
|
|
||
|
Suppose you're using the JSON grammar from https://github.com/antlr/grammars-v4/tree/master/json.
|
||
|
|
||
|
Then, invoke `antlr4 -Dlanguage=PHP JSON.g4`. The result of this is a
|
||
|
collection of `.php` files in the `parser` directory including:
|
||
|
```
|
||
|
JsonParser.php
|
||
|
JsonBaseListener.php
|
||
|
JsonLexer.php
|
||
|
JsonListener.php
|
||
|
```
|
||
|
|
||
|
Another common option to the ANTLR tool is `-visitor`, which generates a parse
|
||
|
tree visitor, but we won't be doing that here. For a full list of antlr4 tool
|
||
|
options, please visit the [tool documentation page](tool-options.md).
|
||
|
|
||
|
We'll write a small main func to call the generated parser/lexer
|
||
|
(assuming they are separate). This one writes out the encountered
|
||
|
`ParseTreeContext`'s:
|
||
|
|
||
|
```php
|
||
|
<?php
|
||
|
|
||
|
namespace JsonParser;
|
||
|
|
||
|
use Antlr\Antlr4\Runtime\CommonTokenStream;
|
||
|
use Antlr\Antlr4\Runtime\Error\Listeners\DiagnosticErrorListener;
|
||
|
use Antlr\Antlr4\Runtime\InputStream;
|
||
|
use Antlr\Antlr4\Runtime\ParserRuleContext;
|
||
|
use Antlr\Antlr4\Runtime\Tree\ErrorNode;
|
||
|
use Antlr\Antlr4\Runtime\Tree\ParseTreeListener;
|
||
|
use Antlr\Antlr4\Runtime\Tree\ParseTreeWalker;
|
||
|
use Antlr\Antlr4\Runtime\Tree\TerminalNode;
|
||
|
|
||
|
final class TreeShapeListener implements ParseTreeListener {
|
||
|
public function visitTerminal(TerminalNode $node) : void {}
|
||
|
public function visitErrorNode(ErrorNode $node) : void {}
|
||
|
public function exitEveryRule(ParserRuleContext $ctx) : void {}
|
||
|
|
||
|
public function enterEveryRule(ParserRuleContext $ctx) : void {
|
||
|
echo $ctx->getText();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
$input = InputStream::fromPath($argv[1]);
|
||
|
$lexer = new JSONLexer($input);
|
||
|
$tokens = new CommonTokenStream($lexer);
|
||
|
$parser = new JSONParser($tokens);
|
||
|
$parser->addErrorListener(new DiagnosticErrorListener());
|
||
|
$parser->setBuildParseTree(true);
|
||
|
$tree = $parser->json();
|
||
|
|
||
|
ParseTreeWalker::default()->walk(new TreeShapeListener(), $tree);
|
||
|
```
|
||
|
|
||
|
Create a `example.json` file:
|
||
|
```json
|
||
|
{"a":1}
|
||
|
```
|
||
|
|
||
|
Parse the input file:
|
||
|
|
||
|
```
|
||
|
php json.php example.json
|
||
|
```
|
||
|
|
||
|
The expected output is:
|
||
|
|
||
|
```
|
||
|
{"a":1}
|
||
|
{"a":1}
|
||
|
"a":1
|
||
|
1
|
||
|
```
|