File: [OMI] / omi / mof / mof.y
(download)
Revision: 1.1,
Wed May 30 21:47:39 2012 UTC (12 years, 1 month ago) by mike
Branch: MAIN
Initial revision
|
%{
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "buffer.h"
#include "types.h"
#include "state.h"
#include "ptrarray.h"
#define ARRAYOF(TYPE) ((MI_Uint32)TYPE | (MI_Uint32)MI_ARRAY_BIT)
extern int yylex();
extern int openIncludeFile(const char* path);
%}
%union
{
MI_Boolean boolean;
MI_Sint64 integer;
MI_Real64 real;
MI_Char16 character;
char* string;
char* identifier;
char* dollarIdentifier;
MI_Type type;
MI_PropertyDecl* property;
MI_MethodDecl* methodDecl;
MI_ParameterDecl* parameter;
MOF_ParameterList parameterList;
MOF_FeatureList featureList;
MI_QualifierDecl* qualifierDeclaration;
MOF_ConstantValue constantValue;
MOF_Initializer initializer;
MI_Uint32 flags;
MI_Qualifier* qualifier;
MOF_QualifierList qualifierList;
MI_ClassDecl* classDeclaration;
MI_InstanceDecl* instanceDeclaration;
}
%start mofSpecification
%token TOK_ERROR
%token TOK_BOOLEAN
%token TOK_SINT8
%token TOK_UINT8
%token TOK_SINT16
%token TOK_UINT16
%token TOK_SINT32
%token TOK_UINT32
%token TOK_SINT64
%token TOK_UINT64
%token TOK_REAL32
%token TOK_REAL64
%token TOK_DATETIME
%token TOK_CHAR16
%token TOK_STRING
%token TOK_BOOLEAN_VALUE
%token TOK_REF
%token TOK_SCOPE
%token TOK_CLASS
%token TOK_ASSOCIATION
%token TOK_INDICATION
%token TOK_QUALIFIER
%token TOK_PROPERTY
%token TOK_REFERENCE
%token TOK_METHOD
%token TOK_PARAMETER
%token TOK_ANY
%token TOK_FLAVOR
%token TOK_ENABLEOVERRIDE
%token TOK_DISABLEOVERRIDE
%token TOK_RESTRICTED
%token TOK_TOSUBCLASS
%token TOK_TRANSLATABLE
%token TOK_INSTANCE
%token TOK_OF
%token TOK_AS
%token TOK_PRAGMA
%token TOK_SCHEMA
%token TOK_INTEGER_VALUE
%token TOK_REAL_VALUE
%token TOK_STRING_VALUE
%token TOK_CHAR_VALUE
%token TOK_IDENT
%token TOK_ALIAS_IDENTIFIER
%token TOK_NULL
%type <string> stringValue
%type <string> TOK_STRING_VALUE
%type <string> identifier
%type <string> objectRef
%type <integer> TOK_INTEGER_VALUE
%type <real> TOK_REAL_VALUE
%type <character> TOK_CHAR_VALUE
%type <boolean> TOK_BOOLEAN_VALUE
%type <string> TOK_IDENT
%type <string> TOK_ALIAS_IDENTIFIER
%type <string> alias
%type <constantValue> constantValue
%type <type> dataType
%type <property> propertyDeclaration
%type <parameter> parameter
%type <parameterList> parameterList
%type <property> referenceDeclaration
%type <methodDecl> methodDeclaration
%type <featureList> classFeatureList
%type <featureList> classBody
%type <featureList> instanceBody
%type <qualifierDeclaration> qualifierDeclaration
%type <qualifierDeclaration> qualifierType
%type <integer> subscript
%type <initializer> initializer
%type <initializer> arrayInitializer
%type <initializer> arrayInitializerList
%type <flags> scope
%type <flags> scopeList
%type <flags> scopeExpr
%type <flags> flavor
%type <flags> flavorList
%type <flags> flavorExpr
%type <qualifier> qualifier
%type <qualifierList> qualifierList
%type <qualifierList> qualifierExpr
%type <initializer> qualifierParameter
%type <classDeclaration> classDeclaration
%type <instanceDeclaration> instanceDeclaration
%type <property> valueInitializer
%type <featureList> valueInitializerList
%%
mofSpecification
: mofProduction
{
}
| mofSpecification mofProduction
{
}
| TOK_ERROR
{
YYABORT;
}
mofProduction
: compilerDirective
{
}
| classDeclaration
{
/* [TODO: validate the class here] */
$1->flags = MI_FLAG_CLASS;
$1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
if (FinalizeClass($1) != 0)
YYABORT;
AddClassDecl($1);
if (state.classDeclCallback)
(*state.classDeclCallback)($1, state.classDeclCallbackData);
}
| qualifierDeclaration
{
AddQualifierDeclaration($1);
if (state.qualifierDeclCallback)
(*state.qualifierDeclCallback)($1, state.qualifierDeclCallbackData);
}
| instanceDeclaration
{
if (FinalizeInstance($1) != 0)
YYABORT;
AddInstanceDecl($1);
if (state.instanceDeclCallback)
(*state.instanceDeclCallback)($1, state.instanceDeclCallbackData);
}
compilerDirective
: TOK_PRAGMA TOK_IDENT '(' stringValue ')'
{
if (strcmp($2, "include") == 0)
{
if (openIncludeFile($4) != 0)
YYABORT;
}
else if (strcmp($2, "instancelocale") == 0)
{
if (state.pragmaCallback)
(*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
}
else if (strcmp($2, "locale") == 0)
{
if (state.pragmaCallback)
(*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
}
else if (strcmp($2, "namespace") == 0)
{
if (state.pragmaCallback)
(*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
}
else
{
yywarnf(ID_UNKNOWN_PRAGMA,
"warning: unknown pragma: %s=%s", $2, $4);
if (state.pragmaCallback)
(*state.pragmaCallback)($2, $4, state.pragmaCallbackData);
}
}
classDeclaration
: TOK_CLASS identifier classBody
{
/* Check whether class already exists */
if (FindClassDecl($2))
{
yyerrorf(ID_CLASS_ALREADY_DEFINED,
"class already defined: \"%s\"", $2);
YYABORT;
}
$$ = CALLOC_T(MI_ClassDecl, 1);
$$->flags = MI_FLAG_CLASS;
$$->name = $2;
$$->properties = $3.propertySet.data;
$$->numProperties = $3.propertySet.size;
$$->methods = $3.methodList.data;
$$->numMethods = $3.methodList.size;
}
| TOK_CLASS identifier ':' identifier classBody
{
const MI_ClassDecl* scd;
/* Check whether class already exists */
if (FindClassDecl($2))
{
yyerrorf(ID_CLASS_ALREADY_DEFINED,
"class already defined: \"%s\"", $2);
YYABORT;
}
/* Check whether superclass exists */
scd = FindClassDecl($4);
if (!scd)
{
yyerrorf(ID_UNDEFINED_SUPERCLASS,
"super class of \"%s\" is undefined: \"%s\"", $2, $4);
YYABORT;
}
$$ = CALLOC_T(MI_ClassDecl, 1);
$$->flags = MI_FLAG_CLASS;
$$->name = $2;
$$->superClass = $4;
$$->superClassDecl = (MI_ClassDecl*)scd;
$$->properties = $5.propertySet.data;
$$->numProperties = $5.propertySet.size;
$$->methods = $5.methodList.data;
$$->numMethods = $5.methodList.size;
}
| qualifierExpr TOK_CLASS identifier classBody
{
/* Check qualifier scope */
if (CheckScope(MI_FLAG_CLASS, &$1) != 0)
YYABORT;
/* Check whether class already exists */
if (FindClassDecl($3))
{
yyerrorf(ID_CLASS_ALREADY_DEFINED,
"class already defined: \"%s\"", $3);
YYABORT;
}
$$ = CALLOC_T(MI_ClassDecl, 1);
$$->flags = MI_FLAG_CLASS;
$$->name = $3;
$$->properties = $4.propertySet.data;
$$->numProperties = $4.propertySet.size;
$$->methods = $4.methodList.data;
$$->numMethods = $4.methodList.size;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
| qualifierExpr TOK_CLASS identifier ':' identifier classBody
{
const MI_ClassDecl* scd;
/* Check qualifier scope */
if (CheckScope(MI_FLAG_CLASS, &$1) != 0)
YYABORT;
/* Check whether class already exists */
if (FindClassDecl($3))
{
yyerrorf(ID_CLASS_ALREADY_DEFINED,
"class already defined: \"%s\"", $3);
YYABORT;
}
/* Check whether superclass exists */
scd = FindClassDecl($5);
if (!scd)
{
yyerrorf(ID_UNDEFINED_SUPERCLASS,
"super class of \"%s\" is undefined: \"%s\"", $3, $5);
YYABORT;
}
$$ = CALLOC_T(MI_ClassDecl, 1);
$$->flags = MI_FLAG_CLASS;
$$->name = $3;
$$->superClass = scd->name;
$$->superClassDecl = (MI_ClassDecl*)scd;
$$->properties = $6.propertySet.data;
$$->numProperties = $6.propertySet.size;
$$->methods = $6.methodList.data;
$$->numMethods = $6.methodList.size;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
classBody
: '{' classFeatureList '}' ';'
{
$$ = $2;
}
| '{' '}' ';'
{
$$.propertySet.data = NULL;
$$.propertySet.size = 0;
$$.methodList.data = NULL;
$$.methodList.size = 0;
}
classFeatureList
: propertyDeclaration
{
if (CheckPropertyValueConstraints($1) != 0)
{
YYABORT;
}
$$.propertySet.data = NULL;
$$.propertySet.size = 0;
$$.methodList.data = NULL;
$$.methodList.size = 0;
$1->flags = MI_FLAG_PROPERTY;
$1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
PtrArray_Append((PtrArray*)&$$.propertySet, $1);
}
| methodDeclaration
{
$$.propertySet.data = NULL;
$$.propertySet.size = 0;
$$.methodList.data = NULL;
$$.methodList.size = 0;
$1->flags = MI_FLAG_METHOD;
$1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
PtrArray_Append((PtrArray*)&$$.methodList, $1);
}
| referenceDeclaration
{
$$.propertySet.data = NULL;
$$.propertySet.size = 0;
$$.methodList.data = NULL;
$$.methodList.size = 0;
$1->flags = MI_FLAG_PROPERTY;
$1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
PtrArray_Append((PtrArray*)&$$.propertySet, $1);
}
| classFeatureList propertyDeclaration
{
if (CheckPropertyValueConstraints($2) != 0)
{
YYABORT;
}
if (FindProperty(&$1.propertySet, $2->name))
{
yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
"class feature already defined: \"%s\"", $2->name);
YYABORT;
}
$2->flags = MI_FLAG_PROPERTY;
$2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
PtrArray_Append((PtrArray*)&$$.propertySet, $2);
}
| classFeatureList methodDeclaration
{
if (FindMethod(&$1.methodList, $2->name))
{
yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
"class feature already defined: \"%s\"", $2->name);
YYABORT;
}
$2->flags = MI_FLAG_METHOD;
$2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
PtrArray_Append((PtrArray*)&$$.methodList, $2);
}
| classFeatureList referenceDeclaration
{
if (FindProperty(&$1.propertySet, $2->name))
{
yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
"class feature already defined: \"%s\"", $2->name);
YYABORT;
}
$2->flags = MI_FLAG_PROPERTY;
$2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
PtrArray_Append((PtrArray*)&$$.propertySet, $2);
}
qualifierExpr
: '[' qualifierList ']'
{
$$ = $2;
}
qualifierList
: qualifier
{
$$.data = NULL;
$$.size = 0;
PtrArray_Append((PtrArray*)&$$, $1);
}
| qualifierList ',' qualifier
{
if (FindQualifier(&$1, $3->name))
{
yyerrorf(ID_DUPLICATE_QUALIFIER,
"duplicate qualifier: \"%s\"", $3->name);
YYABORT;
}
PtrArray_Append((PtrArray*)&$$, $3);
}
qualifier
: identifier
{
MI_Qualifier* q;
const MI_QualifierDecl* qd;
qd = FindQualifierDeclaration($1);
if (!qd)
{
yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
YYABORT;
}
if (qd->type != MI_BOOLEAN)
{
yyerrorf(ID_MISSING_QUALIFIER_INITIALIZER,
"qualifier is missing initializer: \"%s\"", $1);
YYABORT;
}
q = CALLOC_T(MI_Qualifier, 1);
q->name = qd->name; /* use casing of qualifier declaration name */
q->type = qd->type;
q->flavor = qd->flavor;
q->value = NewTrueValue();
$$ = q;
}
| identifier qualifierParameter
{
MI_Qualifier* q;
const MI_QualifierDecl* qd;
void* value;
qd = FindQualifierDeclaration($1);
if (!qd)
{
yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
YYABORT;
}
if (InitializerToValue(&$2, qd->type, &value) != 0)
{
yyerrorf(ID_INVALID_QUALIFIER_INITIALIZER,
"invalid initializer for qualifer: \"%s\"", $1);
YYABORT;
}
q = CALLOC_T(MI_Qualifier, 1);
q->name = qd->name; /* use casing of qualifier declaration name */
q->type = qd->type;
q->flavor = qd->flavor;
q->value = value;
$$ = q;
}
| identifier ':' flavor
{
MI_Qualifier* q;
const MI_QualifierDecl* qd;
qd = FindQualifierDeclaration($1);
if (!qd)
{
yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
YYABORT;
}
if (qd->type != MI_BOOLEAN)
{
yyerrorf(ID_MISSING_QUALIFIER_INITIALIZER,
"qualifier is missing initializer: \"%s\"", $1);
YYABORT;
}
q = CALLOC_T(MI_Qualifier, 1);
q->name = qd->name; /* use casing of qualifier declaration name */
q->type = qd->type;
q->flavor = PropagateFlavors($3, qd->flavor);
q->value = NewTrueValue();
$$ = q;
}
| identifier qualifierParameter ':' flavor
{
MI_Qualifier* q;
const MI_QualifierDecl* qd;
void* value;
qd = FindQualifierDeclaration($1);
if (!qd)
{
yyerrorf(ID_UNDEFINED_QUALIFIER, "undefined qualifier: \"%s\"", $1);
YYABORT;
}
if (InitializerToValue(&$2, qd->type, &value) != 0)
{
yyerrorf(ID_INVALID_QUALIFIER_INITIALIZER,
"invalid initializer for qualifer: \"%s\"", $1);
YYABORT;
}
q = CALLOC_T(MI_Qualifier, 1);
q->name = qd->name; /* use casing of qualifier declaration name */
q->type = qd->type;
q->value = value;
q->flavor = PropagateFlavors($4, qd->flavor);
$$ = q;
}
qualifierParameter
: '(' constantValue ')'
{
memset(&$$, 0, sizeof($$));
$$.data = CALLOC_T(MOF_ConstantValue, 1);
$$.data[0] = $2;
$$.size = 1;
}
| arrayInitializer
{
$$ = $1;
}
flavorList
: flavor
{
$$ = $1;
}
| flavorList ',' flavor
{
$$ |= $3;
}
flavor
: TOK_ENABLEOVERRIDE
{
$$ = MI_FLAG_ENABLEOVERRIDE;
}
| TOK_DISABLEOVERRIDE
{
$$ = MI_FLAG_DISABLEOVERRIDE;
}
| TOK_RESTRICTED
{
$$ = MI_FLAG_RESTRICTED;
}
| TOK_TOSUBCLASS
{
$$ = MI_FLAG_TOSUBCLASS;
}
| TOK_TRANSLATABLE
{
$$ = MI_FLAG_TRANSLATABLE;
}
propertyDeclaration
: dataType identifier ';'
{
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $2;
$$->type = $1;
}
| qualifierExpr dataType identifier ';'
{
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $3;
$$->type = $2;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
| dataType identifier subscript ';'
{
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $2;
$$->type = ARRAYOF($1);
$$->subscript = (MI_Uint32)$3;
}
| qualifierExpr dataType identifier subscript ';'
{
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $3;
$$->type = ARRAYOF($2);
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
$$->subscript = (MI_Uint32)$4;
}
| dataType identifier '=' initializer ';'
{
void* value;
if (InitializerToValue(&$4, $1, &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $2;
$$->type = $1;
$$->value = value;
}
| qualifierExpr dataType identifier '=' initializer ';'
{
void* value;
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
YYABORT;
if (InitializerToValue(&$5, $2, &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $3;
$$->type = $2;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
$$->value = value;
}
| dataType identifier subscript '=' initializer ';'
{
void* value;
if (InitializerToValue(&$5, ARRAYOF($1), &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $2;
$$->type = ARRAYOF($1);
$$->subscript = (MI_Uint32)$3;
$$->value = value;
}
| qualifierExpr dataType identifier subscript '=' initializer ';'
{
void* value;
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PROPERTY, &$1) != 0)
YYABORT;
if (InitializerToValue(&$6, ARRAYOF($2), &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $3;
$$->type = ARRAYOF($2);
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
$$->subscript = (MI_Uint32)$4;
$$->value = value;
}
referenceDeclaration
: objectRef identifier ';'
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($1);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->type = MI_REFERENCE;
$$->name = $2;
$$->className = cd->name;
}
| qualifierExpr objectRef identifier ';'
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($2);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
YYABORT;
}
/* Check qualifier scope */
if (CheckScope(MI_FLAG_REFERENCE, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->type = MI_REFERENCE;
$$->name = $3;
$$->className = cd->name;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
| objectRef identifier initializer';'
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($1);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->type = MI_REFERENCE;
$$->name = $2;
$$->className = cd->name;
yywarnf(ID_IGNORED_INITIALIZER, "warning: ignored initializer");
/* [TODO: use initializer */
}
| qualifierExpr objectRef identifier initializer ';'
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($2);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
YYABORT;
}
/* Check qualifier scope */
if (CheckScope(MI_FLAG_REFERENCE, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->type = MI_REFERENCE;
$$->name = $3;
$$->className = cd->name;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
yywarnf(ID_IGNORED_INITIALIZER, "warning: ignored initializer");
/* [TODO: use initializer */
}
methodDeclaration
: dataType identifier '(' parameterList ')' ';'
{
$$ = CALLOC_T(MI_MethodDecl, 1);
$$->name = $2;
$$->parameters = $4.data;
$$->numParameters = $4.size;
$$->returnType = $1;
}
| qualifierExpr dataType identifier '(' parameterList ')' ';'
{
/* Check qualifier scope */
if (CheckScope(MI_FLAG_METHOD, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_MethodDecl, 1);
$$->name = $3;
$$->parameters = $5.data;
$$->numParameters = $5.size;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
$$->returnType = $2;
}
| dataType identifier '(' ')' ';'
{
MOF_ParameterList parameterList = PTRARRAY_INITIALIZER;
$$ = CALLOC_T(MI_MethodDecl, 1);
$$->name = $2;
$$->parameters = parameterList.data;
$$->numParameters = parameterList.size;
$$->returnType = $1;
}
| qualifierExpr dataType identifier '(' ')' ';'
{
MOF_ParameterList parameterList = PTRARRAY_INITIALIZER;
/* Check qualifier scope */
if (CheckScope(MI_FLAG_METHOD, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_MethodDecl, 1);
$$->name = $3;
$$->parameters = parameterList.data;
$$->numParameters = parameterList.size;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
$$->returnType = $2;
}
dataType
: TOK_BOOLEAN
{
$$ = MI_BOOLEAN;
}
| TOK_SINT8
{
$$ = MI_SINT8;
}
| TOK_UINT8
{
$$ = MI_UINT8;
}
| TOK_SINT16
{
$$ = MI_SINT16;
}
| TOK_UINT16
{
$$ = MI_UINT16;
}
| TOK_SINT32
{
$$ = MI_SINT32;
}
| TOK_UINT32
{
$$ = MI_UINT32;
}
| TOK_SINT64
{
$$ = MI_SINT64;
}
| TOK_UINT64
{
$$ = MI_UINT64;
}
| TOK_REAL32
{
$$ = MI_REAL32;
}
| TOK_REAL64
{
$$ = MI_REAL64;
}
| TOK_CHAR16
{
$$ = MI_CHAR16;
}
| TOK_DATETIME
{
$$ = MI_DATETIME;
}
| TOK_STRING
{
$$ = MI_STRING;
}
objectRef
: identifier TOK_REF
{
$$ = $1;
}
parameterList
: parameter
{
$1->flags = MI_FLAG_PARAMETER;
$1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
$$.data = NULL;
$$.size = 0;
PtrArray_Append((PtrArray*)&$$, $1);
}
| parameterList ',' parameter
{
if (FindParameter(&$1, $3->name))
{
yyerrorf(ID_PARAMETER_ALREADY_DEFINED,
"parameter already defined: \"%s\"", $3->name);
YYABORT;
}
$3->flags = MI_FLAG_PARAMETER;
$3->flags |= GetQualFlags($3->qualifiers, $3->numQualifiers);
PtrArray_Append((PtrArray*)&$$, $3);
}
parameter
: dataType identifier
{
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $2;
$$->type = $1;
}
| objectRef identifier
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($1);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
YYABORT;
}
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $2;
$$->type = MI_REFERENCE;
$$->className = cd->name;
}
| qualifierExpr dataType identifier
{
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $3;
$$->type = $2;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
| qualifierExpr objectRef identifier
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($2);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
YYABORT;
}
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $3;
$$->type = MI_REFERENCE;
$$->className = cd->name;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
| dataType identifier subscript
{
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $2;
$$->type = ARRAYOF($1);
$$->subscript = (MI_Uint32)$3;
}
| objectRef identifier subscript
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($1);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $1);
YYABORT;
}
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $2;
$$->type = ARRAYOF(MI_REFERENCE);
$$->className = cd->name;
$$->subscript = (MI_Uint32)$3;
}
| qualifierExpr dataType identifier subscript
{
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $3;
$$->type = ARRAYOF($2);
$$->subscript = (MI_Uint32)$4;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
| qualifierExpr objectRef identifier subscript
{
const MI_ClassDecl* cd;
/* Verify that class exists */
cd = FindClassDecl($2);
if (!cd)
{
yyerrorf(ID_UNDEFINED_CLASS, "undefined class: \"%s\"", $2);
YYABORT;
}
/* Check qualifier scope */
if (CheckScope(MI_FLAG_PARAMETER, &$1) != 0)
YYABORT;
$$ = CALLOC_T(MI_ParameterDecl, 1);
$$->name = $3;
$$->type = ARRAYOF(MI_REFERENCE);
$$->className = cd->name;
$$->subscript = (MI_Uint32)$4;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
subscript
: '[' TOK_INTEGER_VALUE ']'
{
if ($2 <= 0)
{
yyerrorf(ID_ILLEGAL_ARRAY_SUBSCRIPT,
"illegal array subscript: " SINT64_FMT, $2);
YYABORT;
}
$$ = $2;
}
| '[' ']'
{
/* 0 signifies a dynamic array */
$$ = 0;
}
initializer
: constantValue
{
memset(&$$, 0, sizeof($$));
$$.data = CALLOC_T(MOF_ConstantValue, 1);
$$.data[0] = $1;
$$.size = 1;
}
| arrayInitializer
{
$$ = $1;
}
| TOK_ALIAS_IDENTIFIER
{
memset(&$$, 0, sizeof($$));
$$.data = CALLOC_T(MOF_ConstantValue, 1);
$$.data[0].type = TOK_STRING_VALUE;
$$.data[0].value.string = $1;
$$.size = 0;
}
arrayInitializer
: '{' arrayInitializerList '}'
{
$$ = $2;
}
arrayInitializerList
: constantValue
{
memset(&$$, 0, sizeof($$));
$$.data = CALLOC_T(MOF_ConstantValue, 1);
$$.data[0] = $1;
$$.size = 1;
$$.isArray = 1;
}
| arrayInitializerList ',' constantValue
{
$1.data = REALLOC_T(MOF_ConstantValue, $1.data, $1.size + 1);
$1.data[$1.size] = $3;
$1.size++;
$$ = $1;
}
constantValue
: TOK_INTEGER_VALUE
{
$$.type = TOK_INTEGER_VALUE;
$$.value.integer = $1;
}
| TOK_REAL_VALUE
{
$$.type = TOK_REAL_VALUE;
$$.value.real = $1;
}
| TOK_CHAR_VALUE
{
$$.type = TOK_CHAR_VALUE;
$$.value.character = $1;
}
| stringValue
{
$$.type = TOK_STRING_VALUE;
$$.value.string = $1;
}
| TOK_BOOLEAN_VALUE
{
$$.type = TOK_BOOLEAN_VALUE;
$$.value.boolean = $1;
}
| TOK_NULL
{
$$.type = TOK_NULL;
}
stringValue
: TOK_STRING_VALUE
{
$$ = $1;
}
| stringValue TOK_STRING_VALUE
{
size_t size = strlen($1) + strlen($2) + 1;
$$ = (char*)MOF_Realloc(&state.heap, $1, size);
Strcat($$, size, $2);
MOF_Free(&state.heap, $2);
}
qualifierDeclaration
: TOK_QUALIFIER identifier qualifierType scopeExpr ';'
{
$3->name = $2;
$3->scope = $4;
$3->flavor = 0;
$$ = $3;
}
| TOK_QUALIFIER identifier qualifierType scopeExpr flavorExpr ';'
{
$3->name = $2;
$3->scope = $4;
$3->flavor = $5;
$$ = $3;
}
qualifierType
: ':' dataType
{
$$ = CALLOC_T(MI_QualifierDecl, 1);
$$->type = $2;
}
| ':' dataType '=' initializer
{
void* value;
if (InitializerToValue(&$4, $2, &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_QualifierDecl, 1);
$$->type = $2;
$$->value = value;
ReleaseInitializer(&$4);
}
| ':' dataType subscript
{
$$ = CALLOC_T(MI_QualifierDecl, 1);
$$->type = ARRAYOF($2);
$$->subscript = (MI_Uint32)$3;
}
| ':' dataType subscript '=' initializer
{
void* value = NULL;
if (InitializerToValue(&$5, ARRAYOF($2), &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_QualifierDecl, 1);
$$->type = ARRAYOF($2);
$$->subscript = (MI_Uint32)$3;
$$->value = value;
ReleaseInitializer(&$5);
}
scopeExpr
: ',' TOK_SCOPE '(' scopeList ')'
{
$$ = $4;
}
scopeList
: scope
{
$$ = $1;
}
| scopeList ',' scope
{
$$ |= $3;
}
scope
: TOK_CLASS
{
$$ = MI_FLAG_CLASS;
}
| TOK_ASSOCIATION
{
$$ = MI_FLAG_ASSOCIATION;
}
| TOK_INDICATION
{
$$ = MI_FLAG_INDICATION;
}
| TOK_PROPERTY
{
$$ = MI_FLAG_PROPERTY;
}
| TOK_REFERENCE
{
$$ = MI_FLAG_REFERENCE;
}
| TOK_METHOD
{
$$ = MI_FLAG_METHOD;
}
| TOK_PARAMETER
{
$$ = MI_FLAG_PARAMETER;
}
| TOK_ANY
{
$$ = MI_FLAG_ANY;
}
flavorExpr
: ',' TOK_FLAVOR '(' flavorList ')'
{
/* Reject incompatiable ToSubclass and Restricted flavors */
if ($4 & MI_FLAG_TOSUBCLASS && $4 & MI_FLAG_RESTRICTED)
{
yyerrorf(ID_INCOMPATIBLE_FLAVORS, "incompatible flavors: %s/%s",
"ToSubclass", "Restricted");
YYABORT;
}
/* Reject incompatiable EnableOverride and DisableOverride flavors */
if ($4 & MI_FLAG_ENABLEOVERRIDE && $4 & MI_FLAG_DISABLEOVERRIDE)
{
yyerrorf(ID_INCOMPATIBLE_FLAVORS, "incompatible flavors: %s/%s",
"EnableOverride", "DisableOverride");
YYABORT;
}
$$ = $4;
}
instanceDeclaration
: TOK_INSTANCE TOK_OF identifier instanceBody
{
$$ = CALLOC_T(MI_InstanceDecl, 1);
$$->flags = 0;
$$->name = $3;
$$->properties = $4.propertySet.data;
$$->numProperties = $4.propertySet.size;
}
| qualifierExpr TOK_INDICATION TOK_OF identifier instanceBody
{
$$ = CALLOC_T(MI_InstanceDecl, 1);
$$->flags = 0;
$$->name = $4;
$$->properties = $5.propertySet.data;
$$->numProperties = $5.propertySet.size;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
| TOK_INSTANCE TOK_OF identifier alias instanceBody
{
/* [TODO]: handle alias */
$$ = CALLOC_T(MI_InstanceDecl, 1);
$$->flags = 0;
$$->name = $3;
$$->properties = $5.propertySet.data;
$$->numProperties = $5.propertySet.size;
}
| qualifierExpr TOK_INDICATION TOK_OF identifier alias instanceBody
{
/* [TODO]: handle alias */
$$ = CALLOC_T(MI_InstanceDecl, 1);
$$->flags = 0;
$$->name = $4;
$$->properties = $6.propertySet.data;
$$->numProperties = $6.propertySet.size;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
instanceBody
: '{' valueInitializerList '}' ';'
{
$$ = $2;
}
alias
: TOK_AS TOK_ALIAS_IDENTIFIER
{
$$ = $2;
}
valueInitializerList
: valueInitializer
{
$$.propertySet.data = NULL;
$$.propertySet.size = 0;
$1->flags = MI_FLAG_PROPERTY;
$1->flags |= GetQualFlags($1->qualifiers, $1->numQualifiers);
PtrArray_Append((PtrArray*)&$$.propertySet, $1);
}
| valueInitializerList valueInitializer
{
if (FindProperty(&$1.propertySet, $2->name))
{
yyerrorf(ID_CLASS_FEATURE_ALREADY_DEFINED,
"instance property already defined: \"%s\"", $2->name);
YYABORT;
}
$2->flags = MI_FLAG_PROPERTY;
$2->flags |= GetQualFlags($2->qualifiers, $2->numQualifiers);
PtrArray_Append((PtrArray*)&$$.propertySet, $2);
}
valueInitializer
: identifier '=' initializer ';'
{
void* value;
MI_Type type = InitializerToType(&$3);
if (InitializerToValue(&$3, type, &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $1;
$$->type = type;
$$->value = value;
}
| qualifierExpr identifier '=' initializer ';'
{
void* value;
MI_Type type = InitializerToType(&$4);
if (InitializerToValue(&$4, type, &value) != 0)
{
yyerrorf(ID_INVALID_INITIALIZER, "invalid initializer");
YYABORT;
}
$$ = CALLOC_T(MI_PropertyDecl, 1);
$$->name = $2;
$$->type = type;
$$->value = value;
$$->qualifiers = $1.data;
$$->numQualifiers = $1.size;
}
identifier
: TOK_IDENT
{
$$ = $1;
}
| TOK_ASSOCIATION
{
$$ = MOF_Strdup(&state.heap, "Association");
}
| TOK_INDICATION
{
$$ = MOF_Strdup(&state.heap, "Indication");
}
| TOK_REFERENCE
{
$$ = MOF_Strdup(&state.heap, "Reference");
}
| TOK_PROPERTY
{
$$ = MOF_Strdup(&state.heap, "Property");
}