X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=simgear%2Fnasal%2Flex.c;h=89c3c407b28c578181f07c4e460c684ea8fe591d;hb=bcb320b537b6f7e5e3724e8a30d309322171eb43;hp=73733e464c82604b3dc31097f26d15ba09bd0eb7;hpb=979d3da69c085733d573af7298a3fd95fb4574a3;p=simgear.git diff --git a/simgear/nasal/lex.c b/simgear/nasal/lex.c index 73733e46..89c3c407 100644 --- a/simgear/nasal/lex.c +++ b/simgear/nasal/lex.c @@ -1,7 +1,7 @@ #include "parse.h" // Static table of recognized lexemes in the language -struct Lexeme { +static const struct Lexeme { char* str; int tok; } LEXEMES[] = { @@ -109,7 +109,20 @@ static int lineEnd(struct Parser* p, int line) static void newToken(struct Parser* p, int pos, int type, char* str, int slen, double num) { - struct Token* tok; + struct Token *tok, *last = p->tree.lastChild; + + /* Adjacent string literals get concatenated */ + if(type == TOK_LITERAL && str) { + if(last && last->type == TOK_LITERAL) { + int i, len1 = last->strlen; + char* str2 = naParseAlloc(p, len1 + slen); + for(i=0; istr[i]; + for(i=0; istr = str2; + last->strlen += slen; + return; + } + } tok = naParseAlloc(p, sizeof(struct Token)); tok->type = type; @@ -117,19 +130,19 @@ static void newToken(struct Parser* p, int pos, int type, tok->str = str; tok->strlen = slen; tok->num = num; - tok->parent = &p->tree; tok->next = 0; - tok->prev = p->tree.lastChild; + tok->prev = last; tok->children = 0; tok->lastChild = 0; // Context sensitivity hack: a "-" following a binary operator of - // higher precedence (MUL and DIV, basically) must be a unary - // negation. Needed to get precedence right in the parser for - // expressiong like "a * -2" - if(type == TOK_MINUS && tok->prev) - if(tok->prev->type == TOK_MUL || tok->prev->type == TOK_DIV) + // equal or higher precedence must be a unary negation. Needed to + // get precedence right in the parser for expressiong like "a * -2" + if(type == TOK_MINUS && tok->prev) { + int pt = tok->prev->type; + if(pt==TOK_PLUS||pt==TOK_MINUS||pt==TOK_CAT||pt==TOK_MUL||pt==TOK_DIV) tok->type = type = TOK_NEG; + } if(!p->tree.children) p->tree.children = tok; if(p->tree.lastChild) p->tree.lastChild->next = tok; @@ -168,6 +181,7 @@ static void sqEscape(char* buf, int len, int index, struct Parser* p, } // Ditto, but more complicated for double quotes. +/* FIXME: need to handle \b (8), \f (12), and \uXXXX for JSON compliance */ static void dqEscape(char* buf, int len, int index, struct Parser* p, char* cOut, int* eatenOut) { @@ -179,6 +193,7 @@ static void dqEscape(char* buf, int len, int index, struct Parser* p, case 'n': *cOut = '\n'; break; case 't': *cOut = '\t'; break; case '\\': *cOut = '\\'; break; + case '`': *cOut = '`'; break; case 'x': if(len < 4) error(p, "unterminated string", index); *cOut = (char)((hexc(buf[2], p, index)<<4) | hexc(buf[3], p, index)); @@ -191,11 +206,12 @@ static void dqEscape(char* buf, int len, int index, struct Parser* p, } } -// FIXME: should handle UTF8 too static void charLiteral(struct Parser* p, int index, char* s, int len) { - if(len != 1) error(p, "character constant not single character", index); - newToken(p, index, TOK_LITERAL, 0, 0, *s); + int n, c; + c = naLexUtf8C(s, len, &n); + if(c < 0 || n != len) error(p, "invalid utf8 character constant", index); + newToken(p, index, TOK_LITERAL, 0, 0, c); } // Read in a string literal @@ -240,25 +256,27 @@ static int lexHexLiteral(struct Parser* p, int index) return i; } +#define ISNUM(c) ((c) >= '0' && (c) <= '9') +#define ISHEX(c) (ISNUM(c) || ((c)>='a' && (c)<='f') || ((c)>='A' && (c)<='F')) +#define NUMSTART(c) (ISNUM(c) || (c) == '+' || (c) == '-') static int lexNumLiteral(struct Parser* p, int index) { int len = p->len, i = index; unsigned char* buf = (unsigned char*)p->buf; double d; - if(i+1= '0' && buf[i] <= '9') i++; + while(i= '0' && buf[i] <= '9') i++; + while(i= '0' && buf[i+1] <= '9')) i++; - while(i= '0' && buf[i] <= '9') i++; + if(buf[i] == '-' || buf[i] == '+') i++; + while(ibuf + index, i - index, &d); newToken(p, index, TOK_LITERAL, 0, 0, d); @@ -338,7 +356,8 @@ void naLex(struct Parser* p) i = lexStringLiteral(p, i, c); break; default: - if(c >= '0' && c <= '9') i = lexNumLiteral(p, i); + if(ISNUM(c) || (c == '.' && (i+1)len && ISNUM(p->buf[i+1]))) + i = lexNumLiteral(p, i); else handled = 0; }