-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathanalyse.c
executable file
·147 lines (126 loc) · 4.28 KB
/
analyse.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
//********************************************************************
// Analyse.h
//--------------------------------------------------------------------
//
// Lexical analyser for a generic compiler, based on Martin Davies's
// "Code compilation" article in Personal Computer World of Sep '88.
//
//--------------------------------------------------------------------
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include "analyse.h"
#include "symboltable.h"
#include "Boolean.h"
//------------------------- Constant Decl. --------------------------
#define kBufferSize 30 // size of input buffer
//------------------------- Module Globals ---------------------------
static int gLineNo = 1; // current line no.
TOKEN gTokenVal;
//-------------------------External Globals---------------------------
extern SymTabType *gSymbolTable[]; // the symbol table itself
extern int gNoOfSymbols; // number of entries
//********************************************************************
// Error : print an error message.
//--------------------------------------------------------------------
void Error ( char *message)
{
printf("%s Line: %d\n", message, gLineNo);
}
//********************************************************************
// Lex : the main lexical analysis procedure, reads in a token from
// the input file and returns the token's value.
//
// Parameter fp is a file already opened for reading, pointing to the
// next character to be read;
//--------------------------------------------------------------------
TOKEN Lex(FILE *fp)
{
int tokenSize; // size of token found
char ident[kBufferSize]; // declare buffer
static Boolean unGetChar = false; // set if the buffer is full
static int ch; // one character buffer (must be int to detect EOF)
while (true) {
if (!unGetChar)
ch = fgetc(fp);
else
unGetChar = false;
if ( isdigit(ch) ) {
// It's a digit so expect a decimal constant, work out its value and
// return the fact with NUM.
gTokenVal = 0;
while ( isdigit(ch)) {
gTokenVal = (ch - '0') + gTokenVal * 10;
ch = fgetc(fp);
}
unGetChar = true;
return( NUM );
}
else if (isalpha(ch)) {
// It's a letter so expect a Identifier/keyword.
tokenSize = 0;
do {
ident[tokenSize++] = ch;
ch = fgetc(fp);
} while ( (isalnum(ch) || (ch == '_')) && ( tokenSize < kBufferSize));
if (tokenSize >= kBufferSize) {
Error("Token too large.");
exit(1);
}
ident[tokenSize] = '\0'; // mark end of string
gTokenVal = FindSymbolStr(ident, gSymbolTable, gNoOfSymbols); // Is it in the symbol table?
if (gTokenVal == -1 ) { // if not then add it to table
SymTabType newSymbol;
newSymbol.entry = StrSave(ident);
newSymbol.t = ID;
gTokenVal = InsertSymbol(&newSymbol, gSymbolTable, &gNoOfSymbols);
unGetChar = true;
return (ID);
}
else {
unGetChar = true;
return (gSymbolTable[gTokenVal]->t);
}
}
else // must be a special character
{
switch (ch) {
case '(' : return(LBRACKET); break;
case ')' : return(RBRACKET); break;
case '*' : return(MULT) ; break;
case '/' : return(DIVI); break;
case '+' : return(PLUS); break;
case '-' : return(MINUS) ; break;
case ';' : return(SEMICOLON); break;
case '>' : return(GREATERTHAN); break;
case '=' : return(EQUALS); break;
case ':' : if ( (ch = fgetc(fp)) != '=')
Error("equals expected."); // expects ":=" assigment
else
return( BECOMES );
break;
case '\n': gLineNo++; break; // newline just increments line counter
case EOF : fclose(fp) ; return (DONE); break;
case '\t':
case ' ' :
case '\f': break;
default : Error("Unknown character."); break;
}
}
}
}
//**************************************************************************
// InitLex : add some reserved words to the symbol table before we start.
//--------------------------------------------------------------------------
void InitLex()
{
static SymTabType reservedSymbol[] =
{{"IF", TIF}, {"THEN", TTHEN}, {"ELSE", TELSE}, {"ENDIF", TENDIF}, {"REPEAT",TREPEAT},
{"UNTIL", TUNTIL}, {"BEGIN", TBEGIN}, {"END", TEND}};
#define kNoOfResWords 8
int i;
for (i = 0 ; i < kNoOfResWords ; i++) {
InsertSymbol(&reservedSymbol[i], gSymbolTable, &gNoOfSymbols);
}
}