Completed
Push — master ( 8a5799...ed0b0a )
by Kirill
07:58
created

Parser::bootLexer()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 0
cts 4
cp 0
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 2
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\Compiler\Grammar;
11
12
use Railt\Compiler\Grammar\Delegate\IncludeDelegate;
13
use Railt\Compiler\Grammar\Delegate\RuleDelegate;
14
use Railt\Compiler\Grammar\Delegate\TokenDelegate;
15
use Railt\Lexer\Factory;
16
use Railt\Lexer\LexerInterface;
17
use Railt\Parser\Driver\Llk;
18
use Railt\Parser\Driver\Stateful;
19
use Railt\Parser\Grammar;
20
use Railt\Parser\GrammarInterface;
21
use Railt\Parser\ParserInterface;
22
use Railt\Parser\Rule\Alternation;
23
use Railt\Parser\Rule\Concatenation;
24
use Railt\Parser\Rule\Repetition;
25
use Railt\Parser\Rule\Terminal;
26
27
/**
28
 * Class Parser
29
 */
30
class Parser extends Stateful
31
{
32
    /**
33
     * @var string[]
34
     */
35
    private const LEXER_TOKENS = [
36
        'T_PRAGMA'              => '%pragma\\h+([\\w\\.]+)\\h+([^\\s]+)',
37
        'T_INCLUDE'             => '%include\\h+([^\\s]+)',
38
        'T_TOKEN'               => '%token\\h+(\\w+)\\h+([^\\s]+)',
39
        'T_SKIP'                => '%skip\\h+(\\w+)\\h+([^\\s]+)',
40
        'T_OR'                  => '\\|',
41
        'T_TOKEN_SKIPPED'       => '::(\\w+)::',
42
        'T_TOKEN_KEPT'          => '<(\\w+)>',
43
        'T_TOKEN_STRING'        => '("[^"\\\\]+(\\\\.[^"\\\\]*)*"|\'[^\'\\\\]+(\\\\.[^\'\\\\]*)*\')',
44
        'T_INVOKE'              => '(\\w+)\\(\\)',
45
        'T_GROUP_OPEN'          => '\\(',
46
        'T_GROUP_CLOSE'         => '\\)',
47
        'T_REPEAT_ZERO_OR_ONE'  => '\\?',
48
        'T_REPEAT_ONE_OR_MORE'  => '\\+',
49
        'T_REPEAT_ZERO_OR_MORE' => '\\*',
50
        'T_REPEAT_N_TO_M'       => '{\\h*(\\d+)\\h*,\\h*(\\d+)\\h*}',
51
        'T_REPEAT_N_OR_MORE'    => '{\\h*(\\d+)\\h*,\\h*}',
52
        'T_REPEAT_ZERO_TO_M'    => '{\\h*,\\h*(\\d+)\\h*}',
53
        'T_REPEAT_EXACTLY_N'    => '{\\h*(\\d+)\\h*}',
54
        'T_KEPT_NAME'           => '#',
55
        'T_NAME'                => '[a-zA-Z_\\x7f-\\xff\\\\][a-zA-Z0-9_\\x7f-\\xff\\\\]*',
56
        'T_EQ'                  => '(?:::)?=',
57
        'T_COLON'               => ':',
58
        'T_END_OF_RULE'         => ';',
59
        'T_DELEGATE'            => '\\->',
60
        'T_WHITESPACE'          => '(\\xfe\\xff|\\x20|\\x09|\\x0a|\\x0d)+',
61
        'T_COMMENT'             => '//[^\\n]*',
62
        'T_BLOCK_COMMENT'       => '/\\*.*?\\*/',
63
    ];
64
65
    /**
66
     * @var string[]
67
     */
68
    private const LEXER_SKIPPED_TOKENS = [
69
        'T_WHITESPACE',
70
        'T_COMMENT',
71
        'T_BLOCK_COMMENT',
72
    ];
73
74
    /**
75
     * @var string[]
76
     */
77
    private const PARSER_DELEGATES = [
78
        'IncludeDefinition' => IncludeDelegate::class,
79
        'TokenDefinition'   => TokenDelegate::class,
80
        'RuleDefinition'    => RuleDelegate::class,
81
    ];
82
83
    /**
84
     * @return ParserInterface
85
     * @throws \InvalidArgumentException
86
     * @throws \Railt\Lexer\Exception\BadLexemeException
87
     * @throws \Railt\Parser\Exception\GrammarException
88
     */
89
    protected function boot(): ParserInterface
90
    {
91
        return new Llk($this->bootLexer(), $this->bootGrammar());
92
    }
93
94
    /**
95
     * @return LexerInterface
96
     * @throws \InvalidArgumentException
97
     * @throws \Railt\Lexer\Exception\BadLexemeException
98
     */
99
    public function bootLexer(): LexerInterface
100
    {
101
        return Factory::create(self::LEXER_TOKENS, self::LEXER_SKIPPED_TOKENS, Factory::LOOKAHEAD);
102
    }
103
104
    /**
105
     * @return GrammarInterface
106
     * @throws \Railt\Parser\Exception\GrammarException
107
     */
108
    protected function bootGrammar(): GrammarInterface
109
    {
110
        return new Grammar([
111
            new Repetition(0, 0, -1, '__definition', null),
112
            new Concatenation('Grammar', [0,], 'Grammar'),
113
            new Alternation('__definition', ['TokenDefinition', 'PragmaDefinition', 'IncludeDefinition', 'RuleDefinition',], null),
114
            new Terminal(3, 'T_TOKEN', true),
115
            new Concatenation(4, [3,], 'TokenDefinition'),
116
            new Terminal(5, 'T_SKIP', true),
117
            new Concatenation(6, [5,], 'TokenDefinition'),
118
            new Alternation('TokenDefinition', [4, 6,], null),
119
            new Terminal(8, 'T_PRAGMA', true),
120
            new Concatenation('PragmaDefinition', [8,], 'PragmaDefinition'),
121
            new Terminal(10, 'T_INCLUDE', true),
122
            new Concatenation('IncludeDefinition', [10,], 'IncludeDefinition'),
123
            new Repetition(12, 0, 1, 'ShouldKeep', null),
124
            new Repetition(14, 0, 1, 'RuleDelegate', null),
125
            new Concatenation('RuleDefinition', [12, 'RuleName', 'RuleProduction', 19], 'RuleDefinition'),
126
            new Terminal(16, 'T_NAME', true),
127
            new Concatenation('RuleName', [16, 14, '__ruleProductionDelimiter',], 'RuleName'),
128
            new Terminal(18, 'T_END_OF_RULE', false),
129
            new Repetition(19, 0, 1, 18),
130
            new Terminal(21, 'T_DELEGATE', false),
131
            new Terminal(22, 'T_NAME', true),
132
            new Concatenation('RuleDelegate', [21, 22,], 'RuleDelegate'),
133
            new Terminal(24, 'T_KEPT_NAME', false),
134
            new Concatenation('ShouldKeep', [24,], 'ShouldKeep'),
135
            new Terminal(26, 'T_COLON', false),
136
            new Terminal(27, 'T_EQ', false),
137
            new Alternation('__ruleProductionDelimiter', [26, 27,], null),
138
            new Concatenation('RuleProduction', ['__alternation',], null),
139
            new Alternation('__alternation', ['__concatenation', 'Alternation',], null),
140
            new Terminal(31, 'T_OR', false),
141
            new Concatenation(32, [31, '__concatenation',], 'Alternation'),
142
            new Repetition(33, 1, -1, 32, null),
143
            new Concatenation('Alternation', ['__concatenation', 33,], null),
144
            new Alternation('__concatenation', ['__repetition', 'Concatenation',], null),
145
            new Repetition(36, 1, -1, '__repetition', null),
146
            new Concatenation('Concatenation', ['__repetition', 36,], 'Concatenation'),
147
            new Alternation('__repetition', ['__simple', 'Repetition',], null),
148
            new Concatenation('Repetition', ['__simple', 'Quantifier',], 'Repetition'),
149
            new Terminal(40, 'T_GROUP_OPEN', false),
150
            new Terminal(41, 'T_GROUP_CLOSE', false),
151
            new Concatenation(42, [40, '__alternation', 41,], null),
152
            new Terminal(43, 'T_TOKEN_SKIPPED', true),
153
            new Terminal(44, 'T_TOKEN_KEPT', true),
154
            new Terminal(45, 'T_INVOKE', true),
155
            new Alternation('__simple', [42, 43, 44, 45,], null),
156
            new Terminal(47, 'T_REPEAT_ZERO_OR_ONE', true),
157
            new Concatenation(48, [47,], 'Quantifier'),
158
            new Terminal(49, 'T_REPEAT_ONE_OR_MORE', true),
159
            new Concatenation(50, [49,], 'Quantifier'),
160
            new Terminal(51, 'T_REPEAT_ZERO_OR_MORE', true),
161
            new Concatenation(52, [51,], 'Quantifier'),
162
            new Terminal(53, 'T_REPEAT_N_TO_M', true),
163
            new Concatenation(54, [53,], 'Quantifier'),
164
            new Terminal(55, 'T_REPEAT_ZERO_OR_MORE', true),
165
            new Concatenation(56, [55,], 'Quantifier'),
166
            new Terminal(57, 'T_REPEAT_ZERO_TO_M', true),
167
            new Concatenation(58, [57,], 'Quantifier'),
168
            new Terminal(59, 'T_REPEAT_N_OR_MORE', true),
169
            new Concatenation(60, [59,], 'Quantifier'),
170
            new Terminal(61, 'T_REPEAT_EXACTLY_N', true),
171
            new Concatenation(62, [61,], 'Quantifier'),
172
            new Alternation('Quantifier', [48, 50, 52, 54, 56, 58, 60, 62,], null),
173
        ], 'Grammar', self::PARSER_DELEGATES);
174
    }
175
}
176