Issues (67)

src/RuleContext.php (2 issues)

1
<?php
2
3
declare(strict_types=1);
4
5
namespace Antlr\Antlr4\Runtime;
6
7
use Antlr\Antlr4\Runtime\Atn\ATN;
8
use Antlr\Antlr4\Runtime\Tree\ParseTree;
9
use Antlr\Antlr4\Runtime\Tree\ParseTreeVisitor;
10
use Antlr\Antlr4\Runtime\Tree\RuleNode;
11
use Antlr\Antlr4\Runtime\Tree\Tree;
12
use Antlr\Antlr4\Runtime\Tree\Trees;
13
14
/**
15
 * A rule context is a record of a single rule invocation.
16
 *
17
 * We form a stack of these context objects using the parent pointer. A parent
18
 * pointer of null indicates that the current context is the bottom of the stack.
19
 * The {@see ParserRuleContext} subclass as a children list so that we can turn
20
 * this data structure into a tree.
21
 *
22
 * The root node always has a null pointer and invokingState of -1.
23
 *
24
 * Upon entry to parsing, the first invoked rule function creates a context object
25
 * (a subclass specialized for that rule such as SContext) and makes it the root
26
 * of a parse tree, recorded by field Parser->ctx.
27
 *
28
 *     public final s(){
29
 *         SContext _localctx = new SContext(_ctx, getState()); <-- create new node
30
 *         enterRule(_localctx, 0, RULE_s);                     <-- push it
31
 *         ...
32
 *         exitRule();                                          <-- pop back to _localctx
33
 *         return _localctx;
34
 *     }
35
 *
36
 * A subsequent rule invocation of r from the start rule s pushes a new
37
 * context object for r whose parent points at s and use invoking state is
38
 * the state with r emanating as edge label.
39
 *
40
 * The invokingState fields from a context object to the root together
41
 * form a stack of rule indication states where the root (bottom of the stack)
42
 * has a -1 sentinel value. If we invoke start symbol s then call r1,
43
 * which calls r2, the  would look like this:
44
 *
45
 *     SContext[-1]   <- root node (bottom of the stack)
46
 *     R1Context[p]   <- p in rule s called r1
47
 *     R2Context[q]   <- q in rule r1 called r2
48
 *
49
 * So the top of the stack, `_ctx`, represents a call to the current rule
50
 * and it holds the return address from another rule that invoke to this rule.
51
 * To invoke a rule, we must always have a current context.
52
 *
53
 * The parent contexts are useful for computing lookahead sets and getting
54
 * error information.
55
 *
56
 * These objects are used during parsing and prediction. For the special case
57
 * of parsers, we use the subclass {@see ParserRuleContext}.
58
 */
