Skip to content

Commit 409843e

Browse files
committed
Merge branch 'patch/control-directives' into wip/incompatible-units
2 parents 9ceef0f + 060a4ce commit 409843e

File tree

6 files changed

+181
-26
lines changed

6 files changed

+181
-26
lines changed

src/Compiler.php

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -851,6 +851,27 @@ protected function compileChild($child, $out)
851851
}
852852
break;
853853

854+
case Block::T_NESTED_PROPERTY:
855+
list(, $prop) = $child;
856+
857+
$prefixed = array();
858+
$prefix = $this->compileValue($prop->prefix) . '-';
859+
860+
foreach ($prop->children as $child) {
861+
if ($child[0] == 'assign') {
862+
array_unshift($child[1][2], $prefix);
863+
}
864+
865+
if ($child[0] == 'nestedprop') {
866+
array_unshift($child[1]->prefix[2], $prefix);
867+
}
868+
869+
$prefixed[] = $child;
870+
}
871+
872+
$this->compileChildren($prefixed, $out);
873+
break;
874+
854875
case Block::T_IF:
855876
list(, $if) = $child;
856877

@@ -887,7 +908,13 @@ protected function compileChild($child, $out)
887908
$this->popEnv();
888909

889910
if ($ret) {
890-
return $ret;
911+
if ($ret[0] != 'control') {
912+
return $ret;
913+
}
914+
915+
if ($ret[1]) {
916+
break;
917+
}
891918
}
892919
}
893920
break;
@@ -899,7 +926,13 @@ protected function compileChild($child, $out)
899926
$ret = $this->compileChildren($while->children, $out);
900927

901928
if ($ret) {
902-
return $ret;
929+
if ($ret[0] != 'control') {
930+
return $ret;
931+
}
932+
933+
if ($ret[1]) {
934+
break;
935+
}
903936
}
904937
}
905938
break;
@@ -926,32 +959,26 @@ protected function compileChild($child, $out)
926959
$ret = $this->compileChildren($for->children, $out);
927960

928961
if ($ret) {
929-
return $ret;
962+
if ($ret[0] != 'control') {
963+
return $ret;
964+
}
965+
966+
if ($ret[1]) {
967+
break;
968+
}
930969
}
931970
}
932971

933972
break;
934973

935-
case Block::T_NESTED_PROPERTY:
936-
list(, $prop) = $child;
937-
938-
$prefixed = array();
939-
$prefix = $this->compileValue($prop->prefix) . '-';
974+
case Node::T_BREAK:
975+
return array(Node::T_CONTROL, true);
940976

941-
foreach ($prop->children as $child) {
942-
if ($child[0] == 'assign') {
943-
array_unshift($child[1][2], $prefix);
944-
}
977+
case Node::T_CONTINUE:
978+
return array(Node::T_CONTROL, false);
945979

946-
if ($child[0] == 'nestedprop') {
947-
array_unshift($child[1]->prefix[2], $prefix);
948-
}
949-
950-
$prefixed[] = $child;
951-
}
952-
953-
$this->compileChildren($prefixed, $out);
954-
break;
980+
case Node::T_RETURN:
981+
return $this->reduce($child[1], true);
955982

956983
case Node::T_CHARSET:
957984
if (! $this->charsetSeen) {
@@ -1037,9 +1064,6 @@ protected function compileChild($child, $out)
10371064
}
10381065
break;
10391066

1040-
case Node::T_RETURN:
1041-
return $this->reduce($child[1], true);
1042-
10431067
case Node::T_INCLUDE:
10441068
// including a mixin
10451069
list(, $name, $argValues, $content) = $child;
@@ -1128,6 +1152,9 @@ protected function compileChild($child, $out)
11281152
$this->throwError("Line $line ERROR: $value\n");
11291153
break;
11301154

1155+
case Node::T_CONTROL:
1156+
$this->throwError('@break/@continue not permitted in this scope');
1157+
11311158
default:
11321159
$this->throwError('Unknown child type: %s', $child[0]);
11331160
}

