open_toontown_panda3d/direct/src/dcparser/dcParser.yxx

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:
;