📄 classpsr.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.24 07/01/05 */
/* */
/* CLASS PARSER MODULE */
/*******************************************************/
/**************************************************************/
/* Purpose: Parsing Routines for Defclass Construct */
/* */
/* Principal Programmer(s): */
/* Brian L. Donnell */
/* */
/* Contributing Programmer(s): */
/* */
/* Revision History: */
/* 6.24: Added allowed-classes slot facet. */
/* */
/* Converted INSTANCE_PATTERN_MATCHING to */
/* DEFRULE_CONSTRUCT. */
/* */
/* Renamed BOOLEAN macro type to intBool. */
/* */
/**************************************************************/
/* =========================================
*****************************************
EXTERNAL DEFINITIONS
=========================================
***************************************** */
#include "setup.h"
#if OBJECT_SYSTEM && (! BLOAD_ONLY) && (! RUN_TIME)
#if BLOAD || BLOAD_AND_BSAVE
#include "bload.h"
#endif
#include "classcom.h"
#include "classfun.h"
#include "clsltpsr.h"
#include "cstrcpsr.h"
#include "envrnmnt.h"
#include "inherpsr.h"
#include "memalloc.h"
#include "modulpsr.h"
#include "modulutl.h"
#include "msgpsr.h"
#include "router.h"
#include "scanner.h"
#define _CLASSPSR_SOURCE_
#include "classpsr.h"
/* =========================================
*****************************************
CONSTANTS
=========================================
***************************************** */
#define ROLE_RLN "role"
#define ABSTRACT_RLN "abstract"
#define CONCRETE_RLN "concrete"
#define HANDLER_DECL "message-handler"
#define SLOT_RLN "slot"
#define SGL_SLOT_RLN "single-slot"
#define MLT_SLOT_RLN "multislot"
#define DIRECT 0
#define INHERIT 1
/* =========================================
*****************************************
INTERNALLY VISIBLE FUNCTION HEADERS
=========================================
***************************************** */
static intBool ValidClassName(void *,char *,DEFCLASS **);
static intBool ParseSimpleQualifier(void *,char *,char *,char *,char *,intBool *,intBool *);
static intBool ReadUntilClosingParen(void *,char *,struct token *);
static void AddClass(void *,DEFCLASS *);
static void BuildSubclassLinks(void *,DEFCLASS *);
static void FormInstanceTemplate(void *,DEFCLASS *);
static void FormSlotNameMap(void *,DEFCLASS *);
static TEMP_SLOT_LINK *MergeSlots(void *,TEMP_SLOT_LINK *,DEFCLASS *,unsigned *,int);
static void PackSlots(void *,DEFCLASS *,TEMP_SLOT_LINK *);
#if DEFMODULE_CONSTRUCT
static void CreateClassScopeMap(void *,DEFCLASS *);
#endif
static void CreatePublicSlotMessageHandlers(void *,DEFCLASS *);
/* =========================================
*****************************************
EXTERNALLY VISIBLE FUNCTIONS
=========================================
***************************************** */
/***************************************************************************************
NAME : ParseDefclass
DESCRIPTION : (defclass ...) is a construct (as
opposed to a function), thus no variables
may be used. This means classes may only
be STATICALLY defined (like rules).
INPUTS : The logical name of the router
for the parser input
RETURNS : FALSE if successful parse, TRUE otherwise
SIDE EFFECTS : Inserts valid class definition into
Class Table.
NOTES : H/L Syntax :
(defclass <name> [<comment>]
(is-a <superclass-name>+)
<class-descriptor>*)
<class-descriptor> :== (slot <name> <slot-descriptor>*) |
(role abstract|concrete) |
(pattern-match reactive|non-reactive)
These are for documentation only:
(message-handler <name> [<type>])
<slot-descriptor> :== (default <default-expression>) |
(default-dynamic <default-expression>) |
(storage shared|local) |
(access read-only|read-write|initialize-only) |
(propagation no-inherit|inherit) |
(source composite|exclusive)
(pattern-match reactive|non-reactive)
(visibility public|private)
(override-message <message-name>)
(type ...) |
(cardinality ...) |
(allowed-symbols ...) |
(allowed-strings ...) |
(allowed-numbers ...) |
(allowed-integers ...) |
(allowed-floats ...) |
(allowed-values ...) |
(allowed-instance-names ...) |
(allowed-classes ...) |
(range ...)
<default-expression> ::= ?NONE | ?VARIABLE | <expression>*
***************************************************************************************/
globle int ParseDefclass(
void *theEnv,
char *readSource)
{
SYMBOL_HN *cname;
DEFCLASS *cls;
PACKED_CLASS_LINKS *sclasses,*preclist;
TEMP_SLOT_LINK *slots = NULL;
int roleSpecified = FALSE,
abstract = FALSE,
parseError;
#if DEFRULE_CONSTRUCT
int patternMatchSpecified = FALSE,
reactive = TRUE;
#endif
SetPPBufferStatus(theEnv,ON);
FlushPPBuffer(theEnv);
SetIndentDepth(theEnv,3);
SavePPBuffer(theEnv,"(defclass ");
#if BLOAD || BLOAD_ONLY || BLOAD_AND_BSAVE
if ((Bloaded(theEnv)) && (! ConstructData(theEnv)->CheckSyntaxMode))
{
CannotLoadWithBloadMessage(theEnv,"defclass");
return(TRUE);
}
#endif
cname = GetConstructNameAndComment(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken,"defclass",
EnvFindDefclass,NULL,"#",TRUE,
TRUE,TRUE);
if (cname == NULL)
return(TRUE);
if (ValidClassName(theEnv,ValueToString(cname),&cls) == FALSE)
return(TRUE);
sclasses = ParseSuperclasses(theEnv,readSource,cname);
if (sclasses == NULL)
return(TRUE);
preclist = FindPrecedenceList(theEnv,cls,sclasses);
if (preclist == NULL)
{
DeletePackedClassLinks(theEnv,sclasses,TRUE);
return(TRUE);
}
parseError = FALSE;
GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
while (GetType(DefclassData(theEnv)->ObjectParseToken) != RPAREN)
{
if (GetType(DefclassData(theEnv)->ObjectParseToken) != LPAREN)
{
SyntaxErrorMessage(theEnv,"defclass");
parseError = TRUE;
break;
}
PPBackup(theEnv);
PPCRAndIndent(theEnv);
SavePPBuffer(theEnv,"(");
GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
if (GetType(DefclassData(theEnv)->ObjectParseToken) != SYMBOL)
{
SyntaxErrorMessage(theEnv,"defclass");
parseError = TRUE;
break;
}
if (strcmp(DOToString(DefclassData(theEnv)->ObjectParseToken),ROLE_RLN) == 0)
{
if (ParseSimpleQualifier(theEnv,readSource,ROLE_RLN,CONCRETE_RLN,ABSTRACT_RLN,
&roleSpecified,&abstract) == FALSE)
{
parseError = TRUE;
break;
}
}
#if DEFRULE_CONSTRUCT
else if (strcmp(DOToString(DefclassData(theEnv)->ObjectParseToken),MATCH_RLN) == 0)
{
if (ParseSimpleQualifier(theEnv,readSource,MATCH_RLN,NONREACTIVE_RLN,REACTIVE_RLN,
&patternMatchSpecified,&reactive) == FALSE)
{
parseError = TRUE;
break;
}
}
#endif
else if (strcmp(DOToString(DefclassData(theEnv)->ObjectParseToken),SLOT_RLN) == 0)
{
slots = ParseSlot(theEnv,readSource,slots,preclist,FALSE,FALSE);
if (slots == NULL)
{
parseError = TRUE;
break;
}
}
else if (strcmp(DOToString(DefclassData(theEnv)->ObjectParseToken),SGL_SLOT_RLN) == 0)
{
slots = ParseSlot(theEnv,readSource,slots,preclist,FALSE,TRUE);
if (slots == NULL)
{
parseError = TRUE;
break;
}
}
else if (strcmp(DOToString(DefclassData(theEnv)->ObjectParseToken),MLT_SLOT_RLN) == 0)
{
slots = ParseSlot(theEnv,readSource,slots,preclist,TRUE,TRUE);
if (slots == NULL)
{
parseError = TRUE;
break;
}
}
else if (strcmp(DOToString(DefclassData(theEnv)->ObjectParseToken),HANDLER_DECL) == 0)
{
if (ReadUntilClosingParen(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken) == FALSE)
{
parseError = TRUE;
break;
}
}
else
{
SyntaxErrorMessage(theEnv,"defclass");
parseError = TRUE;
break;
}
GetToken(theEnv,readSource,&DefclassData(theEnv)->ObjectParseToken);
}
if ((GetType(DefclassData(theEnv)->ObjectParseToken) != RPAREN) || (parseError == TRUE))
{
DeletePackedClassLinks(theEnv,sclasses,TRUE);
DeletePackedClassLinks(theEnv,preclist,TRUE);
DeleteSlots(theEnv,slots);
return(TRUE);
}
SavePPBuffer(theEnv,"\n");
/* =========================================================================
The abstract/reactive qualities of a class are inherited if not specified
========================================================================= */
if (roleSpecified == FALSE)
{
if (preclist->classArray[1]->system && /* Change to cause */
(DefclassData(theEnv)->ClassDefaultsMode == CONVENIENCE_MODE)) /* default role of */
{ abstract = FALSE; } /* classes to be concrete. */
else
{ abstract = preclist->classArray[1]->abstract; }
}
#if DEFRULE_CONSTRUCT
if (patternMatchSpecified == FALSE)
{
if ((preclist->classArray[1]->system) && /* Change to cause */
(! abstract) && /* default pattern-match */
(DefclassData(theEnv)->ClassDefaultsMode == CONVENIENCE_MODE)) /* of classes to be */
{ reactive = TRUE; } /* reactive. */
else
{ reactive = preclist->classArray[1]->reactive; }
}
/* ================================================================
An abstract class cannot have direct instances, thus it makes no
sense for it to be reactive since it will have no objects to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -