📄 fincyacc.y
字号:
%{#include <stdio.h>#include <finctype.h>#include <fincnode.h>#include <finclang.h>#ifndef YYDEBUG#define YYDEBUG 1 /* Default to no yydebug support */#endif%}%union { FinCNode* expr; FinCTypeType type; double val_float; int val_int; char val_string[100]; char identifier[100];}%token IF ELSE RETURN WHILE FOR CONTINUE BREAK%token V_TRUE V_FALSE V_NULL%token IMPORT OPT_PARAM ADDR_OF CONTENT_OF%token VOID CHAR SHORT INT FLOAT DOUBLE POINTER STRING BOOL%token STRUCT NATIVE STATIC UNSIGNED PACKAGE%token PLUS INC SUB DEC ASSIGN EQ NE LE GE%token<identifier> IDENTIFIER%token<val_int> V_INT%token<val_float> V_FLOAT%token<val_string> V_STRING%type<expr> decl%type<expr> decl_global decl_struct decl_local decl_function decl_import%type<expr> decl_variable declarator_list declarator%type<expr> decl_param_list decl_param decl_param_type_list%type<expr> decl_pkg decl_pkg_func_list decl_pkg_func%type<expr> struct_declarator_list struct_declarator decl_field_list decl_field_declarator%type<expr> statement statement_list statement_in_block statement_block statement_node%type<expr> statement_if statement_if_else statement_for statement_return statement_while%type<expr> statement_continue statement_break%type<expr> type identifier literal%type<expr> expr expr_assign expr_logic_or expr_logic_and expr_equality expr_relational expr_additive%type<expr> expr_multiplicative expr_unary expr_postfix expr_primary param_list expr_condition expr_cast%type<type> type_basic type_list;%%/************* * Start */input: /* Nothing */ | input decl;decl: decl_struct { finc_lang_decl_add ($1); } | decl_global { finc_lang_decl_add ($1); } | decl_function { finc_lang_decl_add ($1); } | decl_import { finc_lang_decl_add ($1); } | decl_pkg { finc_lang_decl_add ($1); } | error { finc_lang_error ("Expecting a declaration"); };/**************** * Declarations */decl_global: decl_variable { $$ = finc_lang_efunc_create1("global", $1); };decl_local: decl_variable { $$ = finc_lang_efunc_create1("local", $1); };decl_variable: type declarator_list ';' { $$ = finc_lang_var_create ($1); } | type identifier '[' V_INT ']' { $1->type->array_type = FinCArrayType_Fixed; $1->type->array_size = $4; $$ = finc_lang_array_create($1, $2); } | type identifier '[' ']' { $1->type->array_type = FinCArrayType_Dynamic; $1->type->array_size = 0; $$ = finc_lang_array_create($1, $2); } | type error { $$ = NULL; finc_lang_error ("Missing identifier in variable declaration."); } | type declarator_list error { $$ = NULL; finc_lang_error ("Missing a ';' in variable declaration."); };declarator_list: declarator_list ',' declarator | declarator;declarator: identifier { finc_lang_var_list_add($1); } | identifier ASSIGN expr_assign { finc_lang_var_list_add_init($1, $3); };decl_struct: STRUCT identifier { finc_lang_struct_begin($2); } '{' decl_field_list '}' ';' { $$ = finc_lang_struct_end(); } | STRUCT error { $$ = NULL; finc_lang_error ("Missing identifier in struct declaration."); };decl_field_list: decl_field_declarator | decl_field_list decl_field_declarator;decl_field_declarator: type struct_declarator_list ';' { finc_lang_struct_field_create($1); } | type identifier '[' V_INT ']' { $1->type->array_type = FinCArrayType_Fixed; $1->type->array_size = $4; finc_lang_struct_field_create( finc_lang_array_create($1, $2) ); } | type identifier '[' ']' { $1->type->array_type = FinCArrayType_Dynamic; $1->type->array_size = 0; finc_lang_struct_field_create( finc_lang_array_create($1, $2) ); };struct_declarator_list: struct_declarator_list ',' struct_declarator | struct_declarator;struct_declarator: identifier { finc_lang_struct_field_add($1); };decl_function: type identifier { finc_lang_func_create ($1, $2); } '(' decl_param_type_list ')' statement_block { $$ = finc_lang_func_finish ($7); };decl_param_type_list: decl_param_list | decl_param_list ',' OPT_PARAM { finc_lang_func_opt_param(); };decl_param_list: /* Nothing */ { $$ = NULL; } | decl_param | decl_param_list ',' decl_param;decl_param: type identifier { finc_lang_func_add_param ($1, $2); } | type identifier '[' ']' { $1->type->array_type = FinCArrayType_Dynamic; $1->type->array_size = 0; finc_lang_func_add_param ($1, $2); } | type identifier '[' error { finc_lang_error ("Expecting a ']'\n"); } | type identifier '[' V_INT ']' { $1->type->array_type = FinCArrayType_Fixed; $1->type->array_size = $4; finc_lang_func_add_param ($1, $2); } | type identifier '[' V_INT error { finc_lang_error ("Expecting a ']'\n"); };decl_import: IMPORT V_STRING ';' { $$ = finc_lang_efunc_create1 ("import", finc_lang_data_string_create ($2)); } | IMPORT V_STRING error { $$ = NULL; finc_lang_error ("Missing a ';' in import"); };decl_pkg: PACKAGE V_STRING { finc_lang_pkg_begin($2); } '{' decl_pkg_func_list '}' ';' { $$ = finc_lang_pkg_end(); };decl_pkg_func_list: decl_pkg_func | decl_pkg_func_list decl_pkg_func;decl_pkg_func: type identifier { finc_lang_func_create($1, $2); } '(' decl_param_type_list ')' ';' { $$ = finc_lang_pkg_func_add(); };/***************** * Type */type: type_list { $$ = finc_lang_type_create ($1, FinCArrayType_None, 0); } | identifier { $$ = finc_lang_type_create_name ($1, FinCArrayType_None, 0); };type_list: type_basic { $$ = $1; } | type_list type_basic { $$ = $1 || $2; };type_basic: VOID { $$ = FinCType_Void; } | CHAR { $$ = FinCType_Char; } | SHORT { $$ = FinCType_Short; } | INT { $$ = FinCType_Int; } | STRING { $$ = FinCType_String; } | POINTER { $$ = FinCType_Pointer; } | FLOAT { $$ = FinCType_Float; } | DOUBLE { $$ = FinCType_Double; } | BOOL { $$ = FinCType_Bool; } | STATIC { $$ = FinCType_Static; } | UNSIGNED { $$ = FinCType_Unsigned; } | NATIVE { $$ = FinCType_Native; };identifier: IDENTIFIER { $$ = finc_node_new_name ($1); };literal: V_STRING { $$ = finc_lang_data_string_create ($1); } | V_INT { $$ = finc_lang_data_integer_create ($1); } | V_FLOAT { $$ = finc_lang_data_float_create ($1); } | V_TRUE { $$ = finc_lang_data_bool_create (TRUE); } | V_FALSE { $$ = finc_lang_data_bool_create (FALSE); } | V_NULL { $$ = finc_lang_data_pointer_create (NULL); };/******************* * Expressions */expr: expr_assign { $$ = $1; } | expr ',' expr_assign { $$ = finc_lang_efunc_create2 (",", $1, $3);};expr_assign: expr_condition | expr_unary ASSIGN expr_assign { $$ = finc_lang_efunc_create2 ("=", $1, $3); };expr_condition: expr_logic_or { $$ =$1; } | expr_logic_or '?' expr ':' expr_condition { $$ = finc_lang_efunc_create3("?", $1, $3, $5); };expr_logic_or: expr_logic_and { $$ = $1; } | expr_logic_or '|' '|' expr_logic_and { $$ = finc_lang_efunc_create2 ("||", $1, $4); };expr_logic_and: expr_equality { $$ = $1; } | expr_logic_and '&' '&' expr_equality { $$ = finc_lang_efunc_create2 ("&&", $1, $4); };expr_equality: expr_relational { $$ = $1; } | expr_equality EQ expr_relational { $$ = finc_lang_efunc_create2 ("==", $1, $3); } | expr_equality NE expr_relational { $$ = finc_lang_efunc_create2 ("!=", $1, $3); };expr_relational: expr_additive { $$ = $1; } | expr_relational '<' expr_additive { $$ = finc_lang_efunc_create2 ("<", $1, $3); } | expr_relational '>' expr_additive { $$ = finc_lang_efunc_create2 (">", $1, $3); } | expr_relational LE expr_additive { $$ = finc_lang_efunc_create2 ("<=", $1, $3); } | expr_relational GE expr_additive { $$ = finc_lang_efunc_create2 (">=", $1, $3); };expr_additive: expr_multiplicative { $$ = $1; } | expr_additive SUB expr_multiplicative { $$ = finc_lang_efunc_create2 ("-", $1, $3); } | expr_additive PLUS expr_multiplicative { $$ = finc_lang_efunc_create2 ("+", $1, $3); };expr_multiplicative: expr_cast { $$ = $1; } | expr_multiplicative '*' expr_cast { $$ = finc_lang_efunc_create2 ("*", $1, $3); } | expr_multiplicative '/' expr_cast { $$ = finc_lang_efunc_create2 ("/", $1, $3); };expr_cast: expr_unary { $$ =$1; } | '(' type ')' expr_cast { $$ = finc_lang_efunc_create2 ("cast", $2, $4); };expr_unary: expr_postfix { $$ = $1; } | PLUS expr_cast { $$ = finc_lang_efunc_create1 ("plus", $2); } | SUB expr_cast { $$ = finc_lang_efunc_create1 ("negative", $2); } | ADDR_OF '(' expr_unary ')' { $$ = finc_lang_efunc_create1 ("addr_of", $3); } | CONTENT_OF '(' expr_unary ')' { $$ = finc_lang_efunc_create1 ("content_of", $3)} | ADDR_OF error { $$ = NULL; finc_lang_error("Missing '(' in addrof operator"); yyerrok; } | ADDR_OF '(' error { $$ = NULL; finc_lang_error("addrof is expecting an <expr>"); yyerrok; } | ADDR_OF '(' expr_unary error { $$ = NULL; finc_lang_error("Missing ')' in addrof operator"); yyerrok; } | CONTENT_OF error { $$ = NULL; finc_lang_error("Missing '(' in contentof operator"); yyerrok; } | CONTENT_OF '(' error { $$ = NULL; finc_lang_error("contentof is expecting an <expr>"); yyerrok; } | CONTENT_OF '(' expr_unary error { $$ = NULL; finc_lang_error("Missing ')' in contentof operator"); yyerrok; };expr_postfix: expr_primary { $$ = $1; } | expr_postfix '[' expr ']' { $$ = finc_lang_efunc_create2 ("[]", $1, $3); } | expr_postfix INC { $$ = finc_lang_efunc_create1 ("++", $1);} | expr_postfix DEC { $$ = finc_lang_efunc_create1 ("--", $1);} | expr_postfix '.' identifier { $$ = finc_lang_efunc_create2 (".", $1, $3); } | expr_postfix { finc_lang_call_begin (string_get_str ($1->identifier)); unref ($1); } '(' param_list ')' { $$ = finc_lang_call_end (); };expr_primary: literal { $$ = $1; } | '(' expr ')' { $$ = $2; } | identifier { $$ = $1; };param_list: /*Nothing*/ { $$ = NULL; } | expr_assign { finc_lang_call_add ($1); } | param_list ',' expr_assign { finc_lang_call_add ($3); };/********************* * Statements (CODE) */statement: decl_local { $$ = $1; } | statement_block { $$ = $1; } | statement_node { $$ = $1; } | statement_return { $$ = $1; } | statement_for { $$ = $1; } | statement_while { $$ = $1; } | statement_if { $$ = $1; } | statement_continue { $$ = $1; } | statement_break { $$ = $1; };statement_in_block: decl_local { finc_lang_block_add ($1); } | statement_block { finc_lang_block_add ($1); } | statement_node { finc_lang_block_add ($1); } | statement_return { finc_lang_block_add ($1); } | statement_for { finc_lang_block_add ($1); } | statement_while { finc_lang_block_add ($1); } | statement_if { finc_lang_block_add ($1); };statement_block: '{' { finc_lang_block_begin (); } statement_list '}' { $$ = finc_lang_block_end (); };statement_list: statement_in_block | statement_list statement_in_block;statement_node: ';' { $$ = NULL; } | expr ';' { $$ = $1; }statement_return: RETURN expr ';' { $$ = finc_lang_efunc_create1 ("return", $2); } | RETURN error ';' { $$ = NULL; finc_lang_error ("RETURN is expecting an <expr>"); yyerrok; } | RETURN expr error { $$ = NULL; finc_lang_error ("Missing a ';' in return statement"); yyerrok; };statement_for: FOR '(' statement_node statement_node expr ')' statement { $$ = finc_lang_efunc_create4 ("for", $3, $4, $5, $7); } | FOR '(' expr ';' error { $$ = NULL; finc_lang_error ("FOR is expecting an <expr>"); yyerrok; } | FOR error { $$ = NULL; finc_lang_error ("Missing a '(' in for statement"); yyerrok; };statement_while: WHILE '(' expr ')' statement { $$ = finc_lang_efunc_create2 ("while", $3, $5); } | WHILE '(' error { $$ = NULL; finc_lang_error ("WHILE is expecting an <expr>"); yyerrok; } | WHILE error { $$ = NULL; finc_lang_error ("Missing a '(' in while statement"); yyerrok; };statement_if: IF '(' expr ')' statement statement_if_else { if ($5) $$ = finc_lang_efunc_create2 ("if", $3, $5); else $$ = finc_lang_efunc_create1 ("if", $3); if ($6) { finc_node_add ($$, $6); unref ($6); } } | IF '(' error { $$ = NULL; finc_lang_error ("IF is expecting an <expr>"); yyerrok; } | IF error { $$ = NULL; finc_lang_error ("Missing a '(' in if statement"); yyerrok; };statement_if_else: /*Nothing*/ { $$ = NULL; } | ELSE statement { $$ = $2; };statement_continue: CONTINUE ';' { $$ = finc_lang_efunc_create("continue"); } | CONTINUE error { $$ = NULL; finc_lang_error ("Missing a ';' in continue statement"); yyerrok; };statement_break: BREAK ';' { $$ = finc_lang_efunc_create("break"); } | BREAK error { $$ = NULL; finc_lang_error ("Missing a ';' in break statement"); yyerrok; }%%
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -