Skip to content

Instantly share code, notes, and snippets.

@codebrainz
Last active January 11, 2022 16:25
Show Gist options
  • Save codebrainz/8587a1ddc8e020a71fef to your computer and use it in GitHub Desktop.
Save codebrainz/8587a1ddc8e020a71fef to your computer and use it in GitHub Desktop.
Simple assembly parser in Bison
%{
#include "stdinc.h"
#include "parser.h"
#include "tokens.h"
#include "lexer.h"
static void parser_error(YYLTYPE *locp, struct Parser* par, const char *message);
#define parser_lex(a,b,c) parser_lex(a,b,(c)->scanner)
%}
%locations
%pure-parser
%parse-param { struct Parser *parser }
%lex-param { struct Parser *parser }
%name-prefix "parser_"
%union {
char *str;
ptree_node_t *node;
}
%token <str> T_IDENT T_COMMENT
%token <str> T_HEXLIT T_BINLIT T_OCTLIT T_DECLIT T_FLTLIT T_CHRLIT T_STRLIT
%type <node> primary_expr unary_expr operand operand_list
label mnemonic instruction program_element
%destructor { ptree_node_free($$); } <node>
%destructor { free($$); } <str>
%start program
%%
primary_expr
: T_IDENT { $$ = ptree_ident_new($1, @1.first_line, @1.first_column); free($1); }
| T_HEXLIT { $$ = ptree_intlit_new($1, @1.first_line, @1.first_column); free($1); }
| T_BINLIT { $$ = ptree_intlit_new($1, @1.first_line, @1.first_column); free($1); }
| T_OCTLIT { $$ = ptree_intlit_new($1, @1.first_line, @1.first_column); free($1); }
| T_DECLIT { $$ = ptree_intlit_new($1, @1.first_line, @1.first_column); free($1); }
| T_FLTLIT { $$ = ptree_fltlit_new($1, @1.first_line, @1.first_column); free($1); }
| T_CHRLIT { $$ = ptree_chrlit_new($1, @1.first_line, @1.first_column); free($1); }
| T_STRLIT { $$ = ptree_strlit_new($1, @1.first_line, @1.first_column); free($1); }
| '(' operand ')' { $$ = $2; }
;
unary_expr
: primary_expr { $$ = $1; }
| '+' primary_expr { $$ = ptree_unop_new('+', $2, @1.first_line, @1.first_column); }
| '-' primary_expr { $$ = ptree_unop_new('-', $2, @1.first_line, @1.first_column); }
;
operand
: unary_expr { $$ = $1; }
| unary_expr '+' unary_expr { $$ = ptree_binop_new('+', $1, $3, @1.first_line, @1.first_column); }
| unary_expr '-' unary_expr { $$ = ptree_binop_new('-', $1, $3, @1.first_line, @1.first_column); }
;
operand_list
: operand {
$$ = ptree_root_new();
ptree_node_add_child($$, $1);
}
| operand_list ',' operand {
ptree_node_add_child($$, $3);
}
;
label
: T_IDENT ':' { $$ = ptree_label_new($1, @1.first_line, @1.first_column); free($1); }
;
mnemonic: T_IDENT { $$ = ptree_mnemonic_new($1, @1.first_line, @1.first_column); free($1); }
instruction: mnemonic operand_list
{
$$ = ptree_instruction_new(@1.first_line, @1.first_column);
ptree_node_add_child($$, $1);
ptree_node_t *it = $2->children;
while (it) {
ptree_node_t *next = it->next;
ptree_node_add_child($$, it);
it = next;
}
$2->children = NULL;
ptree_node_free($2);
}
;
program_element
: T_COMMENT { $$ = ptree_comment_new($1, @1.first_line, @1.first_column); free($1); }
| instruction { $$ = $1; }
| label { $$ = $1; }
;
program
: program_element { ptree_node_add_child(parser->root, $1); }
| program program_element { ptree_node_add_child(parser->root, $2); }
;
%%
static void parser_error(YYLTYPE *locp, struct Parser* par, const char *message)
{
fprintf(stderr, "error:%d:%d: %s\n",
locp->first_line, locp->first_column, message);
exit(EXIT_FAILURE);
}
struct Parser* parser_init(struct Parser* par)
{
memset(par, 0, sizeof(struct Parser));
parser_lex_init(&par->scanner);
par->root = ptree_root_new();
return par;
}
void parser_deinit(struct Parser* par)
{
ptree_node_free(par->root);
parser_lex_destroy(par->scanner);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment