📄 scanner.c
字号:
/*******************************************************/
/* "C" Language Integrated Production System */
/* */
/* CLIPS Version 6.20 01/31/02 */
/* */
/* SCANNER MODULE */
/*******************************************************/
/*************************************************************/
/* Purpose: Routines for scanning lexical tokens from an */
/* input source. */
/* */
/* Principal Programmer(s): */
/* Gary D. Riley */
/* */
/* Contributing Programmer(s): */
/* Chris Culbert */
/* Brian Donnell */
/* */
/* Revision History: */
/* */
/*************************************************************/
#define _SCANNER_SOURCE_
#include <ctype.h>
#include <stdio.h>
#define _STDIO_INCLUDED_
#include <string.h>
#include <limits.h>
#include "setup.h"
#include "constant.h"
#include "envrnmnt.h"
#include "router.h"
#include "symbol.h"
#include "utility.h"
#include "memalloc.h"
#include "scanner.h"
#include <stdlib.h>
/***************************************/
/* LOCAL INTERNAL FUNCTION DEFINITIONS */
/***************************************/
static void *ScanSymbol(void *,char *,int,unsigned short *);
static void *ScanString(void *,char *);
static void ScanNumber(void *,char *,struct token *);
static void DeallocateScannerData(void *);
/************************************************/
/* InitializeScannerData: Allocates environment */
/* data for scanner routines. */
/************************************************/
globle void InitializeScannerData(
void *theEnv)
{
AllocateEnvironmentData(theEnv,SCANNER_DATA,sizeof(struct scannerData),DeallocateScannerData);
}
/**************************************************/
/* DeallocateScannerData: Deallocates environment */
/* data for scanner routines. */
/**************************************************/
static void DeallocateScannerData(
void *theEnv)
{
if (ScannerData(theEnv)->GlobalMax != 0)
{ genfree(theEnv,ScannerData(theEnv)->GlobalString,ScannerData(theEnv)->GlobalMax); }
}
/***********************************************************************/
/* GetToken: Reads next token from the input stream. The pointer to */
/* the token data structure passed as an argument is set to contain */
/* the type of token (e.g., symbol, string, integer, etc.), the data */
/* value for the token (i.e., a symbol table location if it is a */
/* symbol or string, an integer table location if it is an integer), */
/* and the pretty print representation. */
/***********************************************************************/
globle void GetToken(
void *theEnv,
char *logicalName,
struct token *theToken)
{
int inchar;
unsigned short type;
/*=======================================*/
/* Set Unknown default values for token. */
/*=======================================*/
theToken->type = UNKNOWN_VALUE;
theToken->value = NULL;
theToken->printForm = "unknown";
ScannerData(theEnv)->GlobalPos = 0;
ScannerData(theEnv)->GlobalMax = 0;
/*==============================================*/
/* Remove all white space before processing the */
/* GetToken() request. */
/*==============================================*/
inchar = EnvGetcRouter(theEnv,logicalName);
while ((inchar == ' ') || (inchar == '\n') || (inchar == '\f') ||
(inchar == '\r') || (inchar == ';') || (inchar == '\t'))
{
/*=======================*/
/* Remove comment lines. */
/*=======================*/
if (inchar == ';')
{
inchar = EnvGetcRouter(theEnv,logicalName);
while ((inchar != '\n') && (inchar != '\r') && (inchar != EOF) )
{ inchar = EnvGetcRouter(theEnv,logicalName); }
}
inchar = EnvGetcRouter(theEnv,logicalName);
}
/*==========================*/
/* Process Symbolic Tokens. */
/*==========================*/
if (isalpha(inchar))
{
theToken->type = SYMBOL;
EnvUngetcRouter(theEnv,inchar,logicalName);
theToken->value = (void *) ScanSymbol(theEnv,logicalName,0,&type);
theToken->printForm = ValueToString(theToken->value);
}
/*===============================================*/
/* Process Number Tokens beginning with a digit. */
/*===============================================*/
else if (isdigit(inchar))
{
EnvUngetcRouter(theEnv,inchar,logicalName);
ScanNumber(theEnv,logicalName,theToken);
}
else switch (inchar)
{
/*========================*/
/* Process String Tokens. */
/*========================*/
case '"':
theToken->value = (void *) ScanString(theEnv,logicalName);
theToken->type = STRING;
theToken->printForm = StringPrintForm(theEnv,ValueToString(theToken->value));
break;
/*=======================================*/
/* Process Tokens that might be numbers. */
/*=======================================*/
case '-':
case '.':
case '+':
EnvUngetcRouter(theEnv,inchar,logicalName);
ScanNumber(theEnv,logicalName,theToken);
break;
/*===================================*/
/* Process ? and ?<variable> Tokens. */
/*===================================*/
case '?':
inchar = EnvGetcRouter(theEnv,logicalName);
if (isalpha(inchar)
#if DEFGLOBAL_CONSTRUCT
|| (inchar == '*'))
#else
)
#endif
{
EnvUngetcRouter(theEnv,inchar,logicalName);
theToken->value = (void *) ScanSymbol(theEnv,logicalName,0,&type);
theToken->type = SF_VARIABLE;
#if DEFGLOBAL_CONSTRUCT
if ((ValueToString(theToken->value)[0] == '*') &&
(((int) strlen(ValueToString(theToken->value))) > 1) &&
(ValueToString(theToken->value)[strlen(ValueToString(theToken->value)) - 1] == '*'))
{
size_t count;
theToken->type = GBL_VARIABLE;
theToken->printForm = AppendStrings(theEnv,"?",ValueToString(theToken->value));
count = strlen(ScannerData(theEnv)->GlobalString);
ScannerData(theEnv)->GlobalString[count-1] = EOS;
theToken->value = EnvAddSymbol(theEnv,ScannerData(theEnv)->GlobalString+1);
ScannerData(theEnv)->GlobalString[count-1] = (char) inchar;
}
else
#endif
theToken->printForm = AppendStrings(theEnv,"?",ValueToString(theToken->value));
}
else
{
theToken->type = SF_WILDCARD;
theToken->value = (void *) EnvAddSymbol(theEnv,"?");
EnvUngetcRouter(theEnv,inchar,logicalName);
theToken->printForm = "?";
}
break;
/*=====================================*/
/* Process $? and $?<variable> Tokens. */
/*=====================================*/
case '$':
if ((inchar = EnvGetcRouter(theEnv,logicalName)) == '?')
{
inchar = EnvGetcRouter(theEnv,logicalName);
if (isalpha(inchar)
#if DEFGLOBAL_CONSTRUCT
|| (inchar == '*'))
#else
)
#endif
{
EnvUngetcRouter(theEnv,inchar,logicalName);
theToken->value = (void *) ScanSymbol(theEnv,logicalName,0,&type);
theToken->type = MF_VARIABLE;
#if DEFGLOBAL_CONSTRUCT
if ((ValueToString(theToken->value)[0] == '*') &&
((int) (strlen(ValueToString(theToken->value))) > 1) &&
(ValueToString(theToken->value)[strlen(ValueToString(theToken->value)) - 1] == '*'))
{
size_t count;
theToken->type = MF_GBL_VARIABLE;
theToken->printForm = AppendStrings(theEnv,"$?",ValueToString(theToken->value));
count = strlen(ScannerData(theEnv)->GlobalString);
ScannerData(theEnv)->GlobalString[count-1] = EOS;
theToken->value = EnvAddSymbol(theEnv,ScannerData(theEnv)->GlobalString+1);
ScannerData(theEnv)->GlobalString[count-1] = (char) inchar;
}
else
#endif
theToken->printForm = AppendStrings(theEnv,"$?",ValueToString(theToken->value));
}
else
{
theToken->type = MF_WILDCARD;
theToken->value = (void *) EnvAddSymbol(theEnv,"$?");
theToken->printForm = "$?";
EnvUngetcRouter(theEnv,inchar,logicalName);
}
}
else
{
theToken->type = SYMBOL;
ScannerData(theEnv)->GlobalString = ExpandStringWithChar(theEnv,'$',ScannerData(theEnv)->GlobalString,&ScannerData(theEnv)->GlobalPos,&ScannerData(theEnv)->GlobalMax,ScannerData(theEnv)->GlobalMax+80);
EnvUngetcRouter(theEnv,inchar,logicalName);
theToken->value = (void *) ScanSymbol(theEnv,logicalName,1,&type);
theToken->printForm = ValueToString(theToken->value);
}
break;
/*============================*/
/* Symbols beginning with '<' */
/*============================*/
case '<':
theToken->type = SYMBOL;
ScannerData(theEnv)->GlobalString = ExpandStringWithChar(theEnv,'<',ScannerData(theEnv)->GlobalString,&ScannerData(theEnv)->GlobalPos,&ScannerData(theEnv)->GlobalMax,ScannerData(theEnv)->GlobalMax+80);
theToken->value = (void *) ScanSymbol(theEnv,logicalName,1,&type);
theToken->printForm = ValueToString(theToken->value);
break;
/*=============================================*/
/* Process "(", ")", "~", "|", and "&" Tokens. */
/*=============================================*/
case '(':
theToken->type = LPAREN;
theToken->value = (void *) EnvAddSymbol(theEnv,"(");
theToken->printForm = "(";
break;
case ')':
theToken->type= RPAREN;
theToken->value = (void *) EnvAddSymbol(theEnv,")");
theToken->printForm = ")";
break;
case '~':
theToken->type = NOT_CONSTRAINT;
theToken->value = (void *) EnvAddSymbol(theEnv,"~");
theToken->printForm = "~";
break;
case '|':
theToken->type = OR_CONSTRAINT;
theToken->value = (void *) EnvAddSymbol(theEnv,"|");
theToken->printForm = "|";
break;
case '&':
theToken->type = AND_CONSTRAINT;
theToken->value = (void *) EnvAddSymbol(theEnv,"&");
theToken->printForm = "&";
break;
/*============================*/
/* Process End-of-File Token. */
/*============================*/
case EOF:
case 0:
case 3:
theToken->type = STOP;
theToken->value = (void *) EnvAddSymbol(theEnv,"stop");
theToken->printForm = "";
break;
/*=======================*/
/* Process Other Tokens. */
/*=======================*/
default:
if (isprint(inchar))
{
EnvUngetcRouter(theEnv,inchar,logicalName);
theToken->value = (void *) ScanSymbol(theEnv,logicalName,0,&type);
theToken->type = type;
theToken->printForm = ValueToString(theToken->value);
}
else
{ theToken->printForm = "<<<unprintable character>>>"; }
break;
}
/*===============================================*/
/* Put the new token in the pretty print buffer. */
/*===============================================*/
#if (! RUN_TIME) && (! BLOAD_ONLY)
if (theToken->type == INSTANCE_NAME)
{
SavePPBuffer(theEnv,"[");
SavePPBuffer(theEnv,theToken->printForm);
SavePPBuffer(theEnv,"]");
}
else
{ SavePPBuffer(theEnv,theToken->printForm); }
#endif
/*=========================================================*/
/* Return the temporary memory used in scanning the token. */
/*=========================================================*/
if (ScannerData(theEnv)->GlobalString != NULL)
{
rm(theEnv,ScannerData(theEnv)->GlobalString,ScannerData(theEnv)->GlobalMax);
ScannerData(theEnv)->GlobalString = NULL;
ScannerData(theEnv)->GlobalMax = 0;
ScannerData(theEnv)->GlobalPos = 0;
}
return;
}
/*************************************/
/* ScanSymbol: Scans a symbol token. */
/*************************************/
static void *ScanSymbol(
void *theEnv,
char *logicalName,
int count,
unsigned short *type)
{
int inchar;
#if OBJECT_SYSTEM
void *symbol;
#endif
/*=====================================*/
/* Scan characters and add them to the */
/* symbol until a delimiter is found. */
/*=====================================*/
inchar = EnvGetcRouter(theEnv,logicalName);
while ( (inchar != '<') && (inchar != '"') &&
(inchar != '(') && (inchar != ')') &&
(inchar != '&') && (inchar != '|') && (inchar != '~') &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -