Closed thekid closed 3 years ago
This is in the AST library, inside the following block:
// This is ambiguous:
//
// - An expression surrounded by parentheses `($a ?? $b)->invoke()`;
// - A cast `(int)$a` or `(int)($a / 2)`.
//
// Resolve by looking ahead after the closing ")"
$this->prefix('(', 0, function($parse, $token) {
...
});
This fixes is but isn't satisfactory:
--- a/src/main/php/lang/ast/syntax/PHP.class.php
+++ b/src/main/php/lang/ast/syntax/PHP.class.php
@@ -222,7 +222,6 @@ class PHP extends Language {
// This is ambiguous:
//
- // - An arrow function `($a) ==> $a + 1`
// - An expression surrounded by parentheses `($a ?? $b)->invoke()`;
// - A cast `(int)$a` or `(int)($a / 2)`.
//
@@ -262,7 +261,14 @@ class PHP extends Language {
$parse->forward();
$parse->expecting('(', 'braced');
$expr= $this->expression($parse, 0);
- $parse->expecting(')', 'braced');
+
+ // See https://github.com/xp-framework/compiler/issues/98, unsure why we are
+ // short one ')' in this case though.
+ if (';' === $parse->token->value) {
+ $parse->queue= [$parse->token];
+ } else {
+ $parse->expecting(')', 'braced');
+ }
return new Braced($expr, $token->line);
}
});
Fix released in https://github.com/xp-framework/ast/releases/tag/v7.0.1 after this happened last night:
Oops, this fix wasn't the right one after all!
public function run() {
$e= STDOUT;
return false !== (fstat($e));
}
0: [lang.ast.Token(kind= operator, value= "("), lang.ast.Token(kind= name, value= "fstat")]
// 1: [`(`, `fstat`, `(`, `$e`, `)`, `)`, `;`]
// Q: [lang.ast.Token(kind= operator, value= ";")]
// T: lang.ast.Token(kind= operator, value= ")")
// E: lang.ast.nodes.InvokeExpression {
// kind => "invoke"
// expression => lang.ast.nodes.Literal {
// kind => "literal"
// expression => "fstat"
// line => 4
// }
// arguments => [lang.ast.nodes.Variable {
// kind => "variable"
// name => "e"
// line => 4
// }]
// line => 4
// }
public function run() {
return false !== (fstat(STDOUT));
}
// 0: [lang.ast.Token(kind= operator, value= "("), lang.ast.Token(kind= name, value= "fstat")]
// 1: [`(`, `fstat`, `(`, `STDOUT`, `)`, `)`, `;`]
// Q: [lang.ast.Token(kind= operator, value= ")")]
// T: lang.ast.Token(kind= operator, value= ";")
// E: lang.ast.nodes.InvokeExpression {
// kind => "invoke"
// expression => lang.ast.nodes.Literal {
// kind => "literal"
// expression => "fstat"
// line => 4
// }
// arguments => [lang.ast.nodes.Literal {
// kind => "literal"
// expression => "STDOUT"
// line => 4
// }]
// line => 4
// }
This points us to the fact that the above fix wasn't the correct place after all, the look-ahead code is working perfectly, somehow the argument parser is incorrect, though!
Really fixed by https://github.com/xp-framework/ast/releases/tag/v7.0.1 - unittest included in XP Compiler, v6.1.0
Exception lang.ast.Errors (Errors { Expected ")", have ";" in braced at line 3, Missing semicolon after operator statement at line 3})