src/Node.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,9 @@ abstract class Node
5858
const T_SELF = 'self';
5959
const T_BLOCK = 'block';
6060
const T_HSL = 'hsl';
61+
const T_CONTROL = 'control';
62+
const T_BREAK = 'break';
63+
const T_CONTINUE = 'continue';
6164

6265
/**
6366
* @var string

src/Parser.php

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,8 +385,28 @@ protected function parseChunk()
385385

386386
$this->seek($s);
387387

388-
if ($this->literal('@return') && $this->valueList($retVal) && $this->end()) {
389-
$this->append(array('return', $retVal), $s);
388+
// SCSSPHP feature
389+
if ($this->literal('@break') && $this->end()) {
390+
$this->append(array(Node::T_BREAK), $s);
391+
392+
return true;
393+
}
394+
395+
$this->seek($s);
396+
397+
// SCSSPHP feature
398+
if ($this->literal('@continue') && $this->end()) {
399+
$this->append(array(Node::T_CONTINUE), $s);
400+
401+
return true;
402+
}
403+
404+
$this->seek($s);
405+
406+
407+
// SCSSPHP feature: optional return value
408+
if ($this->literal('@return') && ($this->valueList($retVal) || true) && $this->end()) {
409+
$this->append(array('return', isset($retVal) ? $retVal : array('null')), $s);
390410

391411
return true;
392412
}

tests/inputs/looping.scss

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,3 +84,66 @@ div {
8484
c: is-number("3");
8585
c: is-number(5);
8686
}
87+
88+
body.each {
89+
@each $x in 1 2 3 4 5 {
90+
@if $x == 2 or $x == 4 {
91+
background-color: $x;
92+
@continue;
93+
}
94+
95+
color: $x;
96+
97+
@if $x == 5 {
98+
@break;
99+
}
100+
@else {
101+
@continue;
102+
}
103+
104+
color: "not reached";
105+
}
106+
}
107+
108+
body.for {
109+
@for $x from 1 through 5 {
110+
@if $x == 2 or $x == 4 {
111+
background-color: $x;
112+
@continue;
113+
}
114+
115+
color: $x;
116+
117+
@if $x == 5 {
118+
@break;
119+
}
120+
@else {
121+
@continue;
122+
}
123+
124+
color: "not reached";
125+
}
126+
}
127+
128+
body.while {
129+
$x: 0;
130+
@while $x <= 5 {
131+
$x: $x+1;
132+
133+
@if $x == 2 or $x == 4 {
134+
background-color: $x;
135+
@continue;
136+
}
137+
138+
color: $x;
139+
140+
@if $x == 5 {
141+
@break;
142+
}
143+
@else {
144+
@continue;
145+
}
146+
147+
color: "not reached";
148+
}
149+
}

tests/outputs/looping.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,24 @@ div {
6161
b: true;
6262
c: true;
6363
c: true; }
64+
65+
body.each {
66+
color: 1;
67+
background-color: 2;
68+
color: 3;
69+
background-color: 4;
70+
color: 5; }
71+
72+
body.for {
73+
color: 1;
74+
background-color: 2;
75+
color: 3;
76+
background-color: 4;
77+
color: 5; }
78+
79+
body.while {
80+
color: 1;
81+
background-color: 2;
82+
color: 3;
83+
background-color: 4;
84+
color: 5; }

tests/outputs_numbered/looping.css

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,3 +65,24 @@ div {
6565
b: true;
6666
c: true;
6767
c: true; }
68+
/* line 88, inputs/looping.scss */
69+
body.each {
70+
color: 1;
71+
background-color: 2;
72+
color: 3;
73+
background-color: 4;
74+
color: 5; }
75+
/* line 108, inputs/looping.scss */
76+
body.for {
77+
color: 1;
78+
background-color: 2;
79+
color: 3;
80+
background-color: 4;
81+
color: 5; }
82+
/* line 128, inputs/looping.scss */
83+
body.while {
84+
color: 1;
85+
background-color: 2;
86+
color: 3;
87+
background-color: 4;
88+
color: 5; }

0 commit comments

Comments
 (0)