2
* Motif Tools Library, Version 3.1
5
* Written by David Flanagan.
6
* Copyright (c) 1992-2001 by David Flanagan.
7
* All Rights Reserved. See the file COPYRIGHT for details.
8
* This is open source software. See the file LICENSE for details.
9
* There is no warranty for this software. See NO_WARRANTY for details.
12
* Revision 1.1.1.1 2001/07/18 11:06:02 root
15
* Revision 1.2 2001/06/12 16:25:28 andre
16
* *** empty log message ***
23
#include <Xmt/Lexer.h>
25
#if NeedFunctionPrototypes
26
XmtLexer XmtLexerCreate(String *keywords, int num_keywords)
28
XmtLexer XmtLexerCreate(keywords, num_keywords)
33
XmtLexer lexer = XtNew(XmtLexerRec);
36
lexer->token = XmtLexerNone;
39
lexer->keywords = keywords;
40
lexer->num_keywords = num_keywords;
44
#if NeedFunctionPrototypes
45
void XmtLexerDestroy(XmtLexer lexer)
47
void XmtLexerDestroy(lexer)
51
XtFree((char *)lexer);
54
#if NeedFunctionPrototypes
55
void XmtLexerInit(XmtLexer lexer, StringConst str)
57
void XmtLexerInit(lexer, str)
63
lexer->token = XmtLexerNone;
68
#if NeedFunctionPrototypes
69
XmtLexerToken _XmtLexerGetToken(XmtLexer l)
71
XmtLexerToken _XmtLexerGetToken(l)
80
l->token = XmtLexerNone;
83
l->token = XmtLexerEndOfString;
88
while (isspace((int)*l->c)) l->c++;
90
/* check for end-of-string */
92
l->token = XmtLexerEndOfString;
96
/* check punctuation */
98
case '(': l->token = XmtLexerLParen; break;
99
case ')': l->token = XmtLexerRParen; break;
100
case '[': l->token = XmtLexerLBracket; break;
101
case ']': l->token = XmtLexerRBracket; break;
102
case '{': l->token = XmtLexerLBrace; break;
103
case '}': l->token = XmtLexerRBrace; break;
104
case '<': l->token = XmtLexerLess; break;
105
case '>': l->token = XmtLexerGreater; break;
106
case '+': l->token = XmtLexerPlus; break;
107
case '-': l->token = XmtLexerMinus; break;
108
case '*': l->token = XmtLexerAsterisk; break;
109
case '/': l->token = XmtLexerSlash; break;
110
case '|': l->token = XmtLexerBar; break;
111
case '=': l->token = XmtLexerEqual; break;
112
case '#': l->token = XmtLexerSharp; break;
113
case '~': l->token = XmtLexerTwiddle; break;
114
case '%': l->token = XmtLexerPercent; break;
115
case '$': l->token = XmtLexerDollar; break;
116
case '.': l->token = XmtLexerPeriod; break;
117
case '^': l->token = XmtLexerCaret; break;
118
case ':': l->token = XmtLexerColon; break;
119
case ';': l->token = XmtLexerSemicolon; break;
120
case ',': l->token = XmtLexerComma; break;
123
if (l->token != XmtLexerNone) {
128
if (isdigit((int)*l->c)) {
130
while (isdigit((int)*l->c)) {
132
total += (int)(*l->c - '0');
135
l->token = XmtLexerInteger;
138
else if (*l->c == '"') { /* its a string */
141
while((*l->c != '\0') && (*l->c != '"')) {
142
if ((*l->c == '\\') && (*(l->c+1) != '\0'))
147
XmtWarningMsg("XmtLexer", "badString",
148
"unterminated string.");
149
l->token = XmtLexerError;
154
l->strval = XtMalloc(len+1);
155
strncpy(l->strval, mark, len);
156
l->strval[len] = '\0';
158
l->token = XmtLexerString;
161
else if (isalnum(*l->c) || (*l->c == '_')) {
162
/* its an ident. Figure out how long and copy it. */
165
(isalnum((int)*l->c) || (*l->c == '_'));
167
l->strval = XtMalloc(len+1);
168
strncpy(l->strval, mark, len);
169
l->strval[len] = '\0';
172
/* now go see if it is a keyword. */
173
keyword = XmtBSearch(l->strval, l->keywords, l->num_keywords);
177
l->token = XmtLexerKeyword;
179
l->strval = l->keywords[keyword];
182
l->token = XmtLexerIdent;
184
else { /* otherwise it is an unrecognized character. */
185
XmtWarningMsg("XmtLexer", "badChar",
186
"unrecognized character `%c'.",
189
l->token = XmtLexerError;
196
* Scan from the current lexer location until an unquoted character
197
* from the delimiters string is encountered. Copy the string and return
198
* XmtLexerString. If include is True, include the delimiter, otherwise
199
* don't. If the end of string is found return XmtLexerEndOfString.
202
#if NeedFunctionPrototypes
203
XmtLexerToken XmtLexerScan(XmtLexer l, StringConst delimiters,
204
XmtWideBoolean include)
206
XmtLexerToken XmtLexerScan(l, delimiters, include)
208
StringConst delimiters;
213
Boolean instring = False;
216
l->token = XmtLexerEndOfString;
217
return XmtLexerEndOfString;
220
for(c = l->c; *c; c++) {
222
for(d = delimiters; *d && (*d != *c); d++);
225
if ((*c == '\\') && *(c+1)) c++;
226
else if (*c == '"') instring = !instring;
231
l->token = XmtLexerEndOfString;
232
return XmtLexerEndOfString;
236
* if include is True, we include the terminating delimiter.
240
l->intval = c - l->c;
241
l->strval = XtMalloc(l->intval +1);
242
strncpy(l->strval, l->c, l->intval);
243
l->strval[l->intval] = '\0';
245
l->token = XmtLexerString;
246
return XmtLexerString;
249
#if NeedFunctionPrototypes
250
static String GetArg(XmtLexer l)
252
static String GetArg(l)
264
* This procedure breaks the XmtLexer abstraction and scans the
265
* string directly. It should only be called when the last token
269
/* skip whitespace */
270
XmtLexerSkipWhite(l);
272
/* special case for procedures with 0 args */
277
/* scan to an unquoted, unnested comma or right paren */
280
for(c = l->c; *c; c++) {
281
if (*c == '\0') break;
282
else if (!instring && parenlevel<=0 && (*c == ',' || *c == ')')) break;
283
else if (*c == '"') instring = !instring;
284
else if (!instring && *c == '(') parenlevel++;
285
else if (!instring && *c == ')') parenlevel--;
286
else if ((*c == '\\') && (*(c+1) != '\0')) c++;
289
/* back up over any whitespace */
290
while(isspace(*(c-1))) c--;
292
/* allocate space for a copy of the arg */
293
len = (int) (c - l->c);
294
arg = XtMalloc(len+1);
296
/* copy it, unquoting things */
297
for(s = l->c, t = arg; s < c; s++) {
298
if (*s == '\\') *t++ = *++s;
302
/* and terminate the string */
305
/* put the lexer back in a known state */
307
l->token = XmtLexerNone;
312
#if NeedFunctionPrototypes
313
Boolean XmtLexerGetArgList(XmtLexer l, String *args,
314
Cardinal max_args, Cardinal *num_args)
316
Boolean XmtLexerGetArgList(l, args, max_args, num_args)
325
/* if no '(', then no arguments, but this is not an error. */
326
if (XmtLexerGetToken(l) != XmtLexerLParen) {
331
/* otherwise eat the lparen */
332
XmtLexerConsumeToken(l);
334
/* now loop through the arguments */
337
/* make sure we haven't overflowed */
338
if (*num_args >= max_args) {
339
XmtWarningMsg("_XmtParseArgList", "tooMany",
340
"too many arguments in argument list.");
344
/* get the next argument */
345
args[*num_args] = GetArg(l);
346
if (args[*num_args]) *num_args += 1;
348
/* consume a comma or a right paren */
349
tok = XmtLexerGetToken(l);
350
if (tok == XmtLexerRParen) {
351
XmtLexerConsumeToken(l);
354
else if (tok == XmtLexerComma)
355
XmtLexerConsumeToken(l);
357
XmtWarningMsg("_XmtParseArgList", "syntax",
358
"syntax error in argument list");
364
/* read past closing ')' */
365
while(((tok = XmtLexerGetToken(l)) != XmtLexerEndOfString) &&
366
(tok != XmtLexerRParen))
367
XmtLexerConsumeToken(l);
368
XmtLexerConsumeToken(l);