Skip to content

Commit 52e11d8

Browse files
authored
Merge pull request #15 from mficzel/feature/spreads
!!! FEATURE: Support Spreads in AFX
2 parents 2ebd16f + 1a737f2 commit 52e11d8

File tree

5 files changed

+249
-67
lines changed

5 files changed

+249
-67
lines changed

src/Expression/Node.php

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,32 @@ class Node
88
{
99
public static function parse(Lexer $lexer)
1010
{
11-
while ($lexer->isWhitespace()) {
12-
$lexer->consume();
13-
}
14-
1511
if ($lexer->isOpeningBracket()) {
1612
$lexer->consume();
1713
}
1814

1915
$identifier = Identifier::parse($lexer);
2016

2117
try {
22-
$props = [];
18+
$attributes = [];
2319
$children = [];
2420

2521
if ($lexer->isWhitespace()) {
2622
while ($lexer->isWhitespace()) {
2723
$lexer->consume();
2824
}
2925
while (!$lexer->isForwardSlash() && !$lexer->isClosingBracket()) {
30-
list($propIdentifier, $value) = Prop::parse($lexer);
31-
$props[$propIdentifier] = $value;
26+
if ($lexer->isOpeningBrace()) {
27+
$attributes[] = [
28+
'type' => 'spread',
29+
'payload' => Spread::parse($lexer)
30+
];
31+
} else {
32+
$attributes[] = [
33+
'type' => 'prop',
34+
'payload' => Prop::parse($lexer)
35+
];
36+
}
3237
while ($lexer->isWhitespace()) {
3338
$lexer->consume();
3439
}
@@ -43,7 +48,7 @@ public static function parse(Lexer $lexer)
4348

4449
return [
4550
'identifier' => $identifier,
46-
'props' => $props,
51+
'attributes' => $attributes,
4752
'children' => $children,
4853
'selfClosing' => true
4954
];
@@ -92,7 +97,7 @@ public static function parse(Lexer $lexer)
9297
$lexer->consume();
9398
return [
9499
'identifier' => $identifier,
95-
'props' => $props,
100+
'attributes' => $attributes,
96101
'children' => $children,
97102
'selfClosing' => false
98103
];

src/Expression/Prop.php

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ class Prop
88
{
99
public static function parse(Lexer $lexer)
1010
{
11-
while ($lexer->isWhitespace()) {
12-
$lexer->consume();
13-
}
14-
1511
$identifier = Identifier::parse($lexer);
1612

1713
if ($lexer->isEqualSign()) {
@@ -21,14 +17,16 @@ public static function parse(Lexer $lexer)
2117
case $lexer->isDoubleQuote():
2218
$value = [
2319
'type' => 'string',
24-
'payload' => StringLiteral::parse($lexer)
20+
'payload' => StringLiteral::parse($lexer),
21+
'identifier' => $identifier
2522
];
2623
break;
2724

2825
case $lexer->isOpeningBrace():
2926
$value = [
3027
'type' => 'expression',
31-
'payload' => Expression::parse($lexer)
28+
'payload' => Expression::parse($lexer),
29+
'identifier' => $identifier
3230
];
3331
break;
3432
default:
@@ -40,12 +38,13 @@ public static function parse(Lexer $lexer)
4038
} elseif ($lexer->isWhiteSpace() || $lexer->isForwardSlash() || $lexer->isClosingBracket()) {
4139
$value = [
4240
'type' => 'boolean',
43-
'payload' => true
41+
'payload' => true,
42+
'identifier' => $identifier
4443
];
4544
} else {
4645
throw new Exception(sprintf('Prop identifier "%s" is neither assignment nor boolean', $identifier));
4746
}
4847

49-
return [$identifier, $value];
48+
return $value;
5049
}
5150
}

src/Expression/Spread.php

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<?php
2+
namespace PackageFactory\Afx\Expression;
3+
4+
use PackageFactory\Afx\Exception;
5+
use PackageFactory\Afx\Lexer;
6+
7+
class Spread
8+
{
9+
public static function parse(Lexer $lexer)
10+
{
11+
$contents = '';
12+
$braceCount = 0;
13+
14+
if ($lexer->isOpeningBrace() && $lexer->peek(4) === '{...') {
15+
$lexer->consume();
16+
$lexer->consume();
17+
$lexer->consume();
18+
$lexer->consume();
19+
} else {
20+
throw new Exception('Spread without braces');
21+
}
22+
23+
while (true) {
24+
if ($lexer->isEnd()) {
25+
throw new Exception(sprintf('Unfinished Spread "%s"', $contents));
26+
}
27+
28+
if ($lexer->isOpeningBrace()) {
29+
$braceCount++;
30+
}
31+
32+
if ($lexer->isClosingBrace()) {
33+
if ($braceCount === 0) {
34+
$lexer->consume();
35+
return [
36+
'type' => 'expression',
37+
'payload' => $contents
38+
];
39+
}
40+
41+
$braceCount--;
42+
}
43+
44+
$contents .= $lexer->consume();
45+
}
46+
}
47+
}

src/Lexer.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,21 @@ public function rewind()
230230
$this->currentCharacter = $this->string{--$this->characterPosition};
231231
}
232232

233+
/**
234+
* Peek several characters in advance and return the next n characters
235+
*
236+
* @param int $characterNumber
237+
* @return string|null
238+
*/
239+
public function peek($characterNumber = 1)
240+
{
241+
if ($this->characterPosition < strlen($this->string) - 1) {
242+
return substr($this->string, $this->characterPosition, $characterNumber);
243+
} else {
244+
return null;
245+
}
246+
}
247+
233248
/**
234249
* Returns the current character and moves one step forward
235250
*

0 commit comments

Comments
 (0)