Skip to content

Commit

Permalink
Fix "not match" and "not if" causing a syntax error (#3449)
Browse files Browse the repository at this point in the history
* Updating 4th example of the STYLE_GUIDE's multi-function-call section

* Add cond and whileloop to atom in ast/parser.c

This fixes issue #2988, by allowing `if` and `while` to be used as
expressions following the `not` operator (bzw. any other unary operator).

* Also include forloop in atom in ast/parser.c

`not for` had not been mentionned in #2988. Also updates the comment
preceding `DEF(atom)`.

* Add tests around #2988

* Untangle patch-issue-3441

This reverts commit 8121944.

* Fix match guard being parsed as regular condition

* Update grammar file
  • Loading branch information
adri326 authored and jemc committed Jan 28, 2020
1 parent d8b5665 commit 4081905
Show file tree
Hide file tree
Showing 3 changed files with 131 additions and 11 deletions.
49 changes: 46 additions & 3 deletions pony.g
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ withelem
;

caseexpr
: '|' ('\\' ID (',' ID)* '\\')? pattern? ('if' rawseq)? ('=>' rawseq)?
: '|' ('\\' ID (',' ID)* '\\')? casepattern? ('if' rawseq)? ('=>' rawseq)?
;

elseiftype
Expand Down Expand Up @@ -162,6 +162,11 @@ nextpattern
| nextparampattern
;

casepattern
: ('var' | 'let' | 'embed') ID (':' type)?
| caseparampattern
;

pattern
: ('var' | 'let' | 'embed') ID (':' type)?
| parampattern
Expand All @@ -172,6 +177,11 @@ nextparampattern
| nextpostfix
;

caseparampattern
: ('not' | 'addressof' | '-' | '-~' | MINUS_NEW | MINUS_TILDE_NEW | 'digestof') caseparampattern
| casepostfix
;

parampattern
: ('not' | 'addressof' | '-' | '-~' | MINUS_NEW | MINUS_TILDE_NEW | 'digestof') parampattern
| postfix
Expand All @@ -181,8 +191,12 @@ nextpostfix
: nextatom antlr_2*
;

casepostfix
: caseatom antlr_3*
;

postfix
: atom antlr_3*
: atom antlr_4*
;

call
Expand Down Expand Up @@ -212,6 +226,24 @@ nextatom
| '@{' ('\\' ID (',' ID)* '\\')? cap? ID? typeparams? ('(' | LPAREN_NEW) lambdaparams? ')' lambdacaptures? (':' type)? '?'? '=>' rawseq '}' cap?
| '@' (ID | STRING) typeargs? ('(' | LPAREN_NEW) positional? named? ')' '?'?
| '__loc'
| 'if' ('\\' ID (',' ID)* '\\')? rawseq 'then' rawseq (elseif | ('else' annotatedrawseq))? 'end'
| 'while' ('\\' ID (',' ID)* '\\')? rawseq 'do' rawseq ('else' annotatedrawseq)? 'end'
| 'for' ('\\' ID (',' ID)* '\\')? idseq 'in' rawseq 'do' rawseq ('else' annotatedrawseq)? 'end'
;

caseatom
: ID
| 'this'
| literal
| ('(' | LPAREN_NEW) rawseq tuple? ')'
| ('[' | LSQUARE_NEW) ('as' type ':')? rawseq? ']'
| 'object' ('\\' ID (',' ID)* '\\')? cap? ('is' type)? members 'end'
| '{' ('\\' ID (',' ID)* '\\')? cap? ID? typeparams? ('(' | LPAREN_NEW) lambdaparams? ')' lambdacaptures? (':' type)? '?'? '=>' rawseq '}' cap?
| '@{' ('\\' ID (',' ID)* '\\')? cap? ID? typeparams? ('(' | LPAREN_NEW) lambdaparams? ')' lambdacaptures? (':' type)? '?'? '=>' rawseq '}' cap?
| '@' (ID | STRING) typeargs? ('(' | LPAREN_NEW) positional? named? ')' '?'?
| '__loc'
| 'while' ('\\' ID (',' ID)* '\\')? rawseq 'do' rawseq ('else' annotatedrawseq)? 'end'
| 'for' ('\\' ID (',' ID)* '\\')? idseq 'in' rawseq 'do' rawseq ('else' annotatedrawseq)? 'end'
;

atom
Expand All @@ -225,6 +257,9 @@ atom
| '@{' ('\\' ID (',' ID)* '\\')? cap? ID? typeparams? ('(' | LPAREN_NEW) lambdaparams? ')' lambdacaptures? (':' type)? '?'? '=>' rawseq '}' cap?
| '@' (ID | STRING) typeargs? ('(' | LPAREN_NEW) positional? named? ')' '?'?
| '__loc'
| 'if' ('\\' ID (',' ID)* '\\')? rawseq 'then' rawseq (elseif | ('else' annotatedrawseq))? 'end'
| 'while' ('\\' ID (',' ID)* '\\')? rawseq 'do' rawseq ('else' annotatedrawseq)? 'end'
| 'for' ('\\' ID (',' ID)* '\\')? idseq 'in' rawseq 'do' rawseq ('else' annotatedrawseq)? 'end'
;

tuple
Expand Down Expand Up @@ -285,7 +320,7 @@ tupletype
;

infixtype
: type antlr_4*
: type antlr_5*
;

isecttype
Expand Down Expand Up @@ -380,6 +415,14 @@ antlr_3
;

antlr_4
: dot
| tilde
| chain
| typeargs
| call
;

antlr_5
: uniontype
| isecttype
;
Expand Down
58 changes: 50 additions & 8 deletions src/libponyc/ast/parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ DECL(pattern);
DECL(idseq_in_seq);
DECL(members);
DECL(thisliteral);

DECL(cond);
DECL(whileloop);
DECL(forloop);
DECL(caseatom);
DECL(caseparampattern);

/* Precedence
*
Expand Down Expand Up @@ -519,18 +523,27 @@ DEF(ffi);
OPT TOKEN(NULL, TK_QUESTION);
DONE();

// ref | this | literal | tuple | array | object | lambda | barelambda | ffi |
// atom
// ref | this | literal | tuple | array | object | lambda | barelambda | ffi | cond | whileloop | forloop
// location
DEF(atom);
RULE("value", ref, thisliteral, literal, groupedexpr, array, object, lambda,
barelambda, ffi, location);
barelambda, ffi, location, cond, whileloop, forloop);
DONE();

// caseatom:
// ref | this | literal | tuple | array | object | lambda | barelambda | ffi | whileloop | forloop
// location
DEF(caseatom);
RULE("value", ref, thisliteral, literal, groupedexpr, array, object, lambda,
barelambda, ffi, location, whileloop, forloop);
DONE();

// ref | this | literal | tuple | array | object | lambda | barelambda| ffi |
// ref | this | literal | tuple | array | object | lambda | barelambda| ffi | cond | whileloop | forloop
// location
DEF(nextatom);
RULE("value", ref, thisliteral, literal, nextgroupedexpr, nextarray, object,
lambda, barelambda, ffi, location);
lambda, barelambda, ffi, location, cond, whileloop, forloop);
DONE();

// DOT ID
Expand Down Expand Up @@ -578,6 +591,12 @@ DEF(postfix);
SEQ("postfix expression", dot, tilde, chain, qualify, call);
DONE();

// atom {dot | tilde | chain | qualify | call}
DEF(casepostfix);
RULE("value", caseatom);
SEQ("postfix expression", dot, tilde, chain, qualify, call);
DONE();

// atom {dot | tilde | chain | qualify | call}
DEF(nextpostfix);
RULE("value", nextatom);
Expand Down Expand Up @@ -605,6 +624,19 @@ DEF(prefix);
RULE("expression", parampattern);
DONE();

// (NOT | AMP | MINUS | MINUS_TILDE | MINUS_NEW | MINUS_TILDE_NEW | DIGESTOF)
// casepattern
DEF(caseprefix);
PRINT_INLINE();
TOKEN("prefix", TK_NOT, TK_ADDRESS, TK_MINUS, TK_MINUS_TILDE, TK_MINUS_NEW,
TK_MINUS_TILDE_NEW, TK_DIGESTOF);
MAP_ID(TK_MINUS, TK_UNARY_MINUS);
MAP_ID(TK_MINUS_TILDE, TK_UNARY_MINUS_TILDE);
MAP_ID(TK_MINUS_NEW, TK_UNARY_MINUS);
MAP_ID(TK_MINUS_TILDE_NEW, TK_UNARY_MINUS_TILDE);
RULE("expression", caseparampattern);
DONE();

// (NOT | AMP | MINUS_NEW | MINUS_TILDE_NEW | DIGESTOF) pattern
DEF(nextprefix);
PRINT_INLINE();
Expand All @@ -620,14 +652,24 @@ DEF(parampattern);
RULE("pattern", prefix, postfix);
DONE();

// (caseprefix | casepostfix)
DEF(caseparampattern);
RULE("pattern", caseprefix, casepostfix);
DONE();

// (prefix | postfix)
DEF(nextparampattern);
RULE("pattern", nextprefix, nextpostfix);
DONE();

// (local | prefix | postfix)
DEF(pattern);
RULE("pattern", local, parampattern);
RULE("pattern", local, parampattern);
DONE();

// (local | prefix | postfix)
DEF(casepattern);
RULE("pattern", local, caseparampattern);
DONE();

// (local | prefix | postfix)
Expand Down Expand Up @@ -763,13 +805,13 @@ DEF(iftypeset);
TERMINATE("iftype expression", TK_END);
DONE();

// PIPE [annotations] [infix] [WHERE rawseq] [ARROW rawseq]
// PIPE [annotations] [infix] [IF rawseq] [ARROW rawseq]
DEF(caseexpr);
AST_NODE(TK_CASE);
SCOPE();
SKIP(NULL, TK_PIPE);
ANNOTATE(annotations);
OPT RULE("case pattern", pattern);
OPT RULE("case pattern", casepattern);
IF(TK_IF, RULE("guard expression", rawseq));
IF(TK_DBLARROW, RULE("case body", rawseq));
DONE();
Expand Down
35 changes: 35 additions & 0 deletions test/libponyc/sugar.cc
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,18 @@ TEST_F(SugarTest, IfWithElse)
}


TEST_F(SugarTest, NotIf)
{
const char* short_form =
"class Foo\n"
" fun f() =>\n"
" let a = true\n"
" if not if a then not a else a end then a end";

TEST_COMPILE(short_form);
}


TEST_F(SugarTest, WhileWithoutElse)
{
const char* short_form =
Expand Down Expand Up @@ -675,6 +687,18 @@ TEST_F(SugarTest, WhileWithElse)
}


TEST_F(SugarTest, NotWhileWithElse)
{
const char* short_form =
"class Foo\n"
" fun f(): U32 val =>\n"
" let a = true\n"
" not while a do true else false end";

TEST_COMPILE(short_form);
}


TEST_F(SugarTest, TryWithElseAndThen)
{
const char* short_form =
Expand Down Expand Up @@ -806,6 +830,17 @@ TEST_F(SugarTest, ForWithElse)
}


TEST_F(SugarTest, NotForWithElse)
{
const char* short_form =
"class Foo\n"
" fun f()=>\n"
" not for i in 1 do true else false end";

TEST_COMPILE(short_form);
}


TEST_F(SugarTest, MultiIteratorFor)
{
const char* short_form =
Expand Down

0 comments on commit 4081905

Please sign in to comment.