macro processor: introduce colon operator with three args

This introduces a shift/reduce compilation warning in the macro processor because at expr COLON expr . COLON expr the parser doesn’t know whether to shift or reduce
issue#70
Houtan Bastani 2019-07-15 14:59:49 -04:00
parent ae0a91256a
commit 866e4d6d39
No known key found for this signature in database
GPG Key ID: 000094FB955BE169
2 changed files with 33 additions and 29 deletions

View File

@ -531,38 +531,29 @@ Array::eval()
{
if (arr.empty() && range1 && range2)
{
DoublePtr range1int = dynamic_pointer_cast<Double>(range1->eval());
DoublePtr range2int = dynamic_pointer_cast<Double>(range2->eval());
if (!range1int || !range2int)
DoublePtr range1dbl = dynamic_pointer_cast<Double>(range1->eval());
DoublePtr range2dbl = dynamic_pointer_cast<Double>(range2->eval());
if (!range1dbl || !range2dbl)
throw StackTrace("To create an array from a range using the colon operator, "
"both arguments must be doubles");
"the arguments must evaluate to doubles");
DoublePtr incdbl = make_shared<Double>(1, env);
if (increment)
{
auto incrementp = dynamic_pointer_cast<Double>(increment->eval());
if (*incrementp == 0)
throw StackTrace("the increment cannot be equal to zero");
if (*range1int <= *range2int)
if (*incrementp < 0)
throw StackTrace("In this case the increment cannot be negative");
else
for (int i = *range1int; i <= *range2int; i += *incrementp)
arr.emplace_back(make_shared<Double>(i, env));
else
if (*incrementp > 0)
throw StackTrace("In this case the increment cannot be positive");
else
for (int i = *range1int; i >= *range2int; i += *incrementp)
arr.emplace_back(make_shared<Double>(i, env));
incdbl = dynamic_pointer_cast<Double>(increment->eval());
if (!incdbl)
throw StackTrace("To create an array from a range using the colon operator, "
"the increment must evaluate to a double");
}
else
for (int i = *range1int; i <= *range2int; i++)
if (*incdbl > 0 && *range1dbl < *range2dbl)
for (double i = *range1dbl; i <= *range2dbl; i += *incdbl)
arr.emplace_back(make_shared<Double>(i, env));
else if (*range1dbl > *range2dbl && *incdbl < 0)
for (double i = *range1dbl; i >= *range2dbl; i += *incdbl)
arr.emplace_back(make_shared<Double>(i, env));
range1 = nullptr;
increment = nullptr;
range2 = nullptr;
range1 = increment = range2 = nullptr;
}
vector<ExpressionPtr> retval;

View File

@ -70,7 +70,7 @@ using namespace macro;
%left EQUAL_EQUAL NOT_EQUAL
%left LESS GREATER LESS_EQUAL GREATER_EQUAL
%nonassoc IN
%nonassoc COLON
%left COLON
%left UNION
%left INTERSECTION
%left PLUS MINUS
@ -88,7 +88,7 @@ using namespace macro;
%type <VariablePtr> symbol
%type <vector<VariablePtr>> comma_name
%type <vector<ExpressionPtr>> comma_expr function_args tuple_comma_expr
%type <vector<ExpressionPtr>> comma_expr function_args tuple_comma_expr colon_expr
%%
@ -278,6 +278,12 @@ tuple_comma_expr : %empty
{ $1.emplace_back($3); $$ = $1; }
;
colon_expr : expr COLON expr
{ $$ = vector<ExpressionPtr>{$1, $3}; }
| colon_expr COLON expr
{ $1.emplace_back($3); $$ = $1; }
;
expr : LPAREN expr RPAREN
{ $$ = $2; }
| symbol
@ -292,8 +298,15 @@ expr : LPAREN expr RPAREN
{ $$ = make_shared<Double>($1, driver.env, @$); }
| QUOTED_STRING
{ $$ = make_shared<String>($1, driver.env, @$); }
| expr COLON expr
{ $$ = make_shared<Array>($1, $3, driver.env, @$); }
| colon_expr
{
if ($1.size() == 2)
$$ = make_shared<Array>($1[0], $1[1], driver.env, @$);
else if ($1.size() == 3)
$$ = make_shared<Array>($1[0], $1[1], $1[2], driver.env, @$);
else
error(@$, "The colon operator only works with 2 or 3 arguments");
}
| LBRACKET comma_expr RBRACKET
{ $$ = make_shared<Array>($2, driver.env, @$); }
| symbol LBRACKET comma_expr RBRACKET