Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 35 additions & 18 deletions compiler/src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -9068,26 +9068,28 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseMulExp()
{
const loc = token.loc;
auto e = parseUnaryExp();

while (1)
{
switch (token.value)
{
case TOK.mul:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseUnaryExp();
e = new AST.MulExp(loc, e, e2);
continue;

case TOK.div:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseUnaryExp();
e = new AST.DivExp(loc, e, e2);
continue;

case TOK.mod:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseUnaryExp();
e = new AST.ModExp(loc, e, e2);
Expand All @@ -9103,26 +9105,28 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseAddExp()
{
const loc = token.loc;
auto e = parseMulExp();

while (1)
{
switch (token.value)
{
case TOK.add:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseMulExp();
e = new AST.AddExp(loc, e, e2);
continue;

case TOK.min:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseMulExp();
e = new AST.MinExp(loc, e, e2);
continue;

case TOK.tilde:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseMulExp();
e = new AST.CatExp(loc, e, e2);
Expand All @@ -9138,26 +9142,28 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseShiftExp()
{
const loc = token.loc;
auto e = parseAddExp();

while (1)
{
switch (token.value)
{
case TOK.leftShift:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAddExp();
e = new AST.ShlExp(loc, e, e2);
continue;

case TOK.rightShift:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAddExp();
e = new AST.ShrExp(loc, e, e2);
continue;

case TOK.unsignedRightShift:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAddExp();
e = new AST.UshrExp(loc, e, e2);
Expand All @@ -9173,8 +9179,6 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseCmpExp()
{
const loc = token.loc;

auto e = parseShiftExp();
EXP op = EXP.reserved;

Expand All @@ -9183,6 +9187,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.equal: op = EXP.equal; goto Lequal;
case TOK.notEqual: op = EXP.notEqual; goto Lequal;
Lequal:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseShiftExp();
e = new AST.EqualExp(op, loc, e, e2);
Expand All @@ -9194,6 +9199,7 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
const tv = peekNext();
if (tv == TOK.in_)
{
const loc = token.loc; // Capture operator's location
nextToken();
nextToken();
auto e2 = parseShiftExp();
Expand All @@ -9203,12 +9209,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
}
if (tv != TOK.is_)
break;
const loc = token.loc; // Capture operator's location
nextToken();
op = EXP.notIdentity;
goto Lidentity;
}
case TOK.is_: op = EXP.identity; goto Lidentity;
Lidentity:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseShiftExp();
e = new AST.IdentityExp(op, loc, e, e2);
Expand All @@ -9219,12 +9227,14 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
case TOK.greaterThan: op = EXP.greaterThan; goto Lcmp;
case TOK.greaterOrEqual: op = EXP.greaterOrEqual; goto Lcmp;
Lcmp:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseShiftExp();
e = new AST.CmpExp(op, loc, e, e2);
break;

case TOK.in_:
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseShiftExp();
e = new AST.InExp(loc, e, e2);
Expand All @@ -9238,28 +9248,26 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseAndExp()
{
Loc loc = token.loc;
auto e = parseCmpExp();
while (token.value == TOK.and)
{
checkParens(TOK.and, e);
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseCmpExp();
checkParens(TOK.and, e2);
e = new AST.AndExp(loc, e, e2);
loc = token.loc;
}
return e;
}

private AST.Expression parseXorExp()
{
const loc = token.loc;

auto e = parseAndExp();
while (token.value == TOK.xor)
{
checkParens(TOK.xor, e);
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAndExp();
checkParens(TOK.xor, e2);
Expand All @@ -9270,12 +9278,11 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseOrExp()
{
const loc = token.loc;

auto e = parseXorExp();
while (token.value == TOK.or)
{
checkParens(TOK.or, e);
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseXorExp();
checkParens(TOK.or, e2);
Expand All @@ -9286,11 +9293,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseAndAndExp()
{
const loc = token.loc;

auto e = parseOrExp();
while (token.value == TOK.andAnd)
{
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseOrExp();
e = new AST.LogicalExp(loc, EXP.andAnd, e, e2);
Expand All @@ -9300,11 +9306,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseOrOrExp()
{
const loc = token.loc;

auto e = parseAndAndExp();
while (token.value == TOK.orOr)
{
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAndAndExp();
e = new AST.LogicalExp(loc, EXP.orOr, e, e2);
Expand All @@ -9314,11 +9319,10 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer

private AST.Expression parseCondExp()
{
const loc = token.loc;

auto e = parseOrOrExp();
if (token.value == TOK.question)
{
const loc = token.loc; // Capture operator's location
nextToken();
auto e1 = parseExpression();
check(TOK.colon);
Expand All @@ -9343,102 +9347,115 @@ class Parser(AST, Lexer = dmd.lexer.Lexer) : Lexer
e.toChars(), Token.toChars(token.value));
}

const loc = token.loc;
switch (token.value)
{
case TOK.assign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.AssignExp(loc, e, e2);
break;

case TOK.addAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.AddAssignExp(loc, e, e2);
break;

case TOK.minAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.MinAssignExp(loc, e, e2);
break;

case TOK.mulAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.MulAssignExp(loc, e, e2);
break;

case TOK.divAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.DivAssignExp(loc, e, e2);
break;

case TOK.modAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.ModAssignExp(loc, e, e2);
break;

case TOK.powAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.PowAssignExp(loc, e, e2);
break;

case TOK.andAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.AndAssignExp(loc, e, e2);
break;

case TOK.orAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.OrAssignExp(loc, e, e2);
break;

case TOK.xorAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.XorAssignExp(loc, e, e2);
break;

case TOK.leftShiftAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.ShlAssignExp(loc, e, e2);
break;

case TOK.rightShiftAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.ShrAssignExp(loc, e, e2);
break;

case TOK.unsignedRightShiftAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.UshrAssignExp(loc, e, e2);
break;

case TOK.concatenateAssign:
checkRequiredParens();
const loc = token.loc; // Capture operator's location
nextToken();
auto e2 = parseAssignExp();
e = new AST.CatAssignExp(loc, e, e2);
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/fail196.d
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ fail_compilation/fail196.d(44): expression: `";\n assert(s == "`
fail_compilation/fail196.d(45): Error: found `}` when expecting `;` following expression
fail_compilation/fail196.d(45): expression: `xxx`
fail_compilation/fail196.d(47): Error: found `<` when expecting `;` following expression
fail_compilation/fail196.d(45): expression: `");\n\n s = q" < foo`
fail_compilation/fail196.d(47): expression: `");\n\n s = q" < foo`
fail_compilation/fail196.d(48): Error: found `foo` when expecting `;` following expression
fail_compilation/fail196.d(47): expression: `xxx >> ";\n assert(s == "`
fail_compilation/fail196.d(48): Error: found `<` instead of statement
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/fail_compilation/fail_pretty_errors.d
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ fail_compilation/fail_pretty_errors.d(44): Error: mixin `fail_pretty_errors.test
^
fail_compilation/fail_pretty_errors.d(50): Error: invalid array operation `"" + ""` (possible missing [])
auto x = ""+"";
^
^
fail_compilation/fail_pretty_errors.d(50): did you mean to concatenate (`"" ~ ""`) instead ?
fail_compilation/fail_pretty_errors.d(53): Error: cannot implicitly convert expression `1111` of type `int` to `byte`
byte ɑ = 1111;
Expand Down
12 changes: 12 additions & 0 deletions compiler/test/fail_compilation/fix21166.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
TEST_OUTPUT:
---
fail_compilation/fix21166.d(11): Error: invalid array operation `"foo" + "bar"` (possible missing [])
fail_compilation/fix21166.d(11): did you mean to concatenate (`"foo" ~ "bar"`) instead ?
---
*/

auto r =
"foo"
+
"bar";
Loading