From d83c2a84550221c30a48647fde9c433c65af1802 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Tue, 25 Jan 2000 16:44:21 -0200 Subject: performance details. --- llex.c | 171 ++++++++++++++++++++++++++++++++------------------------------ llex.h | 4 +- lobject.c | 17 ++++--- lparser.c | 87 +++++++++++++++++--------------- 4 files changed, 146 insertions(+), 133 deletions(-) diff --git a/llex.c b/llex.c index 49f22860..cd67103e 100644 --- a/llex.c +++ b/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 1.47 1999/12/22 16:58:36 roberto Exp roberto $ +** $Id: llex.c,v 1.48 1999/12/30 12:40:29 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -33,7 +33,7 @@ /* ORDER RESERVED */ static const char *const reserved [] = {"and", "do", "else", "elseif", "end", "function", "if", "local", "nil", "not", "or", "repeat", "return", "then", - "until", "while"}; + "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", ""}; void luaX_init (lua_State *L) { @@ -57,9 +57,15 @@ void luaX_syntaxerror (LexState *ls, const char *s, const char *token) { } -void luaX_error (LexState *ls, const char *s) { - save(ls->L, '\0'); - luaX_syntaxerror(ls, s, luaL_buffer(ls->L)); +void luaX_error (LexState *ls, const char *s, int token) { + char buff[TOKEN_LEN]; + luaX_token2str(token, buff); + if (buff[0] == '\0') { + save(ls->L, '\0'); + luaX_syntaxerror(ls, s, luaL_buffer(ls->L)); + } + else + luaX_syntaxerror(ls, s, buff); } @@ -156,7 +162,7 @@ static void ifskip (lua_State *L, LexState *LS) { if (LS->current == '\n') inclinenumber(L, LS); else if (LS->current == EOZ) - luaX_error(LS, "input ends inside a $if"); + luaX_error(LS, "input ends inside a $if", EOS); else next(LS); } } @@ -231,13 +237,13 @@ static void inclinenumber (lua_State *L, LexState *LS) { -static int read_long_string (lua_State *L, LexState *LS) { +static void read_long_string (lua_State *L, LexState *LS) { int cont = 0; for (;;) { switch (LS->current) { case EOZ: - luaX_error(LS, "unfinished long string"); - return EOS; /* to avoid warnings */ + luaX_error(LS, "unfinished long string", STRING); + break; /* to avoid warnings */ case '[': save_and_next(L, LS); if (LS->current == '[') { @@ -264,7 +270,52 @@ static int read_long_string (lua_State *L, LexState *LS) { save_and_next(L, LS); /* skip the second ']' */ LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+2), L->Mbuffnext-L->Mbuffbase-4); - return STRING; +} + + +static void read_string (lua_State *L, LexState *LS, int del) { + save_and_next(L, LS); + while (LS->current != del) { + switch (LS->current) { + case EOZ: case '\n': + luaX_error(LS, "unfinished string", STRING); + break; /* to avoid warnings */ + case '\\': + next(LS); /* do not save the '\' */ + switch (LS->current) { + case 'a': save(L, '\a'); next(LS); break; + case 'b': save(L, '\b'); next(LS); break; + case 'f': save(L, '\f'); next(LS); break; + case 'n': save(L, '\n'); next(LS); break; + case 'r': save(L, '\r'); next(LS); break; + case 't': save(L, '\t'); next(LS); break; + case 'v': save(L, '\v'); next(LS); break; + case '\n': save(L, '\n'); inclinenumber(L, LS); break; + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + int c = 0; + int i = 0; + do { + c = 10*c + (LS->current-'0'); + next(LS); + } while (++i<3 && isdigit(LS->current)); + if (c != (unsigned char)c) + luaX_error(LS, "escape sequence too large", STRING); + save(L, c); + break; + } + default: /* handles \\, \", \', and \? */ + save(L, LS->current); + next(LS); + } + break; + default: + save_and_next(L, LS); + } + } + save_and_next(L, LS); /* skip delimiter */ + LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+1), + L->Mbuffnext-L->Mbuffbase-2); } @@ -283,10 +334,9 @@ int luaX_lex (LexState *LS) { continue; case '-': - save_and_next(L, LS); + next(LS); if (LS->current != '-') return '-'; do { next(LS); } while (LS->current != '\n' && LS->current != EOZ); - luaL_resetbuffer(L); continue; case '[': @@ -294,88 +344,41 @@ int luaX_lex (LexState *LS) { if (LS->current != '[') return '['; else { save_and_next(L, LS); /* pass the second '[' */ - return read_long_string(L, LS); + read_long_string(L, LS); + return STRING; } case '=': - save_and_next(L, LS); + next(LS); if (LS->current != '=') return '='; - else { save_and_next(L, LS); return EQ; } + else { next(LS); return EQ; } case '<': - save_and_next(L, LS); + next(LS); if (LS->current != '=') return '<'; - else { save_and_next(L, LS); return LE; } + else { next(LS); return LE; } case '>': - save_and_next(L, LS); + next(LS); if (LS->current != '=') return '>'; - else { save_and_next(L, LS); return GE; } + else { next(LS); return GE; } case '~': - save_and_next(L, LS); + next(LS); if (LS->current != '=') return '~'; - else { save_and_next(L, LS); return NE; } + else { next(LS); return NE; } case '"': - case '\'': { - int del = LS->current; - save_and_next(L, LS); - while (LS->current != del) { - switch (LS->current) { - case EOZ: - case '\n': - luaX_error(LS, "unfinished string"); - return EOS; /* to avoid warnings */ - case '\\': - next(LS); /* do not save the '\' */ - switch (LS->current) { - case 'a': save(L, '\a'); next(LS); break; - case 'b': save(L, '\b'); next(LS); break; - case 'f': save(L, '\f'); next(LS); break; - case 'n': save(L, '\n'); next(LS); break; - case 'r': save(L, '\r'); next(LS); break; - case 't': save(L, '\t'); next(LS); break; - case 'v': save(L, '\v'); next(LS); break; - case '\n': save(L, '\n'); inclinenumber(L, LS); break; - default : { - if (isdigit(LS->current)) { - int c = 0; - int i = 0; - do { - c = 10*c + (LS->current-'0'); - next(LS); - } while (++i<3 && isdigit(LS->current)); - if (c != (unsigned char)c) - luaX_error(LS, "escape sequence too large"); - save(L, c); - } - else { /* handles \, ", ', and ? */ - save(L, LS->current); - next(LS); - } - break; - } - } - break; - default: - save_and_next(L, LS); - } - } - save_and_next(L, LS); /* skip delimiter */ - LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+1), - L->Mbuffnext-L->Mbuffbase-2); + case '\'': + read_string(L, LS, LS->current); return STRING; - } case '.': save_and_next(L, LS); - if (LS->current == '.') - { - save_and_next(L, LS); - if (LS->current == '.') - { - save_and_next(L, LS); + if (LS->current == '.') { + next(LS); + if (LS->current == '.') { + next(LS); return DOTS; /* ... */ } else return CONC; /* .. */ @@ -392,14 +395,14 @@ int luaX_lex (LexState *LS) { save_and_next(L, LS); if (LS->current == '.') { save(L, '.'); - luaX_error(LS, - "ambiguous syntax (decimal point x string concatenation)"); + luaX_error(LS, "ambiguous syntax" + " (decimal point x string concatenation)", NUMBER); } } fraction: /* LUA_NUMBER */ while (isdigit(LS->current)) save_and_next(L, LS); - if (toupper(LS->current) == 'E') { + if (LS->current == 'e' || LS->current == 'E') { save_and_next(L, LS); /* read 'E' */ if (LS->current == '+' || LS->current == '-') save_and_next(L, LS); /* optional exponent sign */ @@ -408,23 +411,25 @@ int luaX_lex (LexState *LS) { } save(L, '\0'); if (!luaO_str2d(L->Mbuffer+L->Mbuffbase, &LS->seminfo.r)) - luaX_error(LS, "malformed number"); + luaX_error(LS, "malformed number", NUMBER); return NUMBER; case EOZ: if (LS->iflevel > 0) - luaX_error(LS, "input ends inside a $if"); + luaX_error(LS, "input ends inside a $if", EOS); return EOS; + case '_': goto tname; + default: - if (LS->current != '_' && !isalpha(LS->current)) { + if (!isalpha(LS->current)) { int c = LS->current; if (iscntrl(c)) luaX_invalidchar(LS, c); - save_and_next(L, LS); + next(LS); return c; } - else { /* identifier or reserved word */ + tname: { /* identifier or reserved word */ TaggedString *ts; do { save_and_next(L, LS); diff --git a/llex.h b/llex.h index ffa53aa5..918b4125 100644 --- a/llex.h +++ b/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.15 1999/11/22 13:12:07 roberto Exp roberto $ +** $Id: llex.h,v 1.16 1999/12/27 17:33:22 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -63,7 +63,7 @@ void luaX_init (lua_State *L); void luaX_setinput (lua_State *L, LexState *LS, ZIO *z); int luaX_lex (LexState *LS); void luaX_syntaxerror (LexState *ls, const char *s, const char *token); -void luaX_error (LexState *ls, const char *s); +void luaX_error (LexState *ls, const char *s, int token); void luaX_token2str (int token, char *s); diff --git a/lobject.c b/lobject.c index 6aa92d0a..d89e2211 100644 --- a/lobject.c +++ b/lobject.c @@ -1,5 +1,5 @@ /* -** $Id: lobject.c,v 1.28 1999/12/23 18:19:57 roberto Exp roberto $ +** $Id: lobject.c,v 1.29 1999/12/30 18:28:40 roberto Exp roberto $ ** Some generic functions over Lua objects ** See Copyright Notice in lua.h */ @@ -87,9 +87,9 @@ int luaO_str2d (const char *s, real *result) { /* LUA_NUMBER */ int point = 0; /* number of decimal digits */ int sig; while (isspace((unsigned char)*s)) s++; - sig = 1; + sig = 0; switch (*s) { - case '-': sig = -1; /* go through */ + case '-': sig = 1; /* go through */ case '+': s++; } if (! (isdigit((unsigned char)*s) || @@ -104,20 +104,21 @@ int luaO_str2d (const char *s, real *result) { /* LUA_NUMBER */ point++; } } - a *= sig; - if (toupper((unsigned char)*s) == 'E') { + if (sig) a = -a; + if (*s == 'e' || *s == 'E') { int e = 0; s++; - sig = 1; + sig = 0; switch (*s) { - case '-': sig = -1; /* go through */ + case '-': sig = 1; /* go through */ case '+': s++; } if (!isdigit((unsigned char)*s)) return 0; /* no digit in the exponent? */ do { e = 10*e + (*(s++)-'0'); } while (isdigit((unsigned char)*s)); - point -= sig*e; + if (sig) e = -e; + point -= e; } while (isspace((unsigned char)*s)) s++; if (*s != '\0') return 0; /* invalid trailing characters? */ diff --git a/lparser.c b/lparser.c index 664795c6..ec655a99 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.54 2000/01/12 16:24:39 roberto Exp roberto $ +** $Id: lparser.c,v 1.55 2000/01/25 13:57:18 roberto Exp roberto $ ** LL(1) Parser and code generator for Lua ** See Copyright Notice in lua.h */ @@ -119,11 +119,16 @@ static void exp1 (LexState *ls); +static void luaY_error (LexState *ls, const char *msg) { + luaX_error(ls, msg, ls->token); +} + + static void checklimit (LexState *ls, int val, int limit, const char *msg) { if (val > limit) { char buff[100]; sprintf(buff, "too many %.50s (limit=%d)", msg, limit); - luaX_error(ls, buff); + luaY_error(ls, buff); } } @@ -145,7 +150,7 @@ static void deltastack (LexState *ls, int delta) { fs->stacksize += delta; if (fs->stacksize > fs->maxstacksize) { if (fs->stacksize > MAX_BYTE) - luaX_error(ls, "function/expression too complex"); + luaY_error(ls, "function/expression too complex"); fs->maxstacksize = fs->stacksize; } } @@ -160,7 +165,7 @@ static void code_oparg_at (LexState *ls, int pc, OpCode op, code[pc+1] = (Byte)arg; } else if (arg > MAX_ARG) - luaX_error(ls, "code too long"); + luaY_error(ls, "code too long"); else { /* MAX_BYTE < arg < MAX_ARG */ if (arg > MAX_WORD) { code[pc] = (Byte)LONGARG; @@ -599,20 +604,6 @@ static void close_func (LexState *ls) { } - -static const int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT, - DO, NAME, LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';', - EOS, ',', 0}; - - -static int is_in (int tok, const int *toks) { - const int *t; - for (t=toks; *t; t++) - if (*t == tok) return t-toks; - return -1; -} - - static void next (LexState *ls) { ls->token = luaX_lex(ls); } @@ -622,12 +613,12 @@ static void error_expected (LexState *ls, int token) { char buff[100], t[TOKEN_LEN]; luaX_token2str(token, t); sprintf(buff, "`%.20s' expected", t); - luaX_error(ls, buff); + luaY_error(ls, buff); } static void error_unexpected (LexState *ls) { - luaX_error(ls, "unexpected token"); + luaY_error(ls, "unexpected token"); } @@ -641,7 +632,7 @@ static void error_unmatched (LexState *ls, int what, int who, int where) { luaX_token2str(who, t_who); sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)", t_what, t_who, where); - luaX_error(ls, buff); + luaY_error(ls, buff); } } @@ -661,7 +652,7 @@ static void check_match (LexState *ls, int what, int who, int where) { static int checkname (LexState *ls) { int sc; if (ls->token != NAME) - luaX_error(ls, " expected"); + luaY_error(ls, " expected"); sc = string_constant(ls, ls->fs, ls->seminfo.ts); next(ls); return sc; @@ -691,7 +682,7 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) { next(&lexstate); /* read first token */ chunk(&lexstate); if (lexstate.token != EOS) - luaX_error(&lexstate, " expected"); + luaY_error(&lexstate, " expected"); close_func(&lexstate); return funcstate.f; } @@ -782,7 +773,7 @@ static int funcparams (LexState *ls, int slf, vardesc *v) { break; default: - luaX_error(ls, "function arguments expected"); + luaY_error(ls, "function arguments expected"); break; } code_setname(ls, v); @@ -871,7 +862,7 @@ static void recfield (LexState *ls) { check(ls, ']'); break; - default: luaX_error(ls, " or `[' expected"); + default: luaY_error(ls, " or `[' expected"); } check(ls, '='); exp1(ls); @@ -977,7 +968,7 @@ static void constructor (LexState *ls) { next(ls); constructor_part(ls, &other_cd); if (cd.k == other_cd.k) /* repeated parts? */ - luaX_error(ls, "invalid constructor syntax"); + luaY_error(ls, "invalid constructor syntax"); nelems += other_cd.n; } check_match(ls, '}', '{', line); @@ -992,8 +983,8 @@ static void constructor (LexState *ls) { /* ** {====================================================================== ** For parsing expressions, we use a classic stack with priorities. -** Each binary operator is represented by its index in `binop' + FIRSTBIN -** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1. +** Each binary operator is represented by an index: EQ=2, NE=3, ... '^'=13. +** The unary NOT is 0 and UNMINUS is 1. ** ======================================================================= */ @@ -1008,8 +999,6 @@ static void constructor (LexState *ls) { */ #define POW 13 -static const int binop [] = {EQ, NE, '>', '<', LE, GE, CONC, - '+', '-', '*', '/', '^', 0}; static const int priority [POW+1] = {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6}; @@ -1024,10 +1013,31 @@ typedef struct stack_op { } stack_op; +/* +** returns the index of a binary operator +*/ +static int binop (int op) { + switch (op) { + case EQ: return FIRSTBIN; + case NE: return FIRSTBIN+1; + case '>': return FIRSTBIN+2; + case '<': return FIRSTBIN+3; + case LE: return FIRSTBIN+4; + case GE: return FIRSTBIN+5; + case CONC: return FIRSTBIN+6; + case '+': return FIRSTBIN+7; + case '-': return FIRSTBIN+8; + case '*': return FIRSTBIN+9; + case '/': return FIRSTBIN+10; + case '^': return FIRSTBIN+11; + default: return -1; + } +} + static void push (LexState *ls, stack_op *s, int op) { if (s->top >= MAXOPS) - luaX_error(ls, "expression too complex"); + luaY_error(ls, "expression too complex"); s->ops[s->top++] = op; } @@ -1086,7 +1096,7 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) { return; default: - luaX_error(ls, " expected"); + luaY_error(ls, " expected"); return; } v->k = VEXP; v->info = 0; @@ -1108,8 +1118,7 @@ static void arith_exp (LexState *ls, vardesc *v) { int op; s.top = 0; prefixexp(ls, v, &s); - while ((op = is_in(ls->token, binop)) >= 0) { - op += FIRSTBIN; + while ((op = binop(ls->token)) >= 0) { lua_pushvar(ls, v); /* '^' is right associative, so must 'simulate' a higher priority */ pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]); @@ -1129,8 +1138,6 @@ static void exp1 (LexState *ls) { vardesc v; expr(ls, &v); lua_pushvar(ls, &v); - if (is_in(ls->token, expfollow) < 0) - luaX_error(ls, "malformed expression"); } @@ -1180,7 +1187,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) { next(ls); var_or_func(ls, &nv); if (nv.k == VEXP) - luaX_error(ls, "syntax error"); + luaY_error(ls, "syntax error"); left = assignment(ls, &nv, nvars+1); } else { /* assignment -> '=' explist1 */ @@ -1313,7 +1320,7 @@ static void namestat (LexState *ls) { var_or_func(ls, &v); if (v.k == VEXP) { /* stat -> func */ if (v.info == 0) /* is just an upper value? */ - luaX_error(ls, "syntax error"); + luaY_error(ls, "syntax error"); close_exp(ls, v.info, 0); } else { /* stat -> ['%'] NAME assignment */ @@ -1410,14 +1417,14 @@ static void parlist (LexState *ls) { case NAME: /* tailparlist -> NAME [',' tailparlist] */ goto init; - default: luaX_error(ls, " or `...' expected"); + default: luaY_error(ls, " or `...' expected"); } } break; case ')': break; /* parlist -> empty */ - default: luaX_error(ls, " or `...' expected"); + default: luaY_error(ls, " or `...' expected"); } code_args(ls, nparams, dots); } -- cgit v1.2.3-55-g6feb