From 5ccebfdec189622b0c5b41eabb46fe67f8282443 Mon Sep 17 00:00:00 2001
From: "benjamin.franksen" <benjamin.franksen@helmholtz-berlin.de>
Date: Wed, 2 Oct 2013 01:30:51 +0000
Subject: [PATCH] snc: allow indirect function calls

This simply replaces 'ident ( args )' with  'expr ( args )' in the
syntax. A few more changes in the code generator and we're done.
---
 src/snc/gen_ss_code.c | 16 ++++++++++------
 src/snc/snl.lem       | 38 ++++++++++++++++++--------------------
 src/snc/types.h       |  7 ++++---
 3 files changed, 32 insertions(+), 29 deletions(-)

diff --git a/src/snc/gen_ss_code.c b/src/snc/gen_ss_code.c
index f30e4576..fd54cd25 100644
--- a/src/snc/gen_ss_code.c
+++ b/src/snc/gen_ss_code.c
@@ -445,9 +445,10 @@ static void gen_expr(
 		gen_code("\"%s\"", ep->value);
 		break;
 	case E_FUNC:
-		if (gen_builtin_func(context, ep))
+		if (ep->func_expr->type == E_VAR && gen_builtin_func(context, ep))
 			break;
-		gen_code("%s(", ep->value);
+		gen_expr(context, ep->func_expr, 0);
+		gen_code("(");
 		foreach (cep, ep->func_args)
 		{
 			gen_expr(context, cep, 0);
@@ -533,10 +534,13 @@ static int gen_builtin_const(Expr *ep)
 /* Generate builtin function call */
 static int gen_builtin_func(int context, Expr *ep)
 {
-	char	*func_name = ep->value;	/* function name */
+	char	*func_name = ep->func_expr->value;
 	Expr	*ap;			/* argument expr */
-	struct func_symbol *sym = lookup_builtin_func(global_sym_table, func_name);
+	struct func_symbol *sym;
 
+	if (ep->func_expr->type != E_VAR)
+		return FALSE;
+	sym = lookup_builtin_func(global_sym_table, func_name);
 	if (!sym)
 		return FALSE;	/* not a special function */
 
@@ -688,7 +692,7 @@ static void gen_pv_func(
 	}
 
 #ifdef	DEBUG
-	report("gen_pv_func: fun=%s, var=%s\n", ep->value, vp->name);
+	report("gen_pv_func: fun=%s, var=%s\n", func_name, vp->name);
 #endif
 	gen_code(", ");
 	if (vp->assign == M_NONE)
@@ -767,7 +771,7 @@ static void gen_pv_func(
 	/* Close the parameter list */
 	gen_code(")");
 #ifdef	DEBUG
-	report("gen_pv_func: done (fun=%s, var=%s)\n", ep->value, vp->name);
+	report("gen_pv_func: done (fun=%s, var=%s)\n", func_name, vp->name);
 #endif
 }
 
diff --git a/src/snc/snl.lem b/src/snc/snl.lem
index b5011b81..89b93887 100644
--- a/src/snc/snl.lem
+++ b/src/snc/snl.lem
@@ -44,7 +44,7 @@ in the file LICENSE that is included with this distribution.
 %token_type { Token }
 %default_type { Expr* }
 
-/* Standard C operator table
+/* Standard C operator table, highest precedence first.
   Primary Expression Operators  () [] . -> expr++ expr--  left-to-right
   Unary Operators  * & + - ! ~ ++expr --expr (typecast) sizeof()  right-to-left
   Binary Operators  * / %  left-to-right
@@ -62,8 +62,10 @@ in the file LICENSE that is included with this distribution.
   Comma  ,  left-to-right
 */
 
-// PRE and POST are pseudo tokens, they only for the
-// precedence declaration.
+// PRE and POST are pseudo tokens used for precedence declaration.
+// They are needed for operators that can appear in more than
+// one position (and then have different precedences) because lemon
+// allows only one precedence declaration for each token.
 
 // The comma operator is implemented as an extra production,
 // so we need no explicit precedence for it.
@@ -80,10 +82,8 @@ in the file LICENSE that is included with this distribution.
 %left	LSHIFT RSHIFT.
 %left	ADD SUB.
 %left	ASTERISK SLASH MOD.
-%right	CAST.
-%right	NOT INCR DECR PRE.
-%left	LBRACKET RBRACKET POINTER PERIOD POST.
-// LPAREN RPAREN not listed as we do not support indirect calls. */
+%right	NOT TILDE INCR DECR PRE. // omitted duplicates: ADD SUB ASTERISK AMPERSAND
+%left	LBRACKET LPAREN POINTER PERIOD POST.  // omitted duplicates: INCR DECR
 
 program ::=
 	PROGRAM NAME(n)
@@ -400,19 +400,17 @@ expr(p) ::= FPCON(x).				{ p = expr(E_CONST, x); }
 expr(p) ::= string(x).				{ p = x; }
 expr(p) ::= variable(v).			{ p = expr(E_VAR, v); }
 
-// Parenthesized
-expr(p) ::= LPAREN(t) comma_expr(x) RPAREN.		{ p = expr(E_PAREN, t, x); }
-
 // Primary Expression and Unary Postfix Operators
-expr(p) ::= NAME(t) LPAREN args(xs) RPAREN.	 [POST] { p = expr(E_FUNC,   t, xs); }
-expr(p) ::= EXIT(t) LPAREN args(xs) RPAREN.	 [POST] { p = expr(E_FUNC,   t, xs); }
-expr(p) ::= SIZEOF(t) LPAREN expr(x) RPAREN.	 [POST] { p = expr(E_FUNC,   t, x); }
-expr(p) ::= SIZEOF(t) LPAREN type_expr(x) RPAREN.[POST] { p = expr(E_FUNC,   t, x); }
-expr(p) ::= expr(x) LBRACKET(t) expr(y) RBRACKET.[POST] { p = expr(E_SUBSCR, t, x, y); }
-expr(p) ::= expr(x) PERIOD(t) member(y).	 [POST] { p = expr(E_SELECT, t, x, y); }
-expr(p) ::= expr(x) POINTER(t) member(y).	 [POST] { p = expr(E_SELECT, t, x, y); }
-expr(p) ::= expr(x) INCR(t).			 [POST] { p = expr(E_POST,   t, x); }
-expr(p) ::= expr(x) DECR(t).			 [POST] { p = expr(E_POST,   t, x); }
+expr(p) ::= LPAREN(t) comma_expr(x) RPAREN.		{ p = expr(E_PAREN,  t, x); }
+expr(p) ::= expr(x) LPAREN(t) args(y) RPAREN.		{ p = expr(E_FUNC,   t, x, y); }
+expr(p) ::= EXIT(n) LPAREN(t) args(y) RPAREN.		{ p = expr(E_FUNC,   t, expr(E_VAR, n), y); }
+expr(p) ::= SIZEOF(n) LPAREN(t) expr(y) RPAREN.		{ p = expr(E_FUNC,   t, expr(E_VAR, n), y); }
+expr(p) ::= SIZEOF(n) LPAREN(t) type_expr(y) RPAREN.	{ p = expr(E_FUNC,   t, expr(E_VAR, n), y); }
+expr(p) ::= expr(x) LBRACKET(t) expr(y) RBRACKET.	{ p = expr(E_SUBSCR, t, x, y); }
+expr(p) ::= expr(x) PERIOD(t) member(y).		{ p = expr(E_SELECT, t, x, y); }
+expr(p) ::= expr(x) POINTER(t) member(y).		{ p = expr(E_SELECT, t, x, y); }
+expr(p) ::= expr(x) INCR(t). [POST]			{ p = expr(E_POST,   t, x); }
+expr(p) ::= expr(x) DECR(t). [POST]			{ p = expr(E_POST,   t, x); }
 
 // Unary Prefix Operators
 expr(p) ::= ADD(t)	expr(x). [PRE]		{ p = expr(E_PRE, t, x); }
@@ -425,7 +423,7 @@ expr(p) ::= INCR(t)	expr(x). [PRE]		{ p = expr(E_PRE, t, x); }
 expr(p) ::= DECR(t)	expr(x). [PRE]		{ p = expr(E_PRE, t, x); }
 
 // Type Cast
-expr(p) ::= LPAREN(t) type_expr(c) RPAREN expr(x). [CAST] { p = expr(E_CAST, t, c, x); }
+expr(p) ::= LPAREN(t) type_expr(c) RPAREN expr(x). [PRE] { p = expr(E_CAST, t, c, x); }
 
 // Binary Operators, left-to-right
 expr(p) ::= expr(x) SUB(t)	expr(y).	{ p = expr(E_BINOP, t, x, y); }
diff --git a/src/snc/types.h b/src/snc/types.h
index d940b470..2ee9027a 100644
--- a/src/snc/types.h
+++ b/src/snc/types.h
@@ -286,7 +286,7 @@ enum expr_type			/* description [child expressions...] */
 	E_BINOP,		/* binary operator [left,right] */
 	E_CAST,			/* type cast [operand] */
 	E_CONST,		/* numeric (inkl. character) constant [] */
-	E_FUNC,			/* function call [args] */
+	E_FUNC,			/* function call [expr,args] */
 	E_INIT,			/* array or struct initializer [elems] */
 	E_MEMBER,		/* struct or union member [] */
 	E_PAREN,		/* parenthesis around an expression [expr] */
@@ -332,7 +332,8 @@ STATIC_ASSERT(NUM_EXPR_TYPES <= 8*sizeof(TypeMask));
 #define for_cond	children[1]
 #define for_iter	children[2]
 #define for_stmt	children[3]
-#define func_args	children[0]
+#define func_expr	children[0]
+#define func_args	children[1]
 #define if_cond		children[0]
 #define if_then		children[1]
 #define if_else		children[2]
@@ -405,7 +406,7 @@ expr_type_info[]
 	{ "E_BINOP",	2 },
 	{ "E_CAST",	2 },
 	{ "E_CONST",	0 },
-	{ "E_FUNC",	1 },
+	{ "E_FUNC",	2 },
 	{ "E_INIT",	1 },
 	{ "E_MEMBER",	0 },
 	{ "E_PAREN",	1 },
-- 
GitLab