-
Notifications
You must be signed in to change notification settings - Fork 0
/
grammar
executable file
·120 lines (87 loc) · 3.27 KB
/
grammar
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#!/usr/bin/env php
<?php declare(strict_types=1);
/*
* This file is part of the Zephir Language Specifications.
*
* (c) Zephir Team <[email protected]>
*
* For the full copyright and license information, please view
* the LICENSE file that was distributed with this source code.
*/
use Zephir\Exceptions\DuplicateDefinitionException;
use Zephir\Exceptions\NoSpecFileFoundException;
use Zephir\Spec\Files;
use function Zephir\Grammar\extract_grammar;
use function Zephir\Grammar\extract_heading;
use function Zephir\Grammar\get_all_defs;
use function Zephir\Grammar\parse_grammar;
use function Zephir\Grammar\render_grammar;
require_once __DIR__ . '/vendor/autoload.php';
error_reporting(-1);
$specDir = __DIR__ . '/spec';
try {
$files = new Files($specDir);
fprintf(STDOUT, 'Render grammars (after GRAMMAR blocks)...%s', PHP_EOL);
// Collect all defined names (for referencing)
$names = [];
foreach ($files() as $fileName => $path) {
$code = file_get_contents($path);
$definitions = get_all_defs($code);
foreach ($definitions as $definition) {
if (isset($names[$definition->getName()])) {
throw new DuplicateDefinitionException($definition->getName());
}
$names[$definition->getName()] = $fileName;
}
}
// Render grammars
foreach ($files() as $fileName => $path) {
$code = $origCode = file_get_contents($path);
$code = preg_replace_callback(
'/(<!--\s*GRAMMAR(.*?)-->)\s+<pre>.*?<\/pre>/s',
function ($matches) use ($names, $fileName) {
$defs = parse_grammar($matches[2]);
$rendered = render_grammar($defs, $names, $fileName);
return $matches[1] . "\n\n" . $rendered;
},
$code
);
if ($code !== $origCode) {
file_put_contents($path, $code);
}
}
fprintf(STDOUT, 'Generate summary grammar chapter...%s', PHP_EOL);
// Pretend that all definitions are inside 19-grammar.md now
$names = array_fill_keys(array_keys($names), '19-grammar.md');
$grammarFile = $specDir . '/19-grammar.md';
$output = <<<'END'
# Grammar
## General
The grammar notation is described in [Grammars section](09-lexical-structure.md#grammars).
## Lexical Grammar
END;
if (file_exists($specDir . '/09-lexical-structure.md') == false) {
throw new NoSpecFileFoundException('09-lexical-structure.md');
}
$lexical = file_get_contents($specDir . '/09-lexical-structure.md');
$lexical = strstr($lexical, '## Lexical analysis');
$output .= extract_grammar($lexical, $names);
$output .= "\n\n## Syntactic Grammar";
$skipFiles = ['05-types.md', '09-lexical-structure.md', '19-grammar.md'];
foreach ($files($skipFiles) as $fileName => $path) {
$code = file_get_contents($path);
$grammar = extract_grammar($code, $names);
if ($grammar === null) {
continue;
}
$heading = extract_heading($code, $fileName);
$output .= "\n\n### $heading\n\n" . $grammar;
}
$output .= "\n";
file_put_contents($grammarFile, $output);
echo 'Done!', PHP_EOL;
exit(0);
} catch (Throwable $e) {
fprintf(STDERR, "Error: %s%s", $e->getMessage(), PHP_EOL);
exit(1);
}