1: <?php
2: // Parco
3: // Copyright (c) 2015 Niels Sonnich Poulsen (http://nielssp.dk)
4: // Licensed under the MIT license.
5: // See the LICENSE file or http://opensource.org/licenses/MIT for more information.
6: namespace Parco;
7:
8: /**
9: * A trait that adds a mutable position (line and column numbers). Implements
10: * the interface {@see Positional}.
11: */
12: trait Position
13: {
14:
15: /**
16: * @var int[]
17: */
18: private $pos = [0, 0];
19:
20: /**
21: * Get the stored position.
22: *
23: * @return int[]
24: * Position as a 2-element array, see {@see Positional}.
25: */
26: public function getPosition()
27: {
28: return $this->pos;
29: }
30:
31: /**
32: * Set the stored position.
33: *
34: * @param int[]
35: * Position as a 2-element array, see {@see Positional}.
36: */
37: public function setPosition(array $pos)
38: {
39: $this->pos = $pos;
40: }
41:
42: /**
43: * Get the stored line number.
44: *
45: * @return int Line number (starting from 1).
46: * @deprecated Use {@see getPosition} or {@see getInputLine} depending on
47: * context.
48: */
49: public function line()
50: {
51: return $this->pos[0];
52: }
53:
54: /**
55: * Get the stored column number.
56: *
57: * @return int Column number (starting from 1).
58: * @deprecated Use {@see getPosition} or {@see getInputColumn} depending on
59: * context.
60: */
61: public function column()
62: {
63: return $this->pos[1];
64: }
65:
66: /**
67: * Get the line number for an array of lines.
68: * Returns `0` if the position is unknown, or the sequence of lines is
69: * empty.
70: * Returns the last line number if position is at the end of the input.
71: *
72: * @param string[] $lines
73: * List of lines (e.g. result of `explode("\n", $input)`).
74: * @return int The positive line number or 0 if unknown.
75: * @since 1.1.0
76: */
77: public function getInputLine($lines)
78: {
79: if (! count($lines) or $this->pos[0] == 0) {
80: return 0;
81: }
82: if ($this->pos[0] < 0) {
83: return count($lines);
84: }
85: return $this->pos[0];
86: }
87:
88: /**
89: * Get the column number for an array of lines.
90: * Returns `0` if the position is unknown, or the sequence of lines is
91: * empty.
92: * If the position is at the end of the input,
93: *
94: * @param string[] $lines
95: * List of lines (e.g. result of `explode("\n", $input)`).
96: * @return int The positive column number or 0 if unknown.
97: * @since 1.1.0
98: */
99: public function getInputColumn($lines)
100: {
101: if (! count($lines) or $this->pos[0] == 0) {
102: return 0;
103: }
104: if ($this->pos[0] < 0) {
105: return strlen($lines[count($lines) - 1]) + 1;
106: }
107: return $this->pos[1];
108: }
109:
110: /**
111: * Compare two positions.
112: *
113: * @param int[] $a
114: * First position.
115: * @param int[] $b
116: * Second position.
117: * @return int 0 if the two positions are equal, a negative integer if
118: * `$b` is greater than `$a`, and a positive integer if `$a` is
119: * greater than `$b`.
120: */
121: public static function comparePositions(array $a, array $b)
122: {
123: if ($a[0] < 0) {
124: if ($b[0] < 0) {
125: return 0;
126: }
127: return 1;
128: }
129: if ($b[0] < 0) {
130: return -1;
131: }
132: if ($a[0] == $b[0]) {
133: return $a[1] - $b[1];
134: }
135: return $a[0] - $b[0];
136: }
137: }
138: