Closed huanghantao closed 1 year ago
Hi
I reproduced a simple calculator with %prec UMINUS
and it works well.
%define api.parser.class {Parser}
%token T_NUMBER
%left '-' '+'
%left UMINUS
%%
start:
expression { printf("%d\n", $1); }
;
expression:
T_NUMBER { $$ = $1; }
| expression '+' expression { $$ = $1 + $3; }
| expression '-' expression { $$ = $1 - $3; }
| '-' expression %prec UMINUS { $$ = -$2; }
;
%%
class Lexer implements LexerInterface {
private array $words;
private int $index = 0;
private int $value = 0;
public function __construct($resource)
{
$this->words = explode(' ', trim(fgets($resource)));
}
public function yyerror(string $message): void
{
printf("%s\n", $message);
}
public function reportSyntaxError(Context $ctx): void
{
$this->yyerror('syntax error');
}
public function getLVal()
{
return $this->value;
}
public function yylex(): int
{
if ($this->index >= count($this->words)) {
return LexerInterface::YYEOF;
}
$word = $this->words[$this->index++];
if (is_numeric($word)) {
$this->value = (int)$word;
return LexerInterface::T_NUMBER;
}
return ord($word);
}
}
$lexer = new Lexer(STDIN);
$parser = new Parser($lexer);
if (!$parser->parse()) {
exit(1);
}
bison -S ../../src/php-skel.m4 -o parser.php grammar.y
php parser.php <<< "1 + - 2"
-1
Feel free to ask questions here https://stackoverflow.com/search?q=bison+BNF as these warnings are unrelated to the php-bison-skeleton
template.
You can suppress warnings:
%expect 2
Thank you! This was my problem and the conflict was resolved when I added semi to the statement:
%define api.parser.class {GeneratedParser}
%define api.namespace {App\Infrastructure\Core\Component\FormulaParser}
%code parser {
private array $stmts = [];
public function setStmts(array $stmts): void { $this->stmts = $stmts; }
public function getStmts(): array { return $this->stmts; }
}
%nonassoc T_IS_EQUAL T_IS_NOT_EQUAL
%left T_BOOLEAN_OR
%left T_BOOLEAN_AND
%nonassoc '<' T_IS_SMALLER_OR_EQUAL '>' T_IS_GREATER_OR_EQUAL
%left '&'
%left '+' '-'
%left '*' '/'
%left '(' ')'
%token T_COLUMN_ID
%token T_SHEET_ID
%token T_LABEL
%token T_LNUMBER
%token T_STRING
%token T_IS_EQUAL "'='"
%token T_IS_NOT_EQUAL "'!='"
%token T_IS_SMALLER_OR_EQUAL "'<='"
%token T_IS_GREATER_OR_EQUAL "'>='"
%token T_BOOLEAN_OR "'||'"
%token T_BOOLEAN_AND "'&&'"
%%
start:
top_statement_list {
self::setStmts($1);
}
;
top_statement_list:
top_statement_list statement {
$$[] = $2;
}
| %empty { $$ = []; }
;
statement:
expr semi {
$$ = new Node\Stmt\Expression($1);
}
;
expr:
expr '+' expr {
$$ = new Node\Expr\BinaryOp\Plus($1, $3);
}
| expr '-' expr {
$$ = new Node\Expr\BinaryOp\Minus($1, $3);
}
| '-' expr {
$$ = new Node\Expr\UnaryMinus($2);
}
;
semi:
';' {
$$ = $1;
}
;
I'm implementing a negative number,the complete syntax is as follows:
and output:
It seems that
%prec UMINUS
is not effective.Relevant environment: