Ejemplo n.º 1
0
/*
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
** where `binop' is any binary operator with a priority higher than `limit'
*/
static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit)
{
    BinOpr op;
    UnOpr uop;
    enterlevel(ls);
    uop = getunopr(ls->t.token);
    if (uop != OPR_NOUNOPR)
    {
        luaX_next(ls);
        subexpr(ls, v, UNARY_PRIORITY);
        luaK_prefix(ls->fs, uop, v);
    }
    else simpleexp(ls, v);
    /* expand while operators have priorities higher than `limit' */
    op = getbinopr(ls->t.token);
    while (op != OPR_NOBINOPR && priority[op].left > limit)
    {
        expdesc v2;
        BinOpr nextop;
        luaX_next(ls);
        luaK_infix(ls->fs, op, v);
        /* read sub-expression with higher priority */
        nextop = subexpr(ls, &v2, priority[op].right);
        luaK_posfix(ls->fs, op, v, &v2);
        op = nextop;
    }
    leavelevel(ls);
    return op;  /* return first untreated operator */
}
Ejemplo n.º 2
0
/*
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
** where `binop' is any binary operator with a priority higher than `limit'
*/
static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit)
{
    callstack_ref cref( *ls->L );

    UnOpr uop = getunopr(ls->t.token);

    FuncState *fs = GetCurrentFuncState( ls );

    if (uop != OPR_NOUNOPR)
    {
        luaX_next(ls);
        subexpr(ls, v, UNARY_PRIORITY);
        luaK_prefix(fs, uop, v);
    }
    else
    {
        simpleexp(ls, v);
    }

    /* expand while operators have priorities higher than `limit' */
    BinOpr op = getbinopr(ls->t.token);

    while (op != OPR_NOBINOPR && priority[op].left > limit)
    {
        luaX_next(ls);
        luaK_infix(fs, op, v);
        /* read sub-expression with higher priority */
        expdesc v2;
        BinOpr nextop = subexpr(ls, &v2, priority[op].right);
        luaK_posfix(fs, op, v, &v2);
        op = nextop;
    }

    return op;  /* return first untreated operator */
}
Ejemplo n.º 3
0
long
ppexpr(int* pun)
{
	long	n;
	int	opeektoken;
	long	ppstate;

	ppstate = (pp.state & (CONDITIONAL|DISABLE|NOSPACE|STRIP));
	pp.state &= ~(DISABLE|STRIP);
	pp.state |= CONDITIONAL|NOSPACE;
	opeektoken = peektoken;
	peektoken = -1;
	*pun = 0;
	n = subexpr(0, pun);
	if (peektoken == ':' && !errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid use of :";
	if (errmsg)
	{
		error(2, "%s in expression", errmsg);
		errmsg = 0;
		n = 0;
	}
	peektoken = opeektoken;
	pp.state &= ~(CONDITIONAL|NOSPACE);
	pp.state |= ppstate;
	if (*pun) debug((-4, "ppexpr() = %luU", n));
	else debug((-4, "ppexpr() = %ld", n));
	return n;
}
Ejemplo n.º 4
0
static BinaryOperationsChain ParseBinaryOperatorsChain( const Lexems& lexems, Lexems::const_iterator& it )
{
	BinaryOperationsChain result;

	while( it < lexems.end() )
	{
		BinaryOperationsChain::ComponentWithOperator comp;

		switch (it->type)
		{
		case Lexem::Type::Identifier:
		case Lexem::Type::Scope:
			{
				std::unique_ptr<BinaryOperationsChain::Variable> var( new BinaryOperationsChain::Variable );
				var->name= ParseCombinedName( lexems, it );

				comp.component= std::move(var);
			}
			break;

		case Lexem::Type::BracketLeft:
			{
				it++;
				if( it == lexems.end()) throw LexicalError(lexems.back().file_position);

				std::unique_ptr<BinaryOperationsChain::BracketExpression> subexpr( new BinaryOperationsChain::BracketExpression );
				subexpr->subexpression.reset( new BinaryOperationsChain(ParseBinaryOperatorsChain( lexems, it )) );
				comp.component= std::move(subexpr);

				if( it->type != Lexem::Type::BracketRight ) throw LexicalError( it->file_position);
				it++;
			}
			break;

		case Lexem::Type::NumericConstant:
			{
				std::unique_ptr<BinaryOperationsChain::NumericConstant> num( new BinaryOperationsChain::NumericConstant );
				num->value= it->text;
				it++;

				comp.component= std::move(num);
			}
			break;

		default:
			goto end;
		};

		BinaryOperationsChain::Operator op= ParseBinaryOperator( it );
		comp.op= op;
		result.components.push_back(std::move(comp));

		if( op == BinaryOperationsChain::Operator::NoOperator ) break;
	}
	end:;

	return result;
}
Ejemplo n.º 5
0
static void expr (LexState *ls, expdesc *v) {
  subexpr(ls, v, 0);
}
Ejemplo n.º 6
0
static void primaryexp (LexState *ls, expdesc *v) {
  /* primaryexp ->
        prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */
  FuncState *fs = ls->fs;
  prefixexp(ls, v);
  for (;;) {
    switch (ls->t.token) {
      case '.': {  /* field */
        field(ls, v);
        break;
      }
      case '[': {  /* `[' exp1 `]' */
        expdesc key;
        luaK_exp2anyreg(fs, v);
        yindex(ls, &key);
        luaK_indexed(fs, v, &key);
        break;
      }
      case ':': {  /* `:' NAME funcargs */
        expdesc key;
        luaX_next(ls);
        checkname(ls, &key);
        luaK_self(fs, v, &key);
        funcargs(ls, v);
        break;
      }
#if LUA_WIDESTRING
      case '(': case TK_STRING: case TK_WSTRING: case '{': {  /* funcargs */
#else
      case '(': case TK_STRING: case '{': {  /* funcargs */
#endif /* LUA_WIDESTRING */
        luaK_exp2nextreg(fs, v);
        funcargs(ls, v);
        break;
      }
      default: return;
    }
  }
}


static void simpleexp (LexState *ls, expdesc *v) {
#if LUA_WIDESTRING
  /* simpleexp -> NUMBER | STRING | WSTRING | NIL | true | false | ... |
                  constructor | FUNCTION body | primaryexp */
#else
  /* simpleexp -> NUMBER | STRING | NIL | true | false | ... |
                  constructor | FUNCTION body | primaryexp */
#endif /* LUA_WIDESTRING */
  switch (ls->t.token) {
    case TK_NUMBER: {
      init_exp(v, VKNUM, 0);
      v->u.nval = ls->t.seminfo.r;
      break;
    }
    case TK_STRING: {
      codestring(ls, v, ls->t.seminfo.ts);
      break;
    }
#if LUA_WIDESTRING
    case TK_WSTRING: {
      codewstring(ls, v, ls->t.seminfo.ts);
      break;
    }
#endif /* LUA_WIDESTRING */
    case TK_NIL: {
      init_exp(v, VNIL, 0);
      break;
    }
    case TK_TRUE: {
      init_exp(v, VTRUE, 0);
      break;
    }
    case TK_FALSE: {
      init_exp(v, VFALSE, 0);
      break;
    }
    case TK_DOTS: {  /* vararg */
      FuncState *fs = ls->fs;
      check_condition(ls, fs->f->is_vararg,
                      "cannot use " LUA_QL("...") " outside a vararg function");
      fs->f->is_vararg &= ~VARARG_NEEDSARG;  /* don't need 'arg' */
      init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0));
      break;
    }
    case '{': {  /* constructor */
      constructor(ls, v);
      return;
    }
    case TK_FUNCTION: {
      luaX_next(ls);
      body(ls, v, 0, ls->linenumber);
      return;
    }
    default: {
      primaryexp(ls, v);
      return;
    }
  }
  luaX_next(ls);
}


