Browse Source

better infix

master
Martin Dørum 8 months ago
parent
commit
9aa7d5afe3
4 changed files with 58 additions and 19 deletions
  1. 7
    2
      lib/parse/lex.c
  2. 34
    17
      lib/parse/parse.c
  3. 13
    0
      test/examples/functions.l2
  4. 4
    0
      test/examples/functions.l2.expected

+ 7
- 2
lib/parse/lex.c View File

@@ -7,8 +7,13 @@ static void log_token(struct l2_token *tok) {
case L2_TOK_STRING:
case L2_TOK_IDENT:
case L2_TOK_ERROR:
printf("%i:%i\t%s '%s'\n", tok->line, tok->ch,
l2_token_get_name(tok), tok->v.str);
if (l2_token_is_small(tok)) {
printf("%i:%i\t%s '%s'\n", tok->line, tok->ch,
l2_token_get_name(tok), tok->v.strbuf);
} else {
printf("%i:%i\t%s '%s'\n", tok->line, tok->ch,
l2_token_get_name(tok), tok->v.str);
}
break;

case L2_TOK_NUMBER:

+ 34
- 17
lib/parse/parse.c View File

@@ -428,11 +428,41 @@ static int parse_func_call_after_base(
size_t argc = 0;

do {
argc += 1;
l2_trace_scope("func call param");
if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
if (tok_is_infix(l2_lexer_peek(lexer, 1))) {
do {
// We already have one value (the lhs) on the stack,
// so we need to parse the operator, then the rhs

// Operator
if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
}

// RHS
if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
}

l2_gen_func_call_infix(gen);
} while (tok_is_infix(l2_lexer_peek(lexer, 1)));

// If this was the "first argument", this wasn't a function call
// after all, it was just a (series of?) infix calls.
if (argc == 0) {
return 0;
}

// Don't increment argc here, because after an infix, we have
// neither added nor removed an arguemnt, just transformed one
} else {
l2_trace_scope("func call param");
if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
}

argc += 1;
}

} while (!tok_is_end(l2_lexer_peek(lexer, 1)));

// The 'argc' previous expressions were arguments, the one before that was the function
@@ -490,19 +520,6 @@ static int parse_expression(
return -1;
}

if (tok_is_infix(l2_lexer_peek(lexer, 1))) {
if (parse_arg_level_expression(lexer, gen, err) < 0) {
return -1;
}

if (parse_expression(lexer, gen, err) < 0) {
return -1;
}


l2_gen_func_call_infix(gen);
}

if (!tok_is_end(l2_lexer_peek(lexer, 1))) {
if (parse_func_call_after_base(lexer, gen, err) < 0) {
return -1;

+ 13
- 0
test/examples/functions.l2 View File

@@ -42,5 +42,18 @@ func := {
}
print func()()

# Functions can be called infix
print 10 + 20

# With complex expressions as left and right
print ({$.0 + $.1} 10 20) + (50 - 40)

# Infix operators are evaluated left to right
print 10 + 20 - 5

# Custom functions starting with a dollar can be infix
$shift-add := {$.0 * 10 + $.1}
print 1 $shift-add 2

# Lastly, just print a function literal
print {0}

+ 4
- 0
test/examples/functions.l2.expected View File

@@ -2,4 +2,8 @@ hello
Hello World
10
what's up
30
40
25
12
(function)

Loading…
Cancel
Save