497 lines
9.0 KiB
Plaintext
497 lines
9.0 KiB
Plaintext
// Filename: dcParser.yxx
|
|
// Created by: drose (05Oct00)
|
|
//
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
%{
|
|
#include "dcLexerDefs.h"
|
|
#include "dcParserDefs.h"
|
|
#include "dcFile.h"
|
|
#include "dcClass.h"
|
|
#include "dcAtomicField.h"
|
|
#include "dcMolecularField.h"
|
|
#include "dcSimpleType.h"
|
|
#include "dcPacker.h"
|
|
|
|
// Because our token type contains objects of type string, which
|
|
// require correct copy construction (and not simply memcpying), we
|
|
// cannot use bison's built-in auto-stack-grow feature. As an easy
|
|
// solution, we ensure here that we have enough yacc stack to start
|
|
// with, and that it doesn't ever try to grow.
|
|
#define YYINITDEPTH 1000
|
|
#define YYMAXDEPTH 1000
|
|
|
|
static DCFile *dc_file = (DCFile *)NULL;
|
|
static DCClass *current_class = (DCClass *)NULL;
|
|
static DCAtomicField *current_atomic = (DCAtomicField *)NULL;
|
|
static DCMolecularField *current_molecular = (DCMolecularField *)NULL;
|
|
static DCAtomicField::ElementType atomic_element(new DCSimpleType(ST_invalid));
|
|
static DCPacker default_value_packer;
|
|
|
|
////////////////////////////////////////////////////////////////////
|
|
// Defining the interface to the parser.
|
|
////////////////////////////////////////////////////////////////////
|
|
|
|
void
|
|
dc_init_parser(istream &in, const string &filename, DCFile &file) {
|
|
dc_file = &file;
|
|
dc_init_lexer(in, filename);
|
|
}
|
|
|
|
void
|
|
dc_cleanup_parser() {
|
|
dc_file = (DCFile *)NULL;
|
|
}
|
|
|
|
%}
|
|
|
|
%token <u.integer> INTEGER
|
|
%token <u.real> REAL
|
|
%token <str> STRING HEX_STRING IDENTIFIER
|
|
|
|
%token KW_DCLASS
|
|
%token KW_FROM
|
|
%token KW_IMPORT
|
|
|
|
%token KW_INT8
|
|
%token KW_INT16
|
|
%token KW_INT32
|
|
%token KW_INT64
|
|
%token KW_UINT8
|
|
%token KW_UINT16
|
|
%token KW_UINT32
|
|
%token KW_UINT64
|
|
%token KW_FLOAT64
|
|
%token KW_STRING
|
|
%token KW_BLOB
|
|
%token KW_BLOB32
|
|
%token KW_INT8ARRAY
|
|
%token KW_INT16ARRAY
|
|
%token KW_INT32ARRAY
|
|
%token KW_UINT8ARRAY
|
|
%token KW_UINT16ARRAY
|
|
%token KW_UINT32ARRAY
|
|
%token KW_UINT32UINT8ARRAY
|
|
|
|
%token KW_MOL
|
|
|
|
%token KW_REQUIRED
|
|
%token KW_BROADCAST
|
|
%token KW_P2P
|
|
%token KW_RAM
|
|
%token KW_DB
|
|
%token KW_CLSEND
|
|
%token KW_CLRECV
|
|
%token KW_OWNSEND
|
|
%token KW_AIRECV
|
|
|
|
%type <u.dclass> dclass_name
|
|
%type <u.atomic> atomic_name
|
|
%type <u.subatomic> type_token
|
|
%type <str> import_identifier
|
|
%type <str> slash_identifier
|
|
|
|
%%
|
|
|
|
dc:
|
|
empty
|
|
| dc ';'
|
|
| dc dclass
|
|
| dc import
|
|
;
|
|
|
|
dclass:
|
|
KW_DCLASS IDENTIFIER
|
|
{
|
|
current_class = new DCClass($2);
|
|
if (!dc_file->add_class(current_class)) {
|
|
DCClass *old_class = dc_file->get_class_by_name(current_class->get_name());
|
|
if (old_class->is_bogus_class()) {
|
|
yyerror("Base class defined after its first reference: " + current_class->get_name());
|
|
} else {
|
|
yyerror("Duplicate class name: " + current_class->get_name());
|
|
}
|
|
}
|
|
}
|
|
dclass_derivation '{' dclass_fields '}'
|
|
;
|
|
|
|
dclass_name:
|
|
IDENTIFIER
|
|
{
|
|
DCFile::ClassesByName::const_iterator ni;
|
|
ni = dc_file->_classes_by_name.find($1);
|
|
if (ni == dc_file->_classes_by_name.end()) {
|
|
$$ = new DCClass($1, true);
|
|
dc_file->add_class($$);
|
|
} else {
|
|
$$ = (*ni).second;
|
|
}
|
|
}
|
|
;
|
|
|
|
slash_identifier:
|
|
IDENTIFIER
|
|
| slash_identifier '/' IDENTIFIER
|
|
{
|
|
$$ = $1 + string("/") + $3;
|
|
}
|
|
;
|
|
|
|
import_identifier:
|
|
slash_identifier
|
|
| import_identifier '.' slash_identifier
|
|
{
|
|
$$ = $1 + string(".") + $3;
|
|
}
|
|
;
|
|
|
|
import:
|
|
KW_IMPORT import_identifier
|
|
{
|
|
dc_file->add_import_module($2);
|
|
}
|
|
| KW_FROM import_identifier KW_IMPORT
|
|
{
|
|
dc_file->add_import_module($2);
|
|
}
|
|
import_symbol_list_or_star
|
|
;
|
|
|
|
import_symbol_list_or_star:
|
|
import_symbol_list
|
|
| '*'
|
|
{
|
|
dc_file->add_import_symbol("*");
|
|
}
|
|
;
|
|
|
|
import_symbol_list:
|
|
slash_identifier
|
|
{
|
|
dc_file->add_import_symbol($1);
|
|
}
|
|
| import_symbol_list ',' slash_identifier
|
|
{
|
|
dc_file->add_import_symbol($3);
|
|
}
|
|
;
|
|
|
|
dclass_derivation:
|
|
empty
|
|
| ':' base_list
|
|
;
|
|
|
|
base_list:
|
|
dclass_name
|
|
{
|
|
if ($1 != (DCClass *)NULL) {
|
|
current_class->add_parent($1);
|
|
}
|
|
}
|
|
| base_list ',' dclass_name
|
|
{
|
|
if ($3 != (DCClass *)NULL) {
|
|
current_class->add_parent($3);
|
|
}
|
|
}
|
|
;
|
|
|
|
dclass_fields:
|
|
empty
|
|
| dclass_fields ';'
|
|
| dclass_fields atomic_field
|
|
| dclass_fields molecular_field
|
|
;
|
|
|
|
atomic_field:
|
|
IDENTIFIER '('
|
|
{
|
|
current_atomic = new DCAtomicField($1);
|
|
if (!current_class->add_field(current_atomic)) {
|
|
yyerror("Duplicate field name: " + current_atomic->get_name());
|
|
}
|
|
}
|
|
parameter_list ')' atomic_flags
|
|
;
|
|
|
|
atomic_name:
|
|
IDENTIFIER
|
|
{
|
|
DCField *field = current_class->get_field_by_name($1);
|
|
$$ = (DCAtomicField *)NULL;
|
|
if (field == (DCField *)NULL) {
|
|
yyerror("Unknown field: " + $1);
|
|
} else {
|
|
$$ = field->as_atomic_field();
|
|
if ($$ == (DCAtomicField *)NULL) {
|
|
yyerror("Not an atomic field: " + $1);
|
|
}
|
|
}
|
|
}
|
|
;
|
|
|
|
parameter_list:
|
|
empty
|
|
| nonempty_parameter_list
|
|
;
|
|
|
|
nonempty_parameter_list:
|
|
atomic_element
|
|
| nonempty_parameter_list ',' atomic_element
|
|
;
|
|
|
|
atomic_element:
|
|
type_token
|
|
{
|
|
atomic_element = DCAtomicField::ElementType(new DCSimpleType($1));
|
|
}
|
|
atomic_element_definition
|
|
{
|
|
current_atomic->_elements.push_back(atomic_element);
|
|
}
|
|
;
|
|
|
|
atomic_element_definition:
|
|
empty
|
|
| atomic_element_definition '/' INTEGER
|
|
{
|
|
if (atomic_element._type->as_simple_type() == NULL) {
|
|
yyerror("Invalid divisor on complex type");
|
|
|
|
} else {
|
|
atomic_element._type->as_simple_type()->set_divisor($3);
|
|
}
|
|
}
|
|
| atomic_element_definition IDENTIFIER
|
|
{
|
|
atomic_element._name = $2;
|
|
}
|
|
| atomic_element_definition '='
|
|
{
|
|
default_value_packer.begin(atomic_element._type);
|
|
}
|
|
default_value
|
|
{
|
|
if (!default_value_packer.end()) {
|
|
yyerror("Invalid default value for type");
|
|
|
|
} else {
|
|
atomic_element.set_default_value(default_value_packer.get_string());
|
|
}
|
|
}
|
|
;
|
|
|
|
default_value:
|
|
INTEGER
|
|
{
|
|
default_value_packer.pack_int($1);
|
|
}
|
|
| REAL
|
|
{
|
|
default_value_packer.pack_double($1);
|
|
}
|
|
| STRING
|
|
{
|
|
default_value_packer.pack_string($1);
|
|
}
|
|
| HEX_STRING
|
|
{
|
|
default_value_packer.pack_literal_value($1);
|
|
}
|
|
| '{'
|
|
{
|
|
default_value_packer.push();
|
|
}
|
|
default_array '}'
|
|
{
|
|
default_value_packer.pop();
|
|
}
|
|
| INTEGER '*' INTEGER
|
|
{
|
|
for (int i = 0; i < $3; i++) {
|
|
default_value_packer.pack_int($1);
|
|
}
|
|
}
|
|
| REAL '*' INTEGER
|
|
{
|
|
for (int i = 0; i < $3; i++) {
|
|
default_value_packer.pack_double($1);
|
|
}
|
|
}
|
|
| HEX_STRING '*' INTEGER
|
|
{
|
|
for (int i = 0; i < $3; i++) {
|
|
default_value_packer.pack_literal_value($1);
|
|
}
|
|
}
|
|
;
|
|
|
|
default_array:
|
|
empty
|
|
| default_array_def maybe_comma
|
|
;
|
|
|
|
maybe_comma:
|
|
empty
|
|
| ','
|
|
;
|
|
|
|
default_array_def:
|
|
default_value
|
|
| default_array_def ',' default_value
|
|
;
|
|
|
|
type_token:
|
|
KW_INT8
|
|
{
|
|
$$ = ST_int8;
|
|
}
|
|
| KW_INT16
|
|
{
|
|
$$ = ST_int16;
|
|
}
|
|
| KW_INT32
|
|
{
|
|
$$ = ST_int32;
|
|
}
|
|
| KW_INT64
|
|
{
|
|
$$ = ST_int64;
|
|
}
|
|
| KW_UINT8
|
|
{
|
|
$$ = ST_uint8;
|
|
}
|
|
| KW_UINT16
|
|
{
|
|
$$ = ST_uint16;
|
|
}
|
|
| KW_UINT32
|
|
{
|
|
$$ = ST_uint32;
|
|
}
|
|
| KW_UINT64
|
|
{
|
|
$$ = ST_uint64;
|
|
}
|
|
| KW_FLOAT64
|
|
{
|
|
$$ = ST_float64;
|
|
}
|
|
| KW_STRING
|
|
{
|
|
$$ = ST_string;
|
|
}
|
|
| KW_BLOB
|
|
{
|
|
$$ = ST_blob;
|
|
}
|
|
| KW_BLOB32
|
|
{
|
|
$$ = ST_blob32;
|
|
}
|
|
| KW_INT8ARRAY
|
|
{
|
|
$$ = ST_int8array;
|
|
}
|
|
| KW_INT16ARRAY
|
|
{
|
|
$$ = ST_int16array;
|
|
}
|
|
| KW_INT32ARRAY
|
|
{
|
|
$$ = ST_int32array;
|
|
}
|
|
| KW_UINT8ARRAY
|
|
{
|
|
$$ = ST_uint8array;
|
|
}
|
|
| KW_UINT16ARRAY
|
|
{
|
|
$$ = ST_uint16array;
|
|
}
|
|
| KW_UINT32ARRAY
|
|
{
|
|
$$ = ST_uint32array;
|
|
}
|
|
| KW_UINT32UINT8ARRAY
|
|
{
|
|
$$ = ST_uint32uint8array;
|
|
}
|
|
;
|
|
|
|
atomic_flags:
|
|
empty
|
|
| atomic_flags KW_REQUIRED
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_required;
|
|
}
|
|
| atomic_flags KW_BROADCAST
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_broadcast;
|
|
}
|
|
| atomic_flags KW_P2P
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_p2p;
|
|
}
|
|
| atomic_flags KW_RAM
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_ram;
|
|
}
|
|
| atomic_flags KW_DB
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_db;
|
|
}
|
|
| atomic_flags KW_CLSEND
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_clsend;
|
|
}
|
|
| atomic_flags KW_CLRECV
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_clrecv;
|
|
}
|
|
| atomic_flags KW_OWNSEND
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_ownsend;
|
|
}
|
|
| atomic_flags KW_AIRECV
|
|
{
|
|
current_atomic->_flags |= DCAtomicField::F_airecv;
|
|
}
|
|
;
|
|
|
|
molecular_field:
|
|
IDENTIFIER ':'
|
|
{
|
|
current_molecular = new DCMolecularField($1);
|
|
if (!current_class->add_field(current_molecular)) {
|
|
yyerror("Duplicate field name: " + current_molecular->get_name());
|
|
}
|
|
}
|
|
molecular_atom_list
|
|
;
|
|
|
|
molecular_atom_list:
|
|
atomic_name
|
|
{
|
|
if ($1 != (DCAtomicField *)NULL) {
|
|
current_molecular->add_atomic($1);
|
|
}
|
|
}
|
|
| molecular_atom_list ',' atomic_name
|
|
{
|
|
if ($3 != (DCAtomicField *)NULL) {
|
|
current_molecular->add_atomic($3);
|
|
if (current_molecular->get_atomic(0)->_flags != $3->_flags) {
|
|
yyerror("Mismatched flags in molecule between " +
|
|
current_molecular->get_atomic(0)->get_name() + " and " +
|
|
$3->get_name());
|
|
}
|
|
}
|
|
}
|
|
;
|
|
|
|
empty:
|
|
;
|