Skip to content

Commit 2f5a0a1

Browse files
committed
TASK: Implement TextParser
1 parent 93dea79 commit 2f5a0a1

File tree

5 files changed

+467
-0
lines changed

5 files changed

+467
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2023 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Language\AST\Node\Text;
24+
25+
use PackageFactory\ComponentEngine\Language\AST\Node\Node;
26+
use PackageFactory\ComponentEngine\Language\AST\NodeAttributes\NodeAttributes;
27+
28+
final class TextNode extends Node
29+
{
30+
public function __construct(
31+
public readonly NodeAttributes $attributes,
32+
public readonly string $value
33+
) {
34+
}
35+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
<?php
2+
3+
/**
4+
* PackageFactory.ComponentEngine - Universal View Components for PHP
5+
* Copyright (C) 2023 Contributors of PackageFactory.ComponentEngine
6+
*
7+
* This program is free software: you can redistribute it and/or modify
8+
* it under the terms of the GNU General Public License as published by
9+
* the Free Software Foundation, either version 3 of the License, or
10+
* (at your option) any later version.
11+
*
12+
* This program is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15+
* GNU General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU General Public License
18+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
19+
*/
20+
21+
declare(strict_types=1);
22+
23+
namespace PackageFactory\ComponentEngine\Language\Parser\Text;
24+
25+
use PackageFactory\ComponentEngine\Language\AST\Node\Text\TextNode;
26+
use PackageFactory\ComponentEngine\Language\AST\NodeAttributes\NodeAttributes;
27+
use PackageFactory\ComponentEngine\Parser\Source\Range;
28+
use PackageFactory\ComponentEngine\Parser\Tokenizer\Scanner;
29+
use PackageFactory\ComponentEngine\Parser\Tokenizer\Token;
30+
use PackageFactory\ComponentEngine\Parser\Tokenizer\TokenType;
31+
32+
final class TextParser
33+
{
34+
/**
35+
* @param \Iterator<mixed,Token> $tokens
36+
* @param boolean $preserveLeadingSpace
37+
* @return null|TextNode
38+
*/
39+
public function parse(\Iterator $tokens, bool $preserveLeadingSpace = false): ?TextNode
40+
{
41+
$value = '';
42+
$startingToken = null;
43+
$finalToken = null;
44+
$ignoreSpace = false;
45+
$keepTrailingSpace = false;
46+
while (!Scanner::isEnd($tokens)) {
47+
$startingToken ??= $tokens->current();
48+
switch (Scanner::type($tokens)) {
49+
case TokenType::BRACKET_CURLY_OPEN:
50+
case TokenType::TAG_START_OPENING:
51+
$keepTrailingSpace = true;
52+
break 2;
53+
case TokenType::TAG_START_CLOSING:
54+
$value = rtrim($value);
55+
break 2;
56+
case TokenType::SPACE:
57+
case TokenType::END_OF_LINE:
58+
if (!$ignoreSpace) {
59+
$value .= ' ';
60+
}
61+
$ignoreSpace = true;
62+
$finalToken = $tokens->current();
63+
Scanner::skipOne($tokens);
64+
break;
65+
default:
66+
$value .= Scanner::value($tokens);
67+
$ignoreSpace = false;
68+
$finalToken = $tokens->current();
69+
Scanner::skipOne($tokens);
70+
break;
71+
}
72+
}
73+
74+
if (is_null($startingToken) || is_null($finalToken)) {
75+
return null;
76+
}
77+
78+
if (!$keepTrailingSpace) {
79+
$value = $preserveLeadingSpace ? rtrim($value) : trim($value);
80+
}
81+
82+
if ($value === '' || $value === ' ') {
83+
return null;
84+
}
85+
86+
return new TextNode(
87+
attributes: new NodeAttributes(
88+
rangeInSource: Range::from(
89+
$startingToken->boundaries->start,
90+
$finalToken->boundaries->end
91+
)
92+
),
93+
value: $value
94+
);
95+
}
96+
}

src/Parser/Tokenizer/Tokenizer.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ public function getIterator(): \Iterator
5656
*/
5757
private static function block(\Iterator $fragments): \Iterator
5858
{
59+
if (!$fragments->valid()) {
60+
return;
61+
}
62+
5963
$bracket = TokenType::tryBracketOpenFromFragment($fragments->current());
6064
$buffer = Buffer::empty();
6165

0 commit comments

Comments
 (0)