📄 lexical.cpp
字号:
// Copyright (c) 1996 Federal Highway Administration
//
// This software has been developed for the Federal Highway Administration
// by Viggen Corporation under contract with Oak Ridge National Lab.
//
// Permission to use, copy, and distribute this software for any purpose
// without fee is hereby granted, provided that the above copyright notice
// appears in all copies and that both the copyright and this permission notice
// appear in the supporting documentation.
//
// Permission to modify this software is granted provided that the above
// copyright and this permission notice appears in the modified software.
//
// This software is provided "as is" with no warranty expressed or implied.
//
// For additional information, please go to the Web site www.ntcip.org.
//
/*******************************************************************************
*
* Copyright (c) 1997 Viggen Corporation
*
* Permission to use, copy, and distribute this software for any purpose
* without fee is hereby granted, provided that this copyright notice
* appears in all copies and this permission notice appears in the
* supporting documentation.
*
* Permission to modify this software is granted provided that the above
* copyright and this permission notice appears in the modified software.
*
******************************************************************************/
/*********************************************
*
* lexical.cpp
*
* 9/29/97 Glenn Pruitt
*********************************************/
#include <string>
using namespace std;
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <conio.h>
#include <alloc.h>
#include <windows.h>
#include <winbase.h>
#include "api.h"
#include "symboltab.h"
#include "stattab.h"
#include "executor.h"
#include "lexical.h"
#define TOKEN_SIZE 256
//locally declared functions
char *relop(FILE *fp, char *s, char ch);
char *identifier(FILE *fp, char *s, char ch);
//recursive descent predictive parser functions
int parse_program(char *filename);
int parse_statementlist(FILE *fp);
int parse_statement(FILE *fp);
int parse_declaration(FILE *fp);
int parse_statementblock(FILE *fp);
int parse_arglist(FILE *fp);
int parse_logicexpr(FILE *fp);
int parse_bool1(FILE *fp);
int parse_bool2(FILE *fp);
int parse_bool3(FILE *fp);
int parse_bool4(FILE *fp);
int parse_bool5(FILE *fp);
int parse_bool6(FILE *fp);
int parse_eprime(FILE *fp);
int parse_term(FILE *fp);
int parse_tprime(FILE *fp);
int parse_fneg(FILE *fp);
int parse_factor(FILE *fp);
int parse_identifier(FILE *fp);
int parse_string(FILE *fp);
int parse_float(FILE *fp);
int parse_integer(FILE *fp);
int _stdcall PrintMessage(char *message);
//Globally declared variables
struct SYTAB *symbol_table;
struct STTAB *statement_table;
int statement_index;
FILE *ofp; //output file pointer
int _stdcall (* LineActivityPntr) (char * theMessage);
int _stdcall (* EditByteStreamPntr) (pmppStruct *msg, char *header, char *trailer);
int _stdcall (* InputFromUserPntr) (char ** userInput, char *prompt, void *threadHandle);
int standalone;
HANDLE heapptr;
main()
{
standalone = 1;
heapptr = NULL;
first_pass("source.txt");
executor("source.txt", &symbol_table,
&statement_table, standalone, NULL, NULL);
HeapDestroy(heapptr);
}
void *safe_alloc(size_t items, size_t size)
{
LPVOID ptr;
if(heapptr == NULL)
{
heapptr = HeapCreate(HEAP_GENERATE_EXCEPTIONS,
65536, 0);
if(heapptr == NULL)
{
printf("Could Not Create Heap for Macro\n");
exit(0);
}
}
ptr = HeapAlloc(heapptr,HEAP_ZERO_MEMORY,items*size);
if(ptr)
return((void *)ptr);
else
{
// printf("HeapAlloc Failed...Compacting Heap Free Space\n");
if(HeapCompact(heapptr,0) > 0)
{
ptr = HeapAlloc(heapptr,HEAP_ZERO_MEMORY,items*size);
if(ptr)
{
// printf("Compaction & Allocation Successful\n");
return((void *)ptr);
}
}
/* if(HeapValidate(heapptr,0,NULL))
printf("Failed to allocate from valid Heap\n");
else
printf("Compaction failed...Corrupted Heap\n");
exit(0);*/
if(!HeapValidate(heapptr,0,NULL))
{
// printf("Compaction failed...Corrupted Heap\n");
exit(0);
}
// else
// printf("Failed to allocate from valid Heap\n");
}
return(NULL);
}
void safe_free(void *memobj)
{
HeapFree(heapptr,0,(LPVOID)memobj);
// free(memobj);
}
void run_macro(char *filename,
int _stdcall (* LineActivityInsert) (char * theMessage),
int _stdcall (* InputFromUser) (char ** userInput, char *prompt, void *threadHandle),
int _stdcall (* EditByteStream) (pmppStruct *msg, char *header, char *trailer))
{
heapptr = NULL;
standalone = 0;
LineActivityPntr = LineActivityInsert;
EditByteStreamPntr = EditByteStream;
InputFromUserPntr = InputFromUser;
// info_message("\nStarting first pass...");
first_pass(filename);
// info_message("First pass done\n");
executor(filename, &symbol_table,
&statement_table, standalone,
LineActivityPntr, EditByteStreamPntr);
info_message("\nAfter execution\n");
HeapDestroy(heapptr);
}
void first_pass(char *filename)
{
symbol_table = NULL;
statement_table = NULL;
statement_index = 0;
if(parse_program(filename))
{
info_message("File parsed successfully\n");
}
else
{
info_message("Invalid input file\n");
}
return;
}
void dump_structs(char *filename)
{
int i, max, stype, iv;
char *outbuff;
char *buffer;
info_message(" -- STATEMENT TABLE --\n");
buffer = (char *)safe_alloc(1024,sizeof(char));
outbuff = (char *)safe_alloc(1280,sizeof(char));
max = count_statements(statement_table);
for(i=0;i<max;i++)
{
buffer = get_statement_text(statement_table, i, filename, buffer);
trim(&buffer);
sprintf(outbuff,"index:%3d type:%d next:%3d jump:%3d text: %s\n",
i,get_statement_type(statement_table, i),
get_next_index(statement_table,i),
get_jump_index(statement_table,i),buffer);
info_message(outbuff);
memset(outbuff,'\0',strlen(outbuff));
memset(buffer,'\0',1024);
}
info_message(" -- SYMBOL TABLE --\n");
max = count_symbols(symbol_table);
memset(outbuff,'\0',strlen(outbuff));
memset(buffer,'\0',1024);
for(i=0;i<max;i++)
{
buffer = get_identifier(symbol_table, i, buffer);
trim(&buffer);
stype = get_symbol_type(symbol_table, i);
iv = get_invar(symbol_table,i);
if(stype == 1)
{
sprintf(outbuff,"index:%3d label value:%3d\t ident: %s invar: %d\n",
i, get_symbol_offset_value(symbol_table,i),buffer,iv);
info_message(outbuff);
}
if(stype == 2)
{
sprintf(outbuff,"index:%3d int value:%ld\t ident: %s invar: %d\n",
i, get_symbol_int_value(symbol_table,i),buffer,iv);
info_message(outbuff);
}
if(stype == 3)
{
sprintf(outbuff,"index:%3d float value:%g\t ident: %s invar: %d\n",
i, get_symbol_float_value(symbol_table,i),buffer,iv);
info_message(outbuff);
}
if(stype == 4)
{
sprintf(outbuff,"index:%3d string[%d] value:\"%s\"\t ident: %s invar %d\n",
i, get_symbol_string_size(symbol_table,i),
get_symbol_string_value(symbol_table,i),buffer,iv);
info_message(outbuff);
}
memset(outbuff,'\0',strlen(outbuff));
memset(buffer,'\0',1024);
}
safe_free(outbuff);
safe_free(buffer);
}
void trim(char **input)
{
char *temp;
char *ptr;
temp = (char *)safe_alloc(strlen(*input) +1,sizeof(char));
ptr = *input;
while(*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r')
ptr++;
strcpy(temp,ptr);
ptr = &(temp[strlen(temp) -1]);
while(*ptr == ' ' || *ptr == '\t' || *ptr == '\n' || *ptr == '\r')
{
*ptr = '\0';
ptr = &(temp[strlen(temp) -1]);
}
strcpy(*input,temp);
safe_free(temp);
}
bool isitalpha(char c)
{
if((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))
return(true);
else
return(false);
}
//Print a message and exit program
void error_message(char *message)
{
if(standalone)
printf(message);
else
LineActivityPntr(message);
exit(0);
}
//Print a message and return control
void info_message(char *message)
{
if(standalone)
printf(message);
else
LineActivityPntr(message);
return;
}
//Print a message and return control
int _stdcall PrintMessage(char *message)
{
LineActivityPntr(message);
return(0);
}
int _stdcall GetInput(char **message, char *prompt, void *thread)
{
InputFromUserPntr(message, prompt, thread);
return(0);
}
//This function will return the next token from the
//current position of the input file pointer
char *get_next_token(FILE *fp, char *token)
{
char ch;
int len;
int fail = 0;
//Consume initial whitespace
ch = (char)getc(fp);
while( !feof(fp) && (ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r'))
{
ch = (char)getc(fp);
}
//Check end of file condition
if(feof(fp))
return(token);
//construct a single character token if possible
if(ch == ';' || ch == '[' || ch == ']' || ch == '(' ||
ch == ')' || ch == ',' || ch == '+' || ch == '-' ||
ch == '*' || ch == '/' || ch == '.' || ch == '"')
{
len = strlen(token);
token[len] = ch;
return(token);
}
//construct a relational operator token if possible
if(ch == '=' || ch == '&' || ch == '|' || ch == '>' ||
ch == '<' || ch == '!')
{
token = relop(fp,token,ch);
if(strlen(token) > 0)
return(token);
else
fail = 1;
}
//return an identifier or function name token
if(!fail)
return(identifier(fp,token,ch));
else
return(token);
}
//Only used internally by get_next_token
char *relop(FILE *fp, char *s, char ch)
{
char text[256];
char next;
long int filepos;
int len;
filepos = ftell(fp);
if(feof(fp))
return(s);
len = strlen(s);
s[len] = ch;
next = (char)getc(fp);
//Test all acceptance states
if(ch == '=' && next == '=')
{
len = strlen(s);
s[len] = next;
return(s);
}
if(ch == '=' && next != '=')
{
fseek(fp,filepos,SEEK_SET);
return(s);
}
if(ch == '&' && next == '&')
{
len = strlen(s);
s[len] = next;
return(s);
}
if(ch == '|' && next == '|')
{
len = strlen(s);
s[len] = next;
return(s);
}
if(ch == '>' && next == '=')
{
len = strlen(s);
s[len] = next;
return(s);
}
if(ch == '>' && next != '=')
{
fseek(fp,filepos,SEEK_SET);
return(s);
}
if(ch == '<' && next == '=')
{
len = strlen(s);
s[len] = next;
return(s);
}
if(ch == '<' && next != '=')
{
fseek(fp,filepos,SEEK_SET);
return(s);
}
if(ch == '!' && next == '=')
{
len = strlen(s);
s[len] = next;
return(s);
}
if(ch == '!' && next != '=')
{
fseek(fp,filepos,SEEK_SET);
return(s);
}
//Invalid input sequence
info_message("Error in input file bad relational operator\n");
strcpy(text,"Character ");
strcat(text, s);
strcat(text," consumed\n");
info_message(text);
fseek(fp,filepos,SEEK_SET);
strcpy(s,"");
return(s);
}
//Only used internally by get_next_token
char *identifier(FILE *fp, char *s, char ch)
{
long int filepos;
int len;
int done;
filepos = ftell(fp);
done = 0;
//while not EOF or whitespace
while(!done)
{
if(feof(fp))
done = 1;
else
{
//look for whitespace
if(ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r')
{
//consume trailing whitespace
while(ch == ' ' || ch == '\n' || ch == '\t' || ch == '\r')
{
ch = (char)getc(fp);
}
//pushback last character
filepos = ftell(fp);
fseek(fp,filepos - 1,SEEK_SET);
done = 1;
}
//look for punctuation
else
{
if(ch == ';' || ch == '[' || ch == ']' || ch == '(' ||
ch == ')' || ch == ',' || ch == '+' || ch == '-' ||
ch == '*' || ch == '/' || ch == '.' || ch == '=' ||
ch == '&' || ch == '|' || ch == '>' || ch == '<' ||
ch == '!' || ch == '"')
{
//pushback last character
fseek(fp, filepos - 1, SEEK_SET);
done = 1;
}
//therefore it must be an alpha-numeric
else
{
len = strlen(s);
s[len] = ch;
ch = (char)getc(fp);
filepos = ftell(fp);
}
}
}
}
return(s);
}
//Top level parser function
int parse_program(char *filename)
{
FILE *fp;
char *token;
int max,i;
fp = fopen(filename,"rt");
if(parse_statementlist(fp))
{
token = (char *)safe_alloc(TOKEN_SIZE,sizeof(char));
token = get_next_token(fp,token);
if(strlen(token) == 0)
{
safe_free(token);
fclose(fp);
//Set references in statement table
// to the last+1 statement to -1
max = count_statements(statement_table);
for(i=0;i<max;i++)
if(max == get_next_index(statement_table,i))
set_next_index_to_null(statement_table,i);
return(1);
}
else
{
info_message("Parsing terminated before end of file.\n");
safe_free(token);
fclose(fp);
return(0);
}
}
else
{
fclose(fp);
return(0);
}
}
int parse_statementlist(FILE *fp)
{
char *token;
long fpos;
int i;
if(parse_statement(fp))
{
//get current file position
fpos = ftell(fp);
//allocate space and get a token
token = (char *)safe_alloc(TOKEN_SIZE,sizeof(char));
token = get_next_token(fp, token);
if(strcmp(token,";")==0)
{
//update file position
//fpos = ftell(fp); not needed?
if(parse_statementlist(fp))
{
//production statementlist::statement;statementlist
safe_free(token);
return(1);
}
else
{
//production statementlist::statement;
safe_free(token);
//The following statement alters the "next_statement" field
//of the previous statement in the statement table.
//this is done because that statement was the last of
//a statement list and should have no "next_statement"
// set_next_index_to_null(statement_table,statement_index-1);
for(i=0;i<statement_index;i++)
if(statement_exists(statement_table,i))
if(get_next_index(statement_table,i)==statement_index)
set_next_index_to_null(statement_table,i);
return(1);
}
}
else
{
//production statementlist::statement
//pushback token
fseek(fp,fpos,SEEK_SET);
safe_free(token);
//The following statement alters the "next_statement" field
//of the previous statement in the statement table.
//this is done because that statement was the last of
//a statement list and should have no "next_statement"
// set_next_index_to_null(statement_table,statement_index-1);
for(i=0;i<statement_index;i++)
if(statement_exists(statement_table,i))
if(get_next_index(statement_table,i)==statement_index)
set_next_index_to_null(statement_table,i);
return(1);
}
}
else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -