Completed
Push — master ( bd87f9...9971b9 )
by Richard
06:03
created

Parser::literal()   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 1
Bugs 0 Features 0
Metric Value
dl 0
loc 4
ccs 3
cts 3
cp 1
rs 10
c 1
b 0
f 0
cc 1
eloc 3
nc 1
nop 2
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 37
    public function __construct() {
33 37
        $this->symbol_table = $this->create_symbol_table();
34 37
        $this->add_symbols_to($this->symbol_table);
35 37
    }
36
37
    /**
38
     * Parse the string according to this parser.
39
     *
40
     * @return mixed
41
     */
42 37
    public function parse($source) {
43
        try {
44 37
            $this->tokenizer = $this->create_tokenizer($source);
45 37
            $this->token = $this->tokenizer->current();
46 37
            return $this->root();
47
        }
48
        finally {
49 37
            $this->tokenizer = null;
50 37
            $this->token = null;
51
        }
52
    }
53
54
    /**
55
     * The root for the parse tree.
56
     *
57
     * @return  mixed
58
     */
59
    abstract protected function root();
60
61
    // Factory Methods
62
63
    /**
64
     * Build the Tokenizer.
65
     *
66
     * @return  Tokenizer
67
     */
68 37
    public function create_tokenizer($source) {
69 37
        assert('is_string($source)');
70 37
        return new Tokenizer($this->symbol_table, $source);
71
    }
72
73
    /**
74
     * Build the SymbolTable
75
     *
76
     * @return SymbolTable
77
     */
78 37
    protected function create_symbol_table() {
79 37
        return new SymbolTable();
80
    }
81
82
    /**
83
     * @param   SymbolTable
84
     * @return  null
85
     */
86
    abstract protected function add_symbols_to(SymbolTable $table);
87
88
    // Helpers for defining the grammar.
89
90
91
    // Helpers for actual parsing.
92
93
    /**
94
     * Set the current token to the next token from the tokenizer.
95
     *
96
     * @return  null
97
     */
98 35
    protected function fetch_next_token() {
99 35
        assert('is_array($this->token)');
100 35
        assert('$this->tokenizer !== null');
101 35
        $this->tokenizer->next();
102 35
        $this->token = $this->tokenizer->current();
103 35
    }
104
105
    /**
106
     * Get the current symbol.
107
     *
108
     * @return  Symbol
109
     */
110 31
    protected function current_symbol() {
111 31
        return $this->token[0];
112
    }
113
114
    /**
115
     * Get the current match.
116
     *
117
     * @return  string[] 
118
     */
119 35
    protected function current_match() {
120 35
        return $this->token[1];
121
    }
122
123
    /**
124
     * Advance the tokenizer to the next token if current token
125
     * was matched by the given regexp.
126
     *
127
     * @param   string  $regexp
128
     * @return  null
129
     */
130 14
    protected function advance($regexp) {
131 14
        assert('is_string($regexp)');
132 14
        assert('is_array($this->token)');
133 14
        assert('$this->tokenizer !== null');
134 14
        if (!$this->is_current_token_matched_by($regexp)) {
135
            throw new ParserException("Syntax Error: Expected '$regexp'");
136
        }
137 14
        $this->tokenizer->next();
138 14
        $this->token = $this->tokenizer->current();
139 14
    }
140
141
    /**
142
     * Advance the tokenizer to the next token if current token
143
     * was matched by the given operator.
144
     *
145
     * @param   string  $op
146
     * @return  null
147
     */
148 10
    protected function advance_operator($op) {
149 10
        $this->advance($this->symbol_table->operator_regexp($op));
150 10
    }
151
152
    /**
153
     * Is the end of the file reached?
154
     *
155
     * @return  bool
156
     */
157 28
    public function is_end_of_file_reached() {
158 28
        return $this->is_current_token_matched_by("");
159
    }
160
161
    /**
162
     * Check if the current token was matched by the given regexp.
163
     *
164
     * @param   string  $regexp
165
     * @return  bool
166
     */
167 35
    protected function is_current_token_matched_by($regexp) {
168 35
        assert('is_string($regexp)');
169 35
        return $this->token[0]->regexp() == $regexp;
170
    }
171
172
    /**
173
     * Check if the current token is the given operator.
174
     *
175
     * @param   string  $operator
176
     * @return  bool
177
     */
178 7
    protected function is_current_token_operator($operator) {
179 7
        return $this->is_current_token_matched_by
180 7
            ($this->symbol_table->operator_regexp($operator));
181
    }
182
}
183