📄 parser.y
字号:
%{
#include "compiler.h"
#include <malloc.h>
void yyerror(char* msg)
{
CtkScanner::instance.error(msg);
}
%}
%union {
CtkToken* tok;
CtkProgram* prog;
CtkTokenList* toks;
CtkStmt* stmt;
CtkExpr* expr;
CtkCaseStmt* cass;
CtkArrayElemExpr* pair;
ctk_integer ival;
ctk_real rval;
char* sval;
}
%token <tok> BREAK
CASE
CATCH
CONTINUE
DEFAULT
DO
ELSE
FOR
FUNCTION
IDENT
IF
IMPORT
NULLLITERAL
PAR
RETURN
THROW
TRY
SYNCHRONIZED
SWITCH
WHILE
','
';'
')'
']'
'{'
'}'
%token <ival> ILITERAL
%token <rval> RLITERAL
%token <sval> SLITERAL
%right <tok> '=' SET_ADD SET_SUB SET_DIV SET_MOD SET_MUL SET_AND SET_OR SET_XOR SET_SHL SET_SHR
%left <tok> '?' ':'
%left <tok> LOR
%left <tok> LAND
%left <tok> '|'
%left <tok> '^'
%left <tok> '&'
%left <tok> EQ NE
%left <tok> '<' LE '>' GE
%left <tok> SHL SHR
%left <tok> '+' '-'
%left <tok> '%' '*' '/'
%right <tok> UPLUS UMINUS '!' '~' '$' INC DEC
%left <tok> '(' '[' '.'
%type <toks> import_list
%type <toks> ident_list
%type <toks> not_empty_ident_list
%type <prog> program
%type <stmt> statements
%type <stmt> stmt
%type <stmt> func_def_stmt
%type <stmt> if_stmt
%type <stmt> for_stmt
%type <stmt> do_while_stmt
%type <stmt> while_stmt
%type <stmt> switch_stmt
%type <stmt> continue_stmt
%type <stmt> break_stmt
%type <stmt> sync_stmt
%type <stmt> return_stmt
%type <stmt> throw_stmt
%type <stmt> try_stmt
%type <stmt> block
%type <stmt> expr_stmt
%type <stmt> empty_stmt
%type <stmt> else_branch
%type <cass> case_node_list;
%type <cass> case_node;
%type <expr> expr
%type <expr> opt_expr
%type <expr> unary_expr
%type <expr> literal
%type <expr> expr_list
%type <expr> not_empty_expr_list
%type <pair> array_initializer_list
%type <pair> not_empty_array_initializer_list
%type <pair> array_initializer
%start program
%%
program: import_list statements {
$$ = new CtkProgram($1, $2);
CtkCompiler::instance.program = $$;
}
import_list: { $$ = NULL; } | IMPORT ident_list ';' { $$ = $2; }
statements: { $$ = NULL; } | stmt statements { $1->next = $2; $$ = $1; }
stmt: func_def_stmt | if_stmt | for_stmt | do_while_stmt | while_stmt
| switch_stmt | continue_stmt | break_stmt | sync_stmt
| return_stmt | throw_stmt | try_stmt | block | expr_stmt | empty_stmt
func_def_stmt: FUNCTION IDENT '(' ident_list ')' block {
$$ = new CtkFuncDef($2, $4, $6);
}
ident_list: { $$ = NULL; } | not_empty_ident_list
not_empty_ident_list: IDENT { $$ = new CtkTokenList($1, NULL); }
| IDENT ',' not_empty_ident_list { $$ = new CtkTokenList($1, $3); }
if_stmt: IF '(' expr ')' stmt else_branch {
$$ = new CtkIfStmt($3, $5, $6);
}
else_branch: { $$ = NULL; } | ELSE stmt { $$ = $2; }
for_stmt: FOR '(' opt_expr ';' opt_expr ';' opt_expr ')' stmt {
$$ = new CtkForStmt($3, $5, $7, $9);
}
opt_expr: { $$ = NULL; } | expr
do_while_stmt: DO stmt WHILE '(' expr ')' ';' {
$$ = new CtkDoWhileStmt($2, $5);
}
while_stmt: WHILE '(' expr ')' stmt {
$$ = new CtkWhileStmt($3, $5);
}
switch_stmt: SWITCH '(' expr ')' '{' case_node_list '}' {
$$ = new CtkSwitchStmt($3, $6);
}
case_node_list: { $$ = NULL; } | case_node case_node_list { $1->next = $2; $$ = $1; }
case_node: CASE expr ':' stmt {
$$ = new CtkCaseStmt($2, $4);
}
| DEFAULT ':' stmt {
$$ = new CtkCaseStmt(NULL, $3);
}
continue_stmt: CONTINUE ';' {
$$ = new CtkContinueStmt();
}
break_stmt: BREAK ';' {
$$ = new CtkBreakStmt();
}
return_stmt: RETURN ';' {
$$ = new CtkReturnStmt();
}
| RETURN expr ';' {
$$ = new CtkReturnStmt($2);
}
throw_stmt: THROW expr ';' {
$$ = new CtkThrowStmt($2);
}
try_stmt: TRY stmt CATCH '(' IDENT ')' stmt {
$$ = new CtkTryStmt($2, $5, $7);
};
block: '{' statements '}' { $$ = $2; }
expr_stmt: expr ';' { $$ = new CtkExprStmt($1); }
empty_stmt: ';' { $$ = new CtkEmptyStmt(); }
sync_stmt: SYNCHRONIZED '(' expr ')' stmt {
$$ = new CtkSynchronizedStmt($3, $5);
}
expr: unary_expr
| expr '+' expr { $$ = new CtkAddExpr($1, $3); }
| expr '-' expr { $$ = new CtkSubExpr($1, $3); }
| expr '/' expr { $$ = new CtkDivExpr($1, $3); }
| expr '%' expr { $$ = new CtkModExpr($1, $3); }
| expr '*' expr { $$ = new CtkMulExpr($1, $3); }
| expr '|' expr { $$ = new CtkOrExpr($1, $3); }
| expr '&' expr { $$ = new CtkAndExpr($1, $3); }
| expr '^' expr { $$ = new CtkXorExpr($1, $3); }
| expr SHL expr { $$ = new CtkShlExpr($1, $3); }
| expr SHR expr { $$ = new CtkShrExpr($1, $3); }
| expr EQ expr { $$ = new CtkEqExpr($1, $3); }
| expr NE expr { $$ = new CtkNeExpr($1, $3); }
| expr '>' expr { $$ = new CtkGtExpr($1, $3); }
| expr GE expr { $$ = new CtkGeExpr($1, $3); }
| expr '<' expr { $$ = new CtkLtExpr($1, $3); }
| expr LE expr { $$ = new CtkLeExpr($1, $3); }
| expr LAND expr { $$ = new CtkLandExpr($1, $3); }
| expr LOR expr { $$ = new CtkLorExpr($1, $3); }
| expr '=' expr { $$ = new CtkAssignExpr($1, $3); }
| expr SET_ADD expr { $$ = new CtkSetAddExpr($1, $3); }
| expr SET_SUB expr { $$ = new CtkSetSubExpr($1, $3); }
| expr SET_DIV expr { $$ = new CtkSetDivExpr($1, $3); }
| expr SET_MOD expr { $$ = new CtkSetModExpr($1, $3); }
| expr SET_MUL expr { $$ = new CtkSetMulExpr($1, $3); }
| expr SET_OR expr { $$ = new CtkSetOrExpr($1, $3); }
| expr SET_XOR expr { $$ = new CtkSetXorExpr($1, $3); }
| expr SET_AND expr { $$ = new CtkSetAndExpr($1, $3); }
| expr SET_SHL expr { $$ = new CtkSetShlExpr($1, $3); }
| expr SET_SHR expr { $$ = new CtkSetShrExpr($1, $3); }
| expr '?' expr ':' expr { $$ = new CtkCondExpr($1, $3, $5); }
| PAR unary_expr '(' expr_list ')' { $$ = new CtkRunThreadExpr($2, $4); }
unary_expr: IDENT { $$ = new CtkVariable($1); }
| literal
| '(' expr ')' { $$ = $2; }
| '+' unary_expr %prec UPLUS { $$ = $2; }
| '-' unary_expr %prec UMINUS { $$ = new CtkNegExpr($2); }
| DEC unary_expr { $$ = new CtkPreDecExpr($2); }
| INC unary_expr { $$ = new CtkPreIncExpr($2); }
| unary_expr DEC { $$ = new CtkPostDecExpr($1); }
| unary_expr INC { $$ = new CtkPostIncExpr($1); }
| '!' unary_expr { $$ = new CtkNotExpr($2); }
| '~' unary_expr { $$ = new CtkComExpr($2); }
| '$' unary_expr { $$ = new CtkEnvExpr($2); }
| '[' array_initializer_list ']' { $$ = new CtkArrayConst($2); }
| unary_expr '(' expr_list ')' { $$ = new CtkFuncCallExpr($1, $3); }
| unary_expr '[' expr ']' { $$ = new CtkArrayAccessExpr($1, $3); }
| unary_expr '.' IDENT { $$ = new CtkArrayAccessExpr($1, new CtkStringConst(ctkAllocateStringLiteral($3->name))); }
array_initializer_list: { $$ = NULL; } | not_empty_array_initializer_list
not_empty_array_initializer_list: array_initializer
| array_initializer ',' array_initializer_list { $1->next = $3; $$ = $1; }
array_initializer: expr ':' expr { $$ = new CtkArrayElemExpr($1, $3); }
| expr { $$ = new CtkArrayElemExpr(NULL, $1); }
literal: SLITERAL { $$ = new CtkStringConst($1); }
| ILITERAL { $$ = new CtkIntConst($1); }
| RLITERAL { $$ = new CtkRealConst($1); }
| NULLLITERAL { $$ = new CtkNullConst(); }
expr_list: { $$ = NULL; } | not_empty_expr_list
not_empty_expr_list: expr
| expr ',' not_empty_expr_list { $1->next = $3; $$ = $1; }
%%
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -