Skip to content

Commit ee68887

Browse files
committed
feature symfony#19013 [ExpressionLanguage] Added a way to dump the AST (lyrixx)
This PR was merged into the 3.2-dev branch. Discussion ---------- [ExpressionLanguage] Added a way to dump the AST | Q | A | ------------- | --- | Branch? | master | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | | License | MIT | Doc PR | Because it's convenient and it makes easier to inline results of sub/smaller part of the main expression. Commits ------- 87af6e5 [ExpressionLanguage] Added a way to dump AST
2 parents 1dcc86d + 87af6e5 commit ee68887

21 files changed

+306
-0
lines changed

src/Symfony/Component/ExpressionLanguage/Node/ArgumentsNode.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,15 @@ public function compile(Compiler $compiler)
2424
{
2525
$this->compileArguments($compiler, false);
2626
}
27+
28+
public function dump()
29+
{
30+
$str = '';
31+
32+
foreach ($this->getKeyValuePairs() as $pair) {
33+
$str .= sprintf('%s, ', $pair['value']->dump());
34+
}
35+
36+
return rtrim($str, ', ');
37+
}
2738
}

src/Symfony/Component/ExpressionLanguage/Node/ArrayNode.php

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,36 @@ public function evaluate($functions, $values)
5858
return $result;
5959
}
6060

61+
public function dump()
62+
{
63+
$array = array();
64+
foreach ($this->getKeyValuePairs() as $pair) {
65+
$array[$pair['key']->attributes['value']] = $pair['value']->dump();
66+
}
67+
68+
if ($this->isHash($array)) {
69+
$str = '{';
70+
71+
foreach ($array as $key => $value) {
72+
if (is_int($key)) {
73+
$str .= sprintf('%s: %s, ', $key, $value);
74+
} else {
75+
$str .= sprintf('"%s": %s, ', $this->dumpEscaped($key), $value);
76+
}
77+
}
78+
79+
return rtrim($str, ', ').'}';
80+
}
81+
82+
$str = '[';
83+
84+
foreach ($array as $key => $value) {
85+
$str .= sprintf('%s, ', $value);
86+
}
87+
88+
return rtrim($str, ', ').']';
89+
}
90+
6191
protected function getKeyValuePairs()
6292
{
6393
$pairs = array();

src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,4 +154,9 @@ public function evaluate($functions, $values)
154154
return preg_match($right, $left);
155155
}
156156
}
157+
158+
public function dump()
159+
{
160+
return sprintf('(%s %s %s)', $this->nodes['left']->dump(), $this->attributes['operator'], $this->nodes['right']->dump());
161+
}
157162
}

src/Symfony/Component/ExpressionLanguage/Node/ConditionalNode.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,9 @@ public function evaluate($functions, $values)
4848

4949
return $this->nodes['expr3']->evaluate($functions, $values);
5050
}
51+
52+
public function dump()
53+
{
54+
return sprintf('(%s ? %s : %s)', $this->nodes['expr1']->dump(), $this->nodes['expr2']->dump(), $this->nodes['expr3']->dump());
55+
}
5156
}

src/Symfony/Component/ExpressionLanguage/Node/ConstantNode.php

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,52 @@ public function evaluate($functions, $values)
3737
{
3838
return $this->attributes['value'];
3939
}
40+
41+
public function dump()
42+
{
43+
return $this->dumpValue($this->attributes['value']);
44+
}
45+
46+
private function dumpValue($value)
47+
{
48+
switch (true) {
49+
case true === $value:
50+
return 'true';
51+
52+
case false === $value:
53+
return 'false';
54+
55+
case null === $value:
56+
return 'null';
57+
58+
case is_numeric($value):
59+
return $value;
60+
61+
case is_array($value):
62+
if ($this->isHash($value)) {
63+
$str = '{';
64+
65+
foreach ($value as $key => $v) {
66+
if (is_int($key)) {
67+
$str .= sprintf('%s: %s, ', $key, $this->dumpValue($v));
68+
} else {
69+
$str .= sprintf('"%s": %s, ', $this->dumpEscaped($key), $this->dumpValue($v));
70+
}
71+
}
72+
73+
return rtrim($str, ', ').'}';
74+
}
75+
76+
$str = '[';
77+
78+
foreach ($value as $key => $v) {
79+
$str .= sprintf('%s, ', $this->dumpValue($v));
80+
}
81+
82+
return rtrim($str, ', ').']';
83+
84+
default:
85+
return sprintf('"%s"', $this->dumpEscaped($value));
86+
}
87+
}
4088
}

src/Symfony/Component/ExpressionLanguage/Node/FunctionNode.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,17 @@ public function evaluate($functions, $values)
4949

5050
return call_user_func_array($functions[$this->attributes['name']]['evaluator'], $arguments);
5151
}
52+
53+
public function dump()
54+
{
55+
$str = $this->attributes['name'];
56+
57+
$str .= '(';
58+
59+
foreach ($this->nodes['arguments']->nodes as $node) {
60+
$str .= $node->dump().', ';
61+
}
62+
63+
return rtrim($str, ', ').')';
64+
}
5265
}

src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,4 +94,18 @@ public function evaluate($functions, $values)
9494
return $array[$this->nodes['attribute']->evaluate($functions, $values)];
9595
}
9696
}
97+
98+
public function dump()
99+
{
100+
switch ($this->attributes['type']) {
101+
case self::PROPERTY_CALL:
102+
return sprintf('%s.%s', $this->nodes['node']->dump(), trim($this->nodes['attribute']->dump(), '"'));
103+
104+
case self::METHOD_CALL:
105+
return sprintf('%s.%s(%s)', $this->nodes['node']->dump(), trim($this->nodes['attribute']->dump(), '"'), $this->nodes['arguments']->dump());
106+
107+
case self::ARRAY_CALL:
108+
return sprintf('%s[%s]', $this->nodes['node']->dump(), $this->nodes['attribute']->dump());
109+
}
110+
}
97111
}

src/Symfony/Component/ExpressionLanguage/Node/NameNode.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,4 +37,9 @@ public function evaluate($functions, $values)
3737
{
3838
return $values[$this->attributes['name']];
3939
}
40+
41+
public function dump()
42+
{
43+
return $this->attributes['name'];
44+
}
4045
}

src/Symfony/Component/ExpressionLanguage/Node/Node.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,27 @@ public function evaluate($functions, $values)
7575

7676
return $results;
7777
}
78+
79+
public function dump()
80+
{
81+
throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', get_class($this)));
82+
}
83+
84+
protected function dumpEscaped($value)
85+
{
86+
return str_replace(array('\\', '"'), array('\\\\', '\"'), $value);
87+
}
88+
89+
protected function isHash(array $value)
90+
{
91+
$expectedKey = 0;
92+
93+
foreach ($value as $key => $val) {
94+
if ($key !== $expectedKey++) {
95+
return true;
96+
}
97+
}
98+
99+
return false;
100+
}
78101
}

src/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,9 @@ public function evaluate($functions, $values)
5858

5959
return $value;
6060
}
61+
62+
public function dump()
63+
{
64+
return sprintf('(%s %s)', $this->attributes['operator'], $this->nodes['node']->dump());
65+
}
6166
}

0 commit comments

Comments
 (0)