From: Michael D. Lowis Date: Fri, 5 Apr 2019 03:28:39 +0000 (-0400) Subject: attempted to implement precedence climbing X-Git-Url: https://git.mdlowis.com/?a=commitdiff_plain;h=eeaaac232fe7ac6c0f19316cb52944277c3cd9c2;p=proto%2Fsclpl.git attempted to implement precedence climbing --- diff --git a/example.src b/example.src index 90a6cee..d52d547 100644 --- a/example.src +++ b/example.src @@ -33,9 +33,9 @@ fun main(args string[]) int { var bar int = 123 {123 321} 123 (123) - foo() - bar(1) - baz(1,2) +# foo() +# bar(1) +# baz(1,2) if (1) {1} if 2 {2} if (3) {3} else {4} @@ -46,9 +46,9 @@ fun main(args string[]) int { 123 } # UFCS call (call regular function like a method) - foo.bar() - foo.bar.baz() - # Struct/Union field access - let a int = foo.bar - let b int = foo.bar.baz +# foo.bar() +# foo.bar.baz() +# # Struct/Union field access +# let a int = foo.bar +# let b int = foo.bar.baz } diff --git a/inc/sclpl.h b/inc/sclpl.h index 0e9996e..9b27ce2 100644 --- a/inc/sclpl.h +++ b/inc/sclpl.h @@ -98,7 +98,7 @@ Sym* sym_get(SymTable* syms, char* name); typedef enum { AST_VAR, AST_FUNC, AST_EXPLIST, AST_IF, AST_APPLY, AST_STRING, AST_SYMBOL, AST_CHAR, AST_INT, - AST_FLOAT, AST_BOOL, AST_IDENT + AST_FLOAT, AST_BOOL, AST_IDENT, AST_OPER } ASTType; typedef struct AST { @@ -106,6 +106,11 @@ typedef struct AST { Type* datatype; union { struct AST* nodes[3]; + struct { + int oper; + struct AST* left; + struct AST* right; + } op; /* Definition Node */ struct { char* name; @@ -174,6 +179,9 @@ AST* Apply(AST* func, AST* args); AST* apply_func(AST* apply); AST* apply_args(AST* apply); +AST* OpCall(int oper, AST* left, AST* right); + + /* Package Definition *****************************************************************************/ typedef struct Require { diff --git a/src/ast.c b/src/ast.c index 0a58dd5..a2e48f5 100644 --- a/src/ast.c +++ b/src/ast.c @@ -181,3 +181,11 @@ AST* apply_args(AST* apply) { assert(apply->nodetype == AST_APPLY); return apply->value.nodes[1]; } + +AST* OpCall(int oper, AST* left, AST* right) { + AST* node = ast(AST_OPER); + node->value.op.oper = oper; + node->value.op.left = left; + node->value.op.right = right; + return node; +} diff --git a/src/parser.c b/src/parser.c index 4a26623..56828ad 100644 --- a/src/parser.c +++ b/src/parser.c @@ -7,7 +7,7 @@ static void definition_list(Parser* p); static AST* definition(Parser* p); static AST* type_definition(Parser* p); static AST* func_definition(Parser* p); -static AST* expression(Parser* p); +static AST* expression(Parser* p, int level); static AST* constant(Parser* p); static AST* type_expression(Parser* p); static AST* struct_fields(Parser* p); @@ -30,13 +30,13 @@ static int Indent = 0; #define parse_exit() #endif -uint8_t PrefixOps[T_COUNT] = { +int8_t PrefixOps[T_COUNT] = { [T_IF] = 1, ['{'] = 1, ['('] = 1, }; -uint8_t BinaryOps[T_COUNT] = { +int8_t BinaryOps[T_COUNT] = { ['.'] = 1, ['('] = 1, }; @@ -154,7 +154,7 @@ static AST* definition(Parser* p) { char* str = strdup(expect_val(p, T_ID)->text); AST* type = type_expression(p); expect(p, '='); - AST* val = expression(p); + AST* val = expression(p, 1); parse_exit(); return Var(str, val, type, SF_CONSTANT); } @@ -191,26 +191,57 @@ static AST* func_definition(Parser* p) { return Var(name, func, type, SF_CONSTANT); } -static AST* expression(Parser* p) { - parse_enter(); - int precedence = PrefixOps[peek(p)->type]; +/* +function parseExpressionAtPrecedence(currentPrecedence) { + expr = parseExpressionAtom() + while op = parseOperator() && op.precedence < currentPrecedence { + if op.rightAssociative { + b = parseExpressionAtPrecedence(op.precedence) + } else { + b = parseExpressionAtPrecedence(op.precedence + 1) + } + expr = OperatorExpression(op, expr, b) + } + return expr +} +*/ + +static AST* expression(Parser* p, int level) { AST* left = prefix_expr(p); - int next = peek(p)->type; - while (BinaryOps[next] && BinaryOps[next] >= precedence) { - left = binary_expr(p, left); - next = peek(p)->type; + int oper = peek(p)->type; + while (BinaryOps[oper] && abs(BinaryOps[oper]) < level) { + AST* right; + expect(p, oper); // consume the operator + if (BinaryOps[oper] < 0) + right = expression(p, level+1); + else + right = expression(p, level); + left = OpCall(oper, left, right); + oper = peek(p)->type; // get next operator } - parse_exit(); return left; } +//static AST* expression(Parser* p) { +// parse_enter(); +// int precedence = PrefixOps[peek(p)->type]; +// AST* left = prefix_expr(p); +// int next = peek(p)->type; +// while (BinaryOps[next] && BinaryOps[next] >= precedence) { +// left = binary_expr(p, left); +// next = peek(p)->type; +// } +// parse_exit(); +// return left; +//} + static AST* prefix_expr(Parser* p) { AST* tree = NULL; Tok* tok = peek(p); switch ((int)tok->type) { case '(': expect(p, '('); - tree = expression(p); + tree = expression(p, 1); expect(p, ')'); break; case '[': @@ -313,7 +344,7 @@ static AST* expression_block(Parser* p) { } else if (matches(p, T_FUN)) { expr = func_definition(p); } else { - expr = expression(p); + expr = expression(p, 1); } explist_append(list, expr); } @@ -324,10 +355,10 @@ static AST* expression_block(Parser* p) { static AST* if_expression(Parser* p) { AST *cond = 0, *b1 = 0, *b2 = 0; expect(p, T_IF); - cond = expression(p); // condition - b1 = expression(p); // true branch + cond = expression(p, 1); // condition + b1 = expression(p, 1); // true branch if (accept(p, T_ELSE)) { - b2 = expression(p); // false branch + b2 = expression(p, 1); // false branch } return If(cond, b1, b2); } @@ -348,7 +379,7 @@ static AST* expr_list(Parser* p, int firstc, int endc) { expect(p, firstc); AST* list = ExpList(); while (!matches(p, endc)) { - explist_append(list, expression(p)); + explist_append(list, expression(p, 1)); if (!matches(p, endc)) { expect(p, ','); if (matches(p, endc))