%{ /* * Copyright (C) 2000-Thu 25 Jun 09:36:43 AEST 2020 * Department of Computer Science and Electrical Engineering, * The University of Queensland */ #include #include #include #include #include "asm_objects.h" #include "asm_string_table.cc" #include "code.h" #include "code_block.h" #include "errors.h" #include "indexing.h" const char *Program = "qa"; extern "C" int yylex(); int yyerror(const char *); ASMStringTable *asm_string_table = NULL; CodeBlock *query_code_block = NULL; vector *predicate_code_blocks = NULL; CodeBlock *code_block = NULL; LabelTable *labels = NULL; %} %union { qint64 int_value; double double_value; string *label_name; string *atom_name; string *string_value; ASMLoc loc; ASMInt *instruction; ASMInt *constant; ASMDouble *double_num; ASMInt *int_num; ASMInt *reg; ASMInt *number; ASMInt *address; ASMInt *offset; ASMInt *pred; ASMInt *table_size; vector *cl_list; ConstantLabel *cl; vector *aal_list; AtomArityLabel *aal; } %token put_x_variable %token put_y_variable %token put_x_value %token put_y_value %token put_constant %token put_integer %token put_double %token put_string %token put_list %token put_structure %token put_x_object_variable %token put_y_object_variable %token put_x_object_value %token put_y_object_value %token put_quantifier check_binder %token put_substitution %token put_x_term_substitution %token put_y_term_substitution %token put_initial_empty_substitution %token get_x_variable %token get_y_variable %token get_x_value %token get_y_value %token get_constant %token get_integer %token get_double %token get_string %token get_list %token get_structure %token get_structure_frame %token get_x_object_variable %token get_y_object_variable %token get_x_object_value %token get_y_object_value %token unify_x_variable %token unify_y_variable %token unify_x_value %token unify_y_value %token unify_void %token unify_constant %token unify_integer %token unify_double %token unify_string %token unify_x_ref %token unify_y_ref %token set_x_variable %token set_y_variable %token set_x_value %token set_y_value %token set_x_object_variable %token set_y_object_variable %token set_x_object_value %token set_y_object_value %token set_constant %token set_integer %token set_double %token set_string %token set_void %token set_object_void %token wam_allocate %token wam_deallocate %token call_predicate %token call_address %token call_escape %token execute_predicate %token execute_address %token execute_escape %token noop %token jump %token proceed %token wam_fail %token halt %token wam_exit %token try_me_else %token retry_me_else %token trust_me_else_fail %token wam_try %token retry %token trust %token neck_cut %token get_x_level %token get_y_level %token cut %token switch_on_term %token switch_on_constant %token switch_on_structure %token switch_on_quantifier %token pseudo_instr0 %token pseudo_instr1 %token pseudo_instr2 %token pseudo_instr3 %token pseudo_instr4 %token pseudo_instr5 %type constant_labels %type constant_label_list %type constant_label %type atom_arity_labels %type atom_arity_label_list %type atom_arity_label %type quantifier_labels %type quantifier_label_list %type quantifier_label %type switch_label %type atom %type
address %type constant %type double_num %type int_num %type number %type reg %type table_size %token INTEGER_TOKEN %token DOUBLE_TOKEN %token STRING_TOKEN %token ATOM_TOKEN %token LABEL_TOKEN %token END_TOKEN %start assembler_file %% assembler_file: predicate_list ; predicate_list: /* empty */ | predicate_list predicate ; predicate: predicate_start source_line_list predicate_end ; predicate_start: atom '/' number ':' { labels = new LabelTable; // Is it the query code block? if ((*asm_string_table)[$1->Value()] == "$query" && $3->Value() == 0) { if (query_code_block != NULL) { Fatal(__FUNCTION__, "more than one query code block"); } query_code_block = new CodeBlock(QUERY_BLOCK, $1->Value(), $3->Value()); code_block = query_code_block; } else { code_block = new CodeBlock(PREDICATE_BLOCK, $1->Value(), $3->Value()); } delete $1; delete $3; } ; predicate_end: END_TOKEN '(' atom '/' number ')' ':' { if ($3->Value() != code_block->Atom() || (u_int)($5->Value()) != code_block->Arity()) { Fatal(__FUNCTION__, "atom or arity mismatch in predicate"); } delete $3; delete $5; // Resolve all the fail label references labels->ResolveFail(*code_block); if (code_block->Type() == PREDICATE_BLOCK) { predicate_code_blocks->push_back(code_block); } // Make it difficult to reuse the label table delete labels; labels = NULL; } ; source_line_list: /* empty */ | source_line_list source_line ; source_line: label_instance | instr ; label_instance: LABEL_TOKEN ':' { labels->Resolve(*$1, *code_block); } ; instr: put_x_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_y_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_x_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_y_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_constant '(' constant ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_integer '(' int_num ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_double '(' double_num ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_string '(' STRING_TOKEN ',' reg ')' { $1->Put(*code_block); delete $1; $5->Put(*code_block); delete $5; string* buff = $3; for (string::iterator iter = buff->begin(); iter != buff->end(); iter++) code_block->Put(*iter); code_block->Put('\0'); delete $3; } | put_list '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | put_structure '(' number ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_x_object_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_y_object_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_x_object_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_y_object_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_quantifier '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | check_binder '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | put_substitution '(' number ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_x_term_substitution '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_y_term_substitution '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | put_initial_empty_substitution '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | get_x_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_y_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_x_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_y_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_constant '(' constant ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_integer '(' int_num ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_double '(' double_num ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_string '(' STRING_TOKEN ',' reg ')' { $1->Put(*code_block); delete $1; $5->Put(*code_block); delete $5; string* buff = $3; for (string::iterator iter = buff->begin(); iter != buff->end(); iter++) code_block->Put(*iter); code_block->Put('\0'); delete $3; } | get_list '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | get_structure '(' constant ',' number ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; $7->Put(*code_block); delete $7; } | get_structure_frame '(' number ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_x_object_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_y_object_variable '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_x_object_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | get_y_object_value '(' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | unify_x_variable '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_y_variable '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_x_value '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_y_value '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_constant '(' constant ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_integer '(' int_num ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_double '(' double_num ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_string '(' STRING_TOKEN ')' { $1->Put(*code_block); delete $1; string* buff = $3; for (string::iterator iter = buff->begin(); iter != buff->end(); iter++) code_block->Put(*iter); code_block->Put('\0'); delete $3; } | unify_void '(' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_x_ref '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | unify_y_ref '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_x_variable '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_y_variable '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_x_value '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_y_value '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_x_object_variable '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_y_object_variable '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_x_object_value '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_y_object_value '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_constant '(' constant ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_integer '(' int_num ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_double '(' double_num ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_string '(' STRING_TOKEN ')' { $1->Put(*code_block); delete $1; string* buff = $3; for (string::iterator iter = buff->begin(); iter != buff->end(); iter++) code_block->Put(*iter); code_block->Put('\0'); delete $3; } | set_void '(' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | set_object_void '(' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | wam_allocate '(' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | wam_deallocate { $1->Put(*code_block); delete $1; } | call_predicate '(' atom ',' number ',' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; $7->Put(*code_block); delete $7; } | call_address '(' address ',' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | call_escape '(' address ',' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | execute_predicate '(' atom ',' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | execute_address '(' address ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | execute_escape '(' address ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | noop { $1->Put(*code_block); delete $1; } | jump '(' address ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | proceed { $1->Put(*code_block); delete $1; } | wam_fail { $1->Put(*code_block); delete $1; } | halt { $1->Put(*code_block); delete $1; } | wam_exit { $1->Put(*code_block); delete $1; } | try_me_else '(' number ',' LABEL_TOKEN ')' { unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + $3->SizeOf() + Code::SIZE_OF_OFFSET; $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; labels->AddReference(*$5, *code_block, jump_offset_base); } | retry_me_else '(' LABEL_TOKEN ')' { unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + Code::SIZE_OF_OFFSET; $1->Put(*code_block); delete $1; labels->AddReference(*$3, *code_block, jump_offset_base); } | trust_me_else_fail { $1->Put(*code_block); delete $1; } | wam_try '(' number ',' LABEL_TOKEN ')' { unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + $3->SizeOf() + Code::SIZE_OF_OFFSET; $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; labels->AddReference(*$5, *code_block, jump_offset_base); } | retry '(' LABEL_TOKEN ')' { unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + Code::SIZE_OF_OFFSET; $1->Put(*code_block); delete $1; labels->AddReference(*$3, *code_block, jump_offset_base); } | trust '(' LABEL_TOKEN ')' { unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + Code::SIZE_OF_OFFSET; $1->Put(*code_block); delete $1; labels->AddReference(*$3, *code_block, jump_offset_base); } | neck_cut { $1->Put(*code_block); delete $1; } | get_x_level '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | get_y_level '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | cut '(' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | switch_on_term '(' reg ',' switch_label ',' switch_label ',' switch_label ',' switch_label ',' switch_label ',' switch_label ')' { // Calculate the pc value from which jumps will be offset unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + $3->SizeOf() + 6 * Code::SIZE_OF_OFFSET; $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; labels->AddReference(*$5, *code_block, jump_offset_base); labels->AddReference(*$7, *code_block, jump_offset_base); labels->AddReference(*$9, *code_block, jump_offset_base); labels->AddReference(*$11, *code_block, jump_offset_base); labels->AddReference(*$13, *code_block, jump_offset_base); labels->AddReference(*$15, *code_block, jump_offset_base); } | switch_on_constant '(' reg ',' table_size ',' '[' ATOM_TOKEN ':' switch_label constant_labels ']' ')' { // Calculate the pc value from which jumps will be offset unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + $3->SizeOf() + $5->SizeOf(); $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); if (*$8 != "$default") { Fatal(__FUNCTION__, "invalid default atom in switch_on_structure"); } ConstantSwitchTable switch_table(jump_offset_base, $5, $10, $11); switch_table.Put(*code_block, *labels); delete $5; delete $10; delete $11; } | switch_on_structure '(' reg ',' table_size ',' '[' ATOM_TOKEN ':' switch_label atom_arity_labels ']' ')' { // Calculate the pc value from which jumps will be offset unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + $3->SizeOf() + $5->SizeOf(); $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); if (*$8 != "$default") { Fatal(__FUNCTION__, "invalid default atom in switch_on_structure"); } AtomSwitchTable switch_table(jump_offset_base, $5, $10, $11); switch_table.Put(*code_block, *labels); delete $5; delete $10; delete $11; } | switch_on_quantifier '(' reg ',' table_size ',' '[' ATOM_TOKEN ':' switch_label quantifier_labels ']' ')' { // Calculate the pc value from which jumps will be offset unsigned jump_offset_base = code_block->Current() + $1->SizeOf() + $3->SizeOf() + $5->SizeOf(); $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); if (*$8 != "$default") { Fatal(__FUNCTION__, "invalid default atom in switch_on_quantifier"); } AtomSwitchTable switch_table(jump_offset_base, $5, $10, $11); switch_table.Put(*code_block, *labels); delete $5; delete $10; delete $11; } | pseudo_instr0 '(' number ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; } | pseudo_instr1 '(' number ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; } | pseudo_instr2 '(' number ',' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; $7->Put(*code_block); delete $7; } | pseudo_instr3 '(' number ',' reg ',' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; $7->Put(*code_block); delete $7; $9->Put(*code_block); delete $9; } | pseudo_instr4 '(' number ',' reg ',' reg ',' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; $7->Put(*code_block); delete $7; $9->Put(*code_block); delete $9; $11->Put(*code_block); delete $11; } | pseudo_instr5 '(' number ',' reg ',' reg ',' reg ',' reg ',' reg ')' { $1->Put(*code_block); delete $1; $3->Put(*code_block); delete $3; $5->Put(*code_block); delete $5; $7->Put(*code_block); delete $7; $9->Put(*code_block); delete $9; $11->Put(*code_block); delete $11; $13->Put(*code_block); delete $13; } ; constant_labels: { $$ = NULL; } | ',' constant_label_list { $$ = $2; } ; constant_label_list: constant_label { vector *tmp = new vector; tmp->push_back($1); $$ = tmp; } | constant_label_list ',' constant_label { $1->push_back($3); $$ = $1; } ; constant_label: constant ':' switch_label { $$ = new ConstantLabel($1, $3); } ; atom_arity_labels: { $$ = NULL; } | ',' atom_arity_label_list { $$ = $2; } ; atom_arity_label_list: atom_arity_label { vector *tmp = new vector; tmp->push_back($1); $$ = tmp; } | atom_arity_label_list ',' atom_arity_label { $1->push_back($3); $$ = $1; } ; atom_arity_label: ATOM_TOKEN '/' number ':' switch_label { ASMStringPointer asm_atom($1); const ASMLoc loc = asm_string_table->lookup(asm_atom); ASMInt *atom = new ASMInt(loc, ConstEntry::ATOM_TYPE); qint64 arity = $3->Value(); ASMInt *carity = new ASMInt(arity); $$ = new AtomArityLabel(atom, carity, $5); } ; quantifier_labels: { $$ = NULL; } | ',' quantifier_label_list { $$ = $2; } ; quantifier_label_list: quantifier_label { vector *tmp = new vector; tmp->push_back($1); $$ = tmp; } | quantifier_label_list ',' quantifier_label { $1->push_back($3); $$ = $1; } ; quantifier_label: ATOM_TOKEN '/' number ':' switch_label { ASMStringPointer asm_atom($1); const ASMLoc loc = asm_string_table->lookup(asm_atom); ASMInt *atom = new ASMInt(loc, ConstEntry::ATOM_TYPE); qint64 arity = $3->Value(); ASMInt *carity = new ASMInt(arity); $$ = new AtomArityLabel(atom, carity, $5); } ; switch_label: LABEL_TOKEN | ATOM_TOKEN { if (*$1 != "fail") { FatalS(__FUNCTION__, "invalid switch label ", $1->c_str()); } } ; constant: ATOM_TOKEN { ASMStringPointer asm_atom($1); const ASMLoc loc = asm_string_table->lookup(asm_atom); $$ = new ASMInt(loc, ConstEntry::ATOM_TYPE); } | INTEGER_TOKEN { $$ = new ASMInt((Code::ConstantSizedType)($1), ConstEntry::INTEGER_TYPE); } | '+' INTEGER_TOKEN { $$ = new ASMInt((Code::ConstantSizedType)($2), ConstEntry::INTEGER_TYPE); } | '-' INTEGER_TOKEN { $$ = new ASMInt((Code::ConstantSizedType)(-$2), ConstEntry::INTEGER_TYPE); } ; number: INTEGER_TOKEN { $$ = new ASMInt($1); } ; int_num: INTEGER_TOKEN { $$ = new ASMInt((qint64)($1), ConstEntry::INTEGER_TYPE); } | '+' INTEGER_TOKEN { $$ = new ASMInt((qint64)($2), ConstEntry::INTEGER_TYPE); } | '-' INTEGER_TOKEN { $$ = new ASMInt(-(qint64)($2), ConstEntry::INTEGER_TYPE); } ; double_num: DOUBLE_TOKEN { $$ = new ASMDouble((double)($1), ConstEntry::INTEGER_TYPE); } | '+' DOUBLE_TOKEN { $$ = new ASMDouble((double)($2), ConstEntry::INTEGER_TYPE); } | '-' DOUBLE_TOKEN { $$ = new ASMDouble((double)(-$2), ConstEntry::INTEGER_TYPE); } ; reg: INTEGER_TOKEN { $$ = new ASMInt($1); } ; address: INTEGER_TOKEN { $$ = new ASMInt($1); } ; atom: ATOM_TOKEN { ASMStringPointer asm_atom($1); const ASMLoc loc = asm_string_table->lookup(asm_atom); $$ = new ASMInt(loc); } ; table_size: INTEGER_TOKEN { $$ = new ASMInt($1); } ; %% #include "lexer.cc" #include #include "qa_options.h" QaOptions *qa_options = NULL; int main(int argc, char **argv) { qa_options = new QaOptions(argc, argv); if (!qa_options->Valid()) { Usage(Program, qa_options->Usage()); } if (streq(qa_options->InputFile(), qa_options->OutputFile())) { Fatal(__FUNCTION__, "Input and output file names are identical"); } // Should also check for suspect extensions .qg, .qi, .qs, .ql, .qx asm_string_table = new ASMStringTable; predicate_code_blocks = new vector; // Read in the assembler source yyin = fopen(qa_options->InputFile(), "r"); if (yyin == NULL) { perror(__FUNCTION__); exit(EXIT_FAILURE); } int result = yyparse(); if (result) { Fatal(__FUNCTION__, "bad .qs input file"); } fclose(yyin); // Write out the assembled object // First check if any compiled predicates are too big - i.e. >= 2^16 for (vector::iterator iter = predicate_code_blocks->begin(); iter != predicate_code_blocks->end(); iter++) { if ((*iter)->Current() >= (1 << (8*sizeof(Code::OffsetSizedType)))) { Fatal(__FUNCTION__, "Compiled predicate is too big"); } } #ifdef WIN32 ofstream ostrm(qa_options->OutputFile(), ios_base::binary); #else ofstream ostrm(qa_options->OutputFile()); #endif asm_string_table->save(ostrm); if (query_code_block) { query_code_block->Save(ostrm); } else { IntSave(ostrm, 0); } for (vector::iterator iter = predicate_code_blocks->begin(); iter != predicate_code_blocks->end(); iter++) { (*iter)->Save(ostrm); } ostrm.close(); exit(EXIT_SUCCESS); } int yyerror(const char *s) { Fatal(__FUNCTION__, s); return(1); }