diff options
Diffstat (limited to 'iup/src/iup_ledlex.c')
-rwxr-xr-x | iup/src/iup_ledlex.c | 366 |
1 files changed, 366 insertions, 0 deletions
diff --git a/iup/src/iup_ledlex.c b/iup/src/iup_ledlex.c new file mode 100755 index 0000000..3283a43 --- /dev/null +++ b/iup/src/iup_ledlex.c @@ -0,0 +1,366 @@ +/** \file + * \brief lexical analysis manager for LED + * + * See Copyright Notice in "iup.h" + */ + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <errno.h> + +#include "iup.h" + +#include "iup_class.h" +#include "iup_ledlex.h" +#include "iup_str.h" +#include "iup_table.h" +#include "iup_register.h" + + +static struct /* lexical variables */ +{ + const char* filename; /* file name */ + const char* f; + FILE* file; /* file handle */ + int token; /* lookahead iLexToken */ + char name[40960]; /* lexical identifier value */ + float number; /* lexical number value */ + int line; /* line number */ + Iclass *ic; /* control class when func is CONTROL_ */ +} ilex = {NULL, NULL, NULL, 0, "", (float) 0.0, 0, NULL}; + +static int iLexGetChar (void); +static int iLexToken(int *erro); +static int iLexCapture (char* dlm); +static int iLexSkip (char* dlm); +static int iLexCaptureAttr (void); + +int iupLexStart(const char* filename, int is_file) /* initialize lexical analysis */ +{ + ilex.filename = filename; + if (is_file) + { + ilex.file = fopen (ilex.filename,"r"); + if (!ilex.file) + return iupLexError (IUPLEX_FILENOTOPENED, filename); + } + else + { + ilex.f = ilex.filename; + ilex.file = NULL; + } + ilex.line = 0; + ilex.line = 1; + return iupLexAdvance(); +} + +void iupLexClose(void) +{ + if (!ilex.file) + return; + fclose (ilex.file); + ilex.file = NULL; +} + +static void iLexUngetc(int c) +{ + if (ilex.file) + ungetc(c, ilex.file); + else + { + if (*ilex.f != 0) + *(char*)ilex.f = (char)c; /* write back to the string ???? */ + } +} + +static int iLexGetc(void) +{ + if (ilex.file) + return getc(ilex.file); + else + { + if (*ilex.f != 0) + ilex.f++; + if (*ilex.f == 0) + return EOF; + return *ilex.f; + } +} + +int iupLexLookAhead(void) +{ + return ilex.token; +} + +int iupLexAdvance(void) +{ + int erro = 0; + ilex.token = iLexToken(&erro); + return erro; +} + +int iupLexFollowedBy(int t) +{ + return (ilex.token==t); +} + +int iupLexMatch(int t) +{ + if (ilex.token==t) + return iupLexAdvance(); + else + return iupLexError (IUPLEX_NOTMATCH, ilex.token, t); +} + + +int iupLexSeenMatch(int t, int *erro) +{ + if (ilex.token==t) + { + *erro = iupLexAdvance(); + return 1; + } + else + return 0; +} + +unsigned char iupLexByte(void) +{ + unsigned int b; + sscanf(ilex.name,"%u", &b); /* read as integer to avoid reading number as characters */ + if (b>255) b = 255; + return (unsigned char)b; +} + +int iupLexInt(void) +{ + int i; + sscanf(ilex.name,"%d", &i); + return i; +} + +float iupLexFloat(void) +{ + float f; + sscanf(ilex.name,"%g", &f); + return f; +} + +char* iupLexGetName(void) +{ + if (ilex.name) + return iupStrDup(ilex.name); + else + return NULL; +} + +char* iupLexName(void) +{ + return ilex.name; +} + +float iupLexGetNumber(void) +{ + return ilex.number; +} + +Iclass *iupLexGetClass(void) +{ + return ilex.ic; +} + +static int iLexToken(int *erro) +{ + for (;;) + { + int c = iLexGetChar(); + switch (c) + { + case 26: + case EOF: + return IUPLEX_TK_END; + + case ']': + return IUPLEX_TK_ENDATTR; + + case '#': /* iLexSkip comment */ + case '%': /* iLexSkip comment */ + iLexSkip ("\n\r"); + continue; + + case ' ': /* ignore whitespace */ + case '\t': + case '\n': + case '\r': + case '\f': + case '\v': + continue; + + case '=': /* attribuicao */ + return IUPLEX_TK_SET; + + case ',': + return IUPLEX_TK_COMMA; + + case '(': /* begin parameters */ + return IUPLEX_TK_BEGP; + + case ')': /* end parameters */ + return IUPLEX_TK_ENDP; + + case '[': /* attributes */ + if (iLexCaptureAttr() == IUPLEX_TK_END) + { + *erro=iupLexError (IUPLEX_NOTENDATTR); + return 0; + } + return IUPLEX_TK_ATTR; + + case '\"': /* string */ + iLexCapture ("\""); + return IUPLEX_TK_STR; + + case '\'': /* string */ + iLexCapture ("\'"); + return IUPLEX_TK_STR; + + default: + if (c > 32) /* identifier */ + { + char class_name[50]; + iLexUngetc(c); + iLexUngetc(iLexCapture ("=[](), \t\n\r\f\v")); + iupStrLower(class_name, iupLexName()); + ilex.ic = iupRegisterFindClass(class_name); + if (ilex.ic) + return IUPLEX_TK_FUNC; + else + return IUPLEX_TK_NAME; + } + } + return c; + } +} + +static int iLexCapture (char* dlm) +{ + int i=0; + int c; + do + { + c = iLexGetChar (); + if (i < sizeof(ilex.name)) + ilex.name[i++] = (char) c; + } while ((c > 0) && !strchr (dlm,c)); + ilex.name[i-1]='\0'; /* discard delimiter */ + return c; /* return delimiter */ +} + +static int iLexCaptureAttr (void) +{ + int i=0; + int c; + int aspas=0; + do + { + c = iLexGetChar (); + if (i < sizeof(ilex.name)) + ilex.name[i++] = (char) c; + if (c == '"') + ++aspas; + } while ((c > 0) && ((aspas & 1) || c != ']')); + ilex.name[i-1]='\0'; /* discard delimiter */ + return c; /* return delimiter */ +} + +static int iLexSkip (char* dlm) +{ + int c; + do + { + c = iLexGetChar (); + } while ((c > 0) && !strchr (dlm,c)); + return c; /* return delimiter */ +} + +static int iLexGetChar (void) +{ + int c = iLexGetc(); if (c == '\n') ++ilex.line; + if (c == '\\') + { + c = iLexGetc(); + if (c == 'n') + return '\n'; + else if (c == '\\') + return '\\'; + } + return c; +} + +static char* iupTokenStr(int t) +{ + switch (t) + { + case IUPLEX_TK_END : return "end of file"; + case IUPLEX_TK_BEGP : return "("; + case IUPLEX_TK_ENDP : return ")"; + case IUPLEX_TK_ATTR : return "["; + case IUPLEX_TK_STR : return "string"; + case IUPLEX_TK_NAME : return "identifier"; + case IUPLEX_TK_NUMB : return "number"; + case IUPLEX_TK_SET : return "="; + case IUPLEX_TK_COMMA: return ","; + case IUPLEX_TK_FUNC : return "function"; + case IUPLEX_TK_ENDATTR : return "]"; + } + return ""; +} + +static char ilex_erromsg[10240]; + +char *iupLexGetError(void) +{ + return ilex_erromsg; +} + +int iupLexError (int n, ...) +{ + char msg[10240]; + va_list va; + va_start(va,n); + switch (n) + { + case IUPLEX_FILENOTOPENED: + { + char *fn=va_arg(va,char *); + sprintf (msg, "cannot open file %s", fn); + } + break; + case IUPLEX_NOTMATCH: + { + int tr=va_arg(va,int); /* iLexToken read */ + int te=va_arg(va,int); /* iLexToken expected */ + char *str=iupTokenStr(tr); + char *ste=iupTokenStr(te); + sprintf (msg, "expected %s but found %s", ste, str); + } + break; + case IUPLEX_NOTENDATTR: + { + sprintf (msg, "missing ']'"); + } + break; + case IUPLEX_PARSEERROR: + { + char* s=va_arg(va,char*); /* iLexToken expected */ + sprintf(msg,"%.*s",(int)(sizeof(msg)-1),s); + } + break; + } + va_end(va); + sprintf(ilex_erromsg, "led(%s): bad input at line %d - %s\n", ilex.filename, ilex.line, msg); + return n; +} |