Completed
Push — master ( f7852e...e666ea )
by Richard
06:08
created

Parser::is_current_token_operator()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 3
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 0
b 0
f 0
cc 1
eloc 3
nc 1
nop 1
crap 1
1
<?php
2
/******************************************************************************
3
 * An implementation of dicto (scg.unibe.ch/dicto) in and for PHP.
4
 *
5
 * Copyright (c) 2016 Richard Klees <[email protected]>
6
 * 
7
 * This software is licensed under The MIT License. You should have received
8
 * a copy of the license along with the code.
9
 */
10
11
namespace Lechimp\Dicto\Definition;
12
13
/**
14
 * Baseclass for Parsers.
15
 */
16
abstract class Parser {
17
    /**
18
     * @var SymbolTable
19
     */
20
    private $symbol_table;
21
22
    /**
23
     * @var Tokenizer|null
24
     */
25
    protected $tokenizer = null;
26
27
    /**
28
     * @var array|null   (Symbol, array $matches)
29
     */
30
    protected $token = null;
31
32 43
    public function __construct() {
33 43
        $this->symbol_table = $this->create_symbol_table();
34 43
        $this->add_symbols_to($this->symbol_table);
35 43
    }
36
37
    /**
38
     * Parse the string according to this parser.
39
     *
40
     * @return mixed
41
     */
42 43
    public function parse($source) {
43
        try {
44 43
            $this->tokenizer = $this->create_tokenizer($source);
45 43
            $this->token = $this->tokenizer->current();
46 43
            return $this->root();
47
        }
48 1
        catch (ParserException $e) {
49 1
            list($l, $c) = $this->tokenizer->source_position();
50 1
            $e->setPosition($l, $c);
51 1
            throw $e;
52
        }
53
        finally {
54 43
            $this->tokenizer = null;
55 43
            $this->token = null;
56 43
        }
57
    }
58
59
    /**
60
     * The root for the parse tree.
61
     *
62
     * @return  mixed
63
     */
64
    abstract protected function root();
65
66
    // Factory Methods
67
68
    /**
69
     * Build the Tokenizer.
70
     *
71
     * @return  Tokenizer
72
     */
73 43
    public function create_tokenizer($source) {
74 43
        assert('is_string($source)');
75 43
        return new Tokenizer($this->symbol_table, $source);
76
    }
77
78
    /**
79
     * Build the SymbolTable
80
     *
81
     * @return SymbolTable
82
     */
83 43
    protected function create_symbol_table() {
84 43
        return new SymbolTable();
85
    }
86
87
    /**
88
     * @param   SymbolTable
89
     * @return  null
90
     */
91
    abstract protected function add_symbols_to(SymbolTable $table);
92
93
    // Helpers for defining the grammar.
94
95
96
    // Helpers for actual parsing.
97
98
    /**
99
     * Set the current token to the next token from the tokenizer.
100
     *
101
     * @return  null
102
     */
103 41
    protected function fetch_next_token() {
104 41
        assert('is_array($this->token)');
105 41
        assert('$this->tokenizer !== null');
106 41
        $this->tokenizer->next();
107 41
        $this->token = $this->tokenizer->current();
108 41
    }
109
110
    /**
111
     * Get the current symbol.
112
     *
113
     * @return  Symbol
114
     */
115 37
    protected function current_symbol() {
116 37
        return $this->token[0];
117
    }
118
119
    /**
120
     * Get the current match.
121
     *
122
     * @return  string[] 
123
     */
124 41
    protected function current_match() {
125 41
        return $this->token[1];
126
    }
127
128
    /**
129
     * Advance the tokenizer to the next token if current token
130
     * was matched by the given regexp.
131
     *
132
     * @param   string  $regexp
133
     * @return  null
134
     */
135 19
    protected function advance($regexp) {
136 19
        assert('is_string($regexp)');
137 19
        assert('is_array($this->token)');
138 19
        assert('$this->tokenizer !== null');
139 19
        if (!$this->is_current_token_matched_by($regexp)) {
140
            throw new ParserException("Syntax Error: Expected '$regexp'");
141
        }
142 19
        $this->tokenizer->next();
143 19
        $this->token = $this->tokenizer->current();
144 19
    }
145
146
    /**
147
     * Advance the tokenizer to the next token if current token
148
     * was matched by the given operator.
149
     *
150
     * @param   string  $op
151
     * @return  null
152
     */
153 7
    protected function advance_operator($op) {
154 7
        $this->advance($this->symbol_table->operator_regexp($op));
155 7
    }
156
157
    /**
158
     * Is the end of the file reached?
159
     *
160
     * @return  bool
161
     */
162 33
    public function is_end_of_file_reached() {
163 33
        return $this->is_current_token_matched_by("");
164
    }
165
166
    /**
167
     * Check if the current token was matched by the given regexp.
168
     *
169
     * @param   string  $regexp
170
     * @return  bool
171
     */
172 40
    protected function is_current_token_matched_by($regexp) {
173 40
        assert('is_string($regexp)');
174 40
        return $this->token[0]->regexp() == $regexp;
175
    }
176
177
    /**
178
     * Check if the current token is the given operator.
179
     *
180
     * @param   string  $operator
181
     * @return  bool
182
     */
183 4
    protected function is_current_token_operator($operator) {
184 4
        return $this->is_current_token_matched_by
185 4
            ($this->symbol_table->operator_regexp($operator));
186
    }
187
}
188