static UnOpr getunopr (int op) {
  switch (op) {
    case TK_NOT: return OPR_NOT;
    case '-': return OPR_MINUS;
    case '#': return OPR_LEN;
    default: return OPR_NOUNOPR;
  }
}


static BinOpr getbinopr (int op) {
  switch (op) {
    case '+': return OPR_ADD;
    case '-': return OPR_SUB;
    case '*': return OPR_MUL;
    case '/': return OPR_DIV;
    case '%': return OPR_MOD;
#if LUA_BITFIELD_OPS
    case '&': return OPR_BAND;
    case '|': return OPR_BOR;
    case TK_XOR: return OPR_BXOR;
    case TK_SHL: return OPR_BSHL;
    case TK_SHR: return OPR_BSHR;
#endif /* LUA_BITFIELD_OPS */
    case '^': return OPR_POW;
    case TK_CONCAT: return OPR_CONCAT;
    case TK_NE: return OPR_NE;
    case TK_EQ: return OPR_EQ;
    case '<': return OPR_LT;
    case TK_LE: return OPR_LE;
    case '>': return OPR_GT;
    case TK_GE: return OPR_GE;
    case TK_AND: return OPR_AND;
    case TK_OR: return OPR_OR;
    default: return OPR_NOBINOPR;
  }
}


