0

My language allows anonymous function declaration like (x: int):int => { return x * x - x }. To call this simply write (expression). But I also have to enclose an expression within parentheses for precedence, for example x*(y+z).

Now bison raises shift/reduce conflict for anonymous function-call with single argument.

Here is a part of the grammar section:

expr: ID %prec LOW
    | ID '=' expr %prec LOW
    | ID '(' ')'
    | ID '(' call_args ')'
    | '(' call_args ')' // anonymous function call
    | '(' ')'           // anonymous function call without arg
    | '(' expr ')'      // expression enclosed, like '(y+z)' in 'x*(y+z)'
    | expr op_arithematic expr %prec HIGH
    | expr op_comparison expr %prec HIGH 
    | numeric

call_args: expr
    | call_args ',' expr

The conflicted output is:

State 31

   31 expr: '(' expr . ')'
   32     | expr . op_arithematic expr
   33     | expr . op_comparison expr
   37 call_args: expr .
    ...
    ...
    ...
    ')'  shift, and go to state 61

    ')'       [reduce using rule 37 (call_args)]
    $default  reduce using rule 37 (call_args)

I have also added %prec with no luck:

expr: ID %prec LOW
    | ID '=' expr %prec LOW
    | ID '(' ')'
    | ID '(' call_args ')'
    | '(' call_args ')'  %prec HIGH // anonymous function call
    | '(' ')'                       // anonymous function call without arg
    | '(' expr ')'       %prec LOW  // expression enclosed, like '(y+z)' in 'x*(y+z)'
    | expr op_arithematic expr %prec HIGH
    | expr op_comparison expr %prec HIGH 
    | numeric

call_args: expr
    | call_args ',' expr

It is painful to me to allow calling an anonymous function like this, but I cannot avoid it's implementation because, it is my lab-assignment. I found no way to resolve this issue.

Chitholian
  • 432
  • 1
  • 10
  • 19
  • 1
    What do you mean specifically by "to call this simply write `(expression)`"? Can you give a concrete example? I'd expect a call to look like `((x: int):int => { return x * x - x })(3)`; that is, including both the anonymous function and the argument list. Your grammar doesn't seem to reflect that, though. – rici Mar 13 '19 at 18:25
  • Example given by my teacher: Anonymous Function Declaration `(x: int, y:int, z:double):int => { return x * y * z }
`. Call it and print output: `echo((4,5,6.0) + (3,5,4.0))` – Chitholian Mar 13 '19 at 18:30
  • 1
    Does that mean that your language only allows one anonymous function? That seems pointless. But uf there is more than one one, how on earth do you know which one to call? Personally, I would seek clarification from your professor. Because if *any* parenthesised expression is a call of the (single, unique) anonymous function, then the language is totally ambiguous. (Feel free to show your teacher these comments.) – rici Mar 13 '19 at 18:37
  • 1
    @Chitholian How do these two snippets relate to each other? What does the whole program look like? Line 1 is just `(x: int, y:int, z:double):int => { return x * y * z }` and then line 2 is `echo((4,5,6.0) + (3,5,4.0))` and then the argument lists magically get associated with the anonymous function on line 1? What if there's more than one anonymous function in the program? And what should `echo ((a+b)*(c+d))` be? A simple arithmetic expression or two calls to a unary anonymous function? That can't possibly be what your instructor meant. – sepp2k Mar 13 '19 at 18:38
  • 1
    I mean even in your example of `x*(y+z)`, how do you decide that `(y+z)` is not a call to an anonymous function? According to your description it very well may be. – sepp2k Mar 13 '19 at 18:42
  • @sepp2k Yes, I understand that it is ambiguous, I will show this to my teacher, but before that, is it possible to make a precedence (i.e. preference) of them ? I mean `echo ((a+b)*(c+d))` is two calls to the anonymous function if an anonymous function exists with the matched signature otherwise it is just an arithmetic expression. What I want to say is "prefer function call over expression". Also declaring more than one anonymous functions with same signature is a compile-time error. – Chitholian Mar 14 '19 at 00:33
  • 2
    @chitholian: you cannot do that with any grammatical artifice, neither with a production nor with precedence, because the language is just plain ambiguous, and the ambiguity can only be resolved with contextual information. The only solution is to make the semantic rule for the reduction of a parenthesised expression decide whether or not the expression is a function call based on the existence or not of an anonymous function with the correct signature, and build an appropriate AST on that basis. But I still think it's absurd, even as a learning exercise. – rici Mar 14 '19 at 02:18

0 Answers0