59
class RuleContext implements RuleNode
60
{
61
    /**
62
     * The context that invoked this rule.
63
     *
64
     * @var RuleContext|null
65
     */
66
    public $parentCtx;
67
68
    /**
69
     * What state invoked the rule associated with this context?
70
     * The "return address" is the followState of invokingState. If parent
71
     * is null, this should be -1 this context object represents the start rule.
72
     *
73
     * @var int
74
     */
75
    public $invokingState = -1;
76
77 7
    public function __construct(?RuleContext $parent, ?int $invokingState = null)
78
    {
79 7
        $this->parentCtx = $parent;
80 7
        $this->invokingState = $invokingState ?? -1;
81 7
    }
82
83 1
    public static function emptyContext() : ParserRuleContext
84
    {
85 1
        static $empty;
86
87 1
        return $empty ?? ($empty = new ParserRuleContext(null));
88
    }
89
90
    public function depth() : int
91
    {
92
        $n = 0;
93
        $p = $this;
94
95
        while ($p !== null) {
96
            $p = $p->parentCtx;
97
            $n++;
98
        }
99
100
        return $n;
101
    }
102
103
    /**
104
     * A context is empty if there is no invoking state; meaning nobody call
105
     * current context.
106
     */
107
    public function isEmpty() : bool
108
    {
109
        return $this->invokingState === -1;
110
    }
111
112
    public function getSourceInterval() : Interval
113
    {
114
        return Interval::invalid();
115
    }
116
117
    public function getRuleContext() : RuleContext
118
    {
119
        return $this;
120
    }
121
122
    public function getPayload() : RuleContext
123
    {
124
        return $this;
125
    }
126
127
    /**
128
     * Return the combined text of all child nodes. This method only considers
129
     * tokens which have been added to the parse tree.
130
     *
131
     * Since tokens on hidden channels (e.g. whitespace or comments) are not
132
     * added to the parse trees, they will not appear in the output
133
     * of this method.
134
     */
135
    public function getText() : string
136
    {
137
        $text = '';
138
139
        for ($i = 0, $count = $this->getChildCount(); $i < $count; $i++) {
140
            $child = $this->getChild($i);
0 ignored issues
show
Are you sure the assignment to $child is correct as $this->getChild($i) targeting Antlr\Antlr4\Runtime\RuleContext::getChild() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

The method getObject() can return nothing but null, so it makes no sense to assign that value to a variable.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
141
142
            if ($child !== null) {
143
                $text .= $child->getText();
144
            }
145
        }
146
147
        return $text;
148
    }
149
150
    public function getRuleIndex() : int
151
    {
152
        return -1;
153
    }
154
155
    /**
156
     * For rule associated with this parse tree internal node, return the outer
157
     * alternative number used to match the input. Default implementation
158
     * does not compute nor store this alt num. Create a subclass of
159
     * {@see ParserRuleContext} with backing field and set option
160
     * `contextSuperClass` to set it.
161
     */
162
    public function getAltNumber() : int
163
    {
164
        return ATN::INVALID_ALT_NUMBER;
165
    }
166
167
    /**
168
     * Set the outer alternative number for this context node. Default
169
     * implementation does nothing to avoid backing field overhead for trees
170
     * that don't need it. Create a subclass of {@see ParserRuleContext} with backing
171
     * field and set option `contextSuperClass`.
172
     */
173 4
    public function setAltNumber(int $altNumber) : void
0 ignored issues
show
The parameter $altNumber is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

173
    public function setAltNumber(/** @scrutinizer ignore-unused */ int $altNumber) : void

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
174
    {
175 4
    }
176
177
    /**
178
     * @return RuleContext|null
179
     */
180
    public function getParent() : ?Tree
181
    {
182
        return $this->parentCtx;
183
    }
184
185 4
    public function setParent(?RuleContext $ctx) : void
186
    {
187 4
        $this->parentCtx = $ctx;
188 4
    }
189
190
    /**
191
     * @return ParseTree|null
192
     */
193
    public function getChild(int $i, ?string $type = null) : ?Tree
194
    {
195
        return null;
196
    }
197
198
    public function getChildCount() : int
199
    {
200
        return 0;
201
    }
202
203 3
    public function accept(ParseTreeVisitor $visitor)
204
    {
205 3
        return $visitor->visitChildren($this);
206
    }
207
208
    /**
209
     * Print out a whole tree, not just a node, in LISP format
210
     * (root child1 .. childN). Print just a node if this is a leaf.
211
     *
212
     * @param array<string>|null $ruleNames
213
     */
214
    public function toStringTree(?array $ruleNames = null) : string
215
    {
216
        return Trees::toStringTree($this, $ruleNames);
217
    }
218
219
    public function __toString() : string
220
    {
221
        return $this->toString();
222
    }
223
224
    /**
225
     * @param array<string>|null $ruleNames
226
     */
227
    public function toString(?array $ruleNames = null, ?RuleContext $stop = null) : string
228
    {
229
        $p = $this;
230
        $string = '[';
231
232
        while ($p !== null && $p !== $stop) {
233
            if ($ruleNames === null) {
234
                if (!$p->isEmpty()) {
235
                    $string .= $p->invokingState;
236
                }
237
            } else {
238
                $ri = $p->getRuleIndex();
239
                $ruleName = $ri >= 0 && $ri < \count($ruleNames) ? $ruleNames[$ri] : (string) $ri;
240
                $string .= $ruleName;
241
            }
242
243
            if ($p->parentCtx !== null && ($ruleNames !== null || !$p->parentCtx->isEmpty())) {
244
                $string .= ' ';
245
            }
246
247
            $p = $p->parentCtx;
248
        }
249
250
        return $string . ']';
251
    }
252
}
253