static const struct {
  lu_byte left;  /* left priority for each binary operator */
  lu_byte right; /* right priority */
} priority[] = {  /* ORDER OPR */
#if LUA_BITFIELD_OPS
   {8, 8}, {8, 8}, {8, 8}, {8, 8}, {8, 8},  /* bitwise operators */
#endif /* LUA_BITFIELD_OPS */
   {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7},  /* `+' `-' `/' `%' */
   {10, 9}, {5, 4},                 /* power and concat (right associative) */
   {3, 3}, {3, 3},                  /* equality and inequality */
   {3, 3}, {3, 3}, {3, 3}, {3, 3},  /* order */
   {2, 2}, {1, 1}                   /* logical (and/or) */
};

#define UNARY_PRIORITY	8  /* priority for unary operators */


/*
** subexpr -> (simpleexp | unop subexpr) { binop subexpr }
** where `binop' is any binary operator with a priority higher than `limit'
*/
static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) {
  BinOpr op;
  UnOpr uop;
  enterlevel(ls);
  uop = getunopr(ls->t.token);
  if (uop != OPR_NOUNOPR) {
    luaX_next(ls);
    subexpr(ls, v, UNARY_PRIORITY);
    luaK_prefix(ls->fs, uop, v);
  }
  else simpleexp(ls, v);
  /* expand while operators have priorities higher than `limit' */
  op = getbinopr(ls->t.token);
  while (op != OPR_NOBINOPR && priority[op].left > limit) {
    expdesc v2;
    BinOpr nextop;
    luaX_next(ls);
    luaK_infix(ls->fs, op, v);
    /* read sub-expression with higher priority */
    nextop = subexpr(ls, &v2, priority[op].right);
    luaK_posfix(ls->fs, op, v, &v2);
    op = nextop;
  }
  leavelevel(ls);
  return op;  /* return first untreated operator */
}
Ejemplo n.º 7
0
static void ICACHE_FLASH_ATTR expr (LexState *ls, expdesc *v) {
  subexpr(ls, v, 0);
}
Ejemplo n.º 8
0
static long
subexpr(register int precedence, int* pun)
{
	register int		c;
	register long		n;
	register long		x;
	register int		operand = 1;
	int			un = 0;
	int			xn;

	switch (lex(c))
	{
	case 0:
	case '\n':
		unlex(c);
		if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "more tokens expected";
		return 0;
	case '-':
		n = -subexpr(13, &un);
		break;
	case '+':
		n = subexpr(13, &un);
		break;
	case '!':
		n = !subexpr(13, &un);
		break;
	case '~':
		n = ~subexpr(13, &un);
		break;
	default:
		unlex(c);
		n = 0;
		operand = 0;
		break;
	}
	un <<= 1;
	for (;;)
	{
		switch (lex(c))
		{
		case 0:
		case '\n':
			goto done;
		case ')':
			if (!precedence)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "too many )'s";
				return 0;
			}
			goto done;
		case '(':
			n = subexpr(1, &un);
			if (lex(c) != ')')
			{
				unlex(c);
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "closing ) expected";
				return 0;
			}
		gotoperand:
			if (operand)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operator expected";
				return 0;
			}
			operand = 1;
			un <<= 1;
			continue;
		case '?':
			if (precedence > 1) goto done;
			un = 0;
			if (lex(c) == ':')
			{
				if (!n) n = subexpr(2, &un);
				else
				{
					x = pp.mode;
					pp.mode |= INACTIVE;
					subexpr(2, &xn);
					pp.mode = x;
				}
			}
			else
			{
				unlex(c);
				x = subexpr(2, &xn);
				if (lex(c) != ':')
				{
					unlex(c);
					if (!errmsg && !(pp.mode & INACTIVE)) errmsg = ": expected for ? operator";
					return 0;
				}
				if (n)
				{
					n = x;
					un = xn;
					subexpr(2, &xn);
				}
				else n = subexpr(2, &un);
			}
			break;
		case ':':
			goto done;
		case T_ANDAND:
		case T_OROR:
			xn = (c == T_ANDAND) ? 4 : 3;
			if (precedence >= xn) goto done;
			if ((n != 0) == (c == T_ANDAND)) n = subexpr(xn, &un) != 0;
			else
			{
				x = pp.mode;
				pp.mode |= INACTIVE;
				subexpr(xn, &un);
				pp.mode = x;
			}
			un = 0;
			break;
		case '|':
			if (precedence > 4) goto done;
			n |= subexpr(5, &un);
			break;
		case '^':
			if (precedence > 5) goto done;
			n ^= subexpr(6, &un);
			break;
		case '&':
			if (precedence > 6) goto done;
			n &= subexpr(7, &un);
			break;
		case T_EQ:
		case T_NE:
			if (precedence > 7) goto done;
			n = (n == subexpr(8, &un)) == (c == T_EQ);
			un = 0;
			break;
		case '<':
		case T_LE:
		case T_GE:
		case '>':
			if (precedence > 8) goto done;
			x = subexpr(9, &un);
			switch (c)
			{
			case '<':
				switch (un)
				{
				case 01:
					n = n < (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n < x;
					break;
				case 03:
					n = (unsigned long)n < (unsigned long)x;
					break;
				default:
					n = n < x;
					break;
				}
				break;
			case T_LE:
				switch (un)
				{
				case 01:
					n = n <= (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n <= x;
					break;
				case 03:
					n = (unsigned long)n <= (unsigned long)x;
					break;
				default:
					n = n <= x;
					break;
				}
				break;
			case T_GE:
				switch (un)
				{
				case 01:
					n = n >= (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n >= x;
					break;
				case 03:
					n = (unsigned long)n >= (unsigned long)x;
					break;
				default:
					n = n >= x;
					break;
				}
				break;
			case '>':
				switch (un)
				{
				case 01:
					n = n > (unsigned long)x;
					break;
				case 02:
					n = (unsigned long)n > x;
					break;
				case 03:
					n = (unsigned long)n > (unsigned long)x;
					break;
				default:
					n = n > x;
					break;
				}
				break;
			}
			un = 0;
			break;
		case T_LSHIFT:
		case T_RSHIFT:
			if (precedence > 9) goto done;
			x = subexpr(10, &un);
			if (c == T_LSHIFT) n <<= x;
			else n >>= x;
			un >>= 1;
			break;
		case '+':
		case '-':
			if (precedence > 10) goto done;
			x = subexpr(11, &un);
			if (c == '+') n += x;
			else n -= x;
			break;
		case '*':
		case '/':
		case '%':
			if (precedence > 11) goto done;
			x = subexpr(12, &un);
			if (c == '*') n *= x;
			else if (x == 0)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "divide by zero";
				return 0;
			}
			else if (c == '/') n /= x;
			else n %= x;
			break;
		case '#':
			pp.state |= DISABLE;
			c = pplex();
			pp.state &= ~DISABLE;
			if (c != T_ID)
			{
				if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "# must precede a predicate identifier";
				return 0;
			}
			n = predicate(0);
			goto gotoperand;
		case T_ID:
			n = predicate(1);
			goto gotoperand;
		case T_CHARCONST:
			c = *(pp.toknxt - 1);
			*(pp.toknxt - 1) = 0;
			n = chrtoi(pp.token + 1);
			*(pp.toknxt - 1) = c;
			if (n & ~((1<<CHAR_BIT)-1))
			{
				if (!(pp.mode & HOSTED))
					error(1, "'%s': multi-character character constants are not portable", pp.token);
			}
#if CHAR_MIN < 0
			else n = (char)n;
#endif
			goto gotoperand;
		case T_DECIMAL_U:
		case T_DECIMAL_UL:
		case T_OCTAL_U:
		case T_OCTAL_UL:
		case T_HEXADECIMAL_U:
		case T_HEXADECIMAL_UL:
			un |= 01;
			/*FALLTHROUGH*/
		case T_DECIMAL:
		case T_DECIMAL_L:
		case T_OCTAL:
		case T_OCTAL_L:
		case T_HEXADECIMAL:
		case T_HEXADECIMAL_L:
			n = strtoul(pp.token, NiL, 0);
			if ((unsigned long)n > LONG_MAX) un |= 01;
			goto gotoperand;
		case T_WCHARCONST:
			n = chrtoi(pp.token);
			goto gotoperand;
		default:
			if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "invalid token";
			return 0;
		}
		if (errmsg) return 0;
		if (!operand) goto nooperand;
	}
 done:
	unlex(c);
	if (!operand)
	{
	nooperand:
		if (!errmsg && !(pp.mode & INACTIVE)) errmsg = "operand expected";
		return 0;
	}
	if (un) *pun |= 01;
	return n;
}