trick/trick_source/sim_services/MemoryManager/adef_parser.y
jmpenn 9438bd559b
Add unittests to cover uncovered code in MemoryManager ADEF_ and REF_… (#1483)
* Add unittests to cover uncovered code in MemoryManager ADEF_ and REF_ parsers.

* Remove the second production of the 'user_defined_type' target
because it is superfluous, and impossible to reach. This is
because the NAME token is defined as pattern : '[_a-zA-Z][_a-zA-Z0-9:]*'.
This pattern will always match a string of colon separated names.
Note that the NAME itoken is used for colon separated type-name as well as
colon separated variable names.

* Add a test to MM_declare_var_unittest that covers the HEX token in adef_parser.l.

* Add a unittest for MemoryManager_JSON_Intf.cpp.

* Tweak MM_JSON_Intf.cc to get better code-coverage.
2023-04-27 14:57:55 -05:00

134 lines
3.3 KiB
Plaintext

%name-prefix="ADEF_"
%pure-parser
%locations
%parse-param {Trick::ADefParseContext* context}
%lex-param { void* scanner }
%{
/*
%debug
%error-verbose
*/
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include "trick/vval.h"
#include "trick/value.h"
#include "trick/var.h"
#include "trick/ADefParseContext.hh"
#include "adef_parser.tab.hpp"
#pragma GCC diagnostic ignored "-Wunused-parameter"
using namespace std;
int ADEF_lex( YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner );
void ADEF_error( YYLTYPE* locp, Trick::ADefParseContext* context, const char* err) {
std::stringstream message;
message << "adef_parser PARSE-ERROR " << locp->first_line << ": " << err << ".";
Trick::MemoryManager::emitError(message.str());
}
#define scanner context->scanner
#ifdef YYDEBUG
#undef YYDEBUG
#endif
#define YYDEBUG 1
%}
%start alloc_definition
%union {
char* sval ;
int ival ;
VALUE_LIST* value_list ;
}
%token <sval> NAME
%token <ival> TYPE
%token <ival> I_CON
%token END 0 "End of file"
%type <value_list> dim_list
%type <ival> pointers
%type <sval> opt_name user_type_name
%%
alloc_definition: TYPE pointers opt_name dim_list {
context->type = (TRICK_TYPE)$1;
context->user_type_name = "";
context->n_stars = $2;
if ($3 == NULL) {
context->var_name = "";
} else {
context->var_name = $3;
free($3) ;
}
}
| user_type_name pointers opt_name dim_list {
// TRICK_OPAQUE_TYPE means that the type is a user-defined type,
// the details of which will be determined later.
context->type = TRICK_OPAQUE_TYPE;
context->user_type_name = $1;
free($1) ;
context->n_stars = $2;
if ($3 == NULL) {
context->var_name = "";
} else {
context->var_name = $3;
free($3) ;
}
}
;
opt_name: { $$ = NULL; }
| NAME { $$ = $1; }
;
pointers: {
/*
* pointers counts how many pointer dims there are in a variable declaration
* the first rule handles no pointers, the next handles 1 or more pointers
*/
$$ = 0 ;
}
| pointers '*' {
$$++ ;
}
;
user_type_name: NAME {
$$ = $1;
};
dim_list: {
/*
* These two rules handle C style array indexing. This rule
* handles no indexes, the second rule handles one or more other
* indexes.
*/
int ii ;
context->n_cdims = 0;
for ( ii = 0 ; ii < TRICK_MAX_INDEX ; ii++ ) {
context->cdims[ii] = 0;
}
}
| dim_list '[' I_CON ']' {
if (context->n_cdims >= TRICK_MAX_INDEX ) {
context->error_str = "Too many array dimensions." ;
return(MM_TOO_MANY_ARRAY_DIMENSIONS) ;
}
context->cdims[ context->n_cdims ] = $3 ;
context->n_cdims++;
};
%%