Skip to content

Commit

Permalink
Merge pull request #536 from nkt/feature/else-if
Browse files Browse the repository at this point in the history
Elseif support
  • Loading branch information
Phalcon committed Sep 14, 2014
2 parents b2a3062 + a445c4e commit db0c6e7
Show file tree
Hide file tree
Showing 18 changed files with 253 additions and 48 deletions.
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,9 @@ indent_style = tab

[*.h]
indent_style = tab

[*.lemon]
indent_style = tab

[*.re]
indent_style = tab
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ before_script:

script:
- vendor/bin/phpcs --standard=PSR2 --report=emacs --extensions=php --warning-severity=0 Library/ unit-tests/Extension/ unit-tests/Zephir/
- valgrind --read-var-info=yes --error-exitcode=1 --fullpath-after= --track-origins=yes phpunit --debug
- valgrind --read-var-info=yes --error-exitcode=1 --fullpath-after= --track-origins=yes --leak-check=full phpunit --debug

after_script:
- vendor/bin/coveralls -v --exclude-no-stmt
Expand Down
2 changes: 1 addition & 1 deletion Library/Compiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
*/
class Compiler
{
const VERSION = '0.4.6a';
const VERSION = '0.5.0a';

/**
* @var CompilerFile[]
Expand Down
20 changes: 18 additions & 2 deletions Library/Statements/IfStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ public function compile(CompilationContext $compilationContext)
$this->_evalExpression = $expr;

/**
* Try to mark lastest temporary variable used as idle
* Try to mark latest temporary variable used as idle
*/
$evalVariable = $expr->getEvalVariable();
$evalVariable = $expr->getEvalVariable();
if (is_object($evalVariable)) {
if ($evalVariable->isTemporal()) {
$evalVariable->setIdle(true);
Expand All @@ -90,6 +90,22 @@ public function compile(CompilationContext $compilationContext)
$branch->setRelatedStatement($this);
}

/**
* Compile statements in the 'elseif' block
*/
if (isset($this->_statement['elseif_statements'])) {
foreach ($this->_statement['elseif_statements'] as $statement) {
if (!isset($statement['statements'])) {
continue;
}
$condition = $expr->optimize($statement['expr'], $compilationContext);
$compilationContext->codePrinter->output('} else if (' . $condition . ') {');
$st = new StatementsBlock($statement['statements']);
$branch = $st->compile($compilationContext, $expr->isUnreachable(), Branch::TYPE_CONDITIONAL_TRUE);
$branch->setRelatedStatement($this);
}
}

/**
* Compile statements in the 'else' block
*/
Expand Down
1 change: 1 addition & 0 deletions ext/config.m4
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ if test "$PHP_TEST" = "yes"; then
test/scallparent.zep.c
test/spectralnorm.zep.c
test/spropertyaccess.zep.c
test/statements.zep.c
test/strings.zep.c
test/ternary.zep.c
test/testinterface.zep.c
Expand Down
2 changes: 2 additions & 0 deletions ext/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ zend_class_entry *test_scall_ce;
zend_class_entry *test_scallexternal_ce;
zend_class_entry *test_spectralnorm_ce;
zend_class_entry *test_spropertyaccess_ce;
zend_class_entry *test_statements_ce;
zend_class_entry *test_strings_ce;
zend_class_entry *test_ternary_ce;
zend_class_entry *test_trie_ce;
Expand Down Expand Up @@ -402,6 +403,7 @@ static PHP_MINIT_FUNCTION(test)
ZEPHIR_INIT(Test_Scall);
ZEPHIR_INIT(Test_ScallExternal);
ZEPHIR_INIT(Test_SpectralNorm);
ZEPHIR_INIT(Test_Statements);
ZEPHIR_INIT(Test_Strings);
ZEPHIR_INIT(Test_Ternary);
ZEPHIR_INIT(Test_Trie);
Expand Down
1 change: 1 addition & 0 deletions ext/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
#include "test/scallparent.zep.h"
#include "test/spectralnorm.zep.h"
#include "test/spropertyaccess.zep.h"
#include "test/statements.zep.h"
#include "test/strings.zep.h"
#include "test/ternary.zep.h"
#include "test/testinterface.zep.h"
Expand Down
4 changes: 2 additions & 2 deletions ext/test/constants.zep.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions ext/test/declaretest.zep.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions ext/test/statements.zep.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 15 additions & 0 deletions ext/test/statements.zep.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions parser/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,9 @@ int xx_parse_program(char *program, unsigned int program_length, char *file_path
case XX_T_ELSE:
xx_(xx_parser, XX_ELSE, NULL, parser_status);
break;
case XX_T_ELSEIF:
xx_(xx_parser, XX_ELSEIF, NULL, parser_status);
break;
case XX_T_LOOP:
xx_(xx_parser, XX_LOOP, NULL, parser_status);
break;
Expand Down
67 changes: 34 additions & 33 deletions parser/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,36 +83,37 @@
#define XX_CONTINUE 83
#define XX_IF 84
#define XX_ELSE 85
#define XX_SWITCH 86
#define XX_CASE 87
#define XX_COLON 88
#define XX_DEFAULT 89
#define XX_LOOP 90
#define XX_WHILE 91
#define XX_DO 92
#define XX_TRY 93
#define XX_CATCH 94
#define XX_FOR 95
#define XX_IN 96
#define XX_REVERSE 97
#define XX_LET 98
#define XX_ADDASSIGN 99
#define XX_SUBASSIGN 100
#define XX_MULASSIGN 101
#define XX_DIVASSIGN 102
#define XX_CONCATASSIGN 103
#define XX_MODASSIGN 104
#define XX_STRING 105
#define XX_DOUBLECOLON 106
#define XX_INCR 107
#define XX_DECR 108
#define XX_ECHO 109
#define XX_RETURN 110
#define XX_UNSET 111
#define XX_THROW 112
#define XX_INTEGER 113
#define XX_CHAR 114
#define XX_DOUBLE 115
#define XX_TRUE 116
#define XX_FALSE 117
#define XX_CBLOCK 118
#define XX_ELSEIF 86
#define XX_SWITCH 87
#define XX_CASE 88
#define XX_COLON 89
#define XX_DEFAULT 90
#define XX_LOOP 91
#define XX_WHILE 92
#define XX_DO 93
#define XX_TRY 94
#define XX_CATCH 95
#define XX_FOR 96
#define XX_IN 97
#define XX_REVERSE 98
#define XX_LET 99
#define XX_ADDASSIGN 100
#define XX_SUBASSIGN 101
#define XX_MULASSIGN 102
#define XX_DIVASSIGN 103
#define XX_CONCATASSIGN 104
#define XX_MODASSIGN 105
#define XX_STRING 106
#define XX_DOUBLECOLON 107
#define XX_INCR 108
#define XX_DECR 109
#define XX_ECHO 110
#define XX_RETURN 111
#define XX_UNSET 112
#define XX_THROW 113
#define XX_INTEGER 114
#define XX_CHAR 115
#define XX_DOUBLE 116
#define XX_TRUE 117
#define XX_FALSE 118
#define XX_CBLOCK 119
67 changes: 60 additions & 7 deletions parser/parser.lemon
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ static json_object *xx_ret_let_assignment(char *type, json_object *operator, xx_
return ret;
}

static json_object *xx_ret_if_statement(json_object *expr, json_object *statements, json_object *else_statements, xx_scanner_state *state)
static json_object *xx_ret_if_statement(json_object *expr, json_object *statements, json_object *elseif_statements, json_object *else_statements, xx_scanner_state *state)
{
json_object *ret = json_object_new_object();

Expand All @@ -576,6 +576,10 @@ static json_object *xx_ret_if_statement(json_object *expr, json_object *statemen
json_object_object_add(ret, "statements", statements);
}

if (elseif_statements) {
json_object_object_add(ret, "elseif_statements", elseif_statements);
}

if (else_statements) {
json_object_object_add(ret, "else_statements", else_statements);
}
Expand Down Expand Up @@ -1960,28 +1964,77 @@ xx_continue_statement(R) ::= CONTINUE DOTCOMMA . {
R = xx_ret_continue_statement(status->scanner_state);
}

/* if(a) {} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN BRACKET_CLOSE . {
R = xx_ret_if_statement(E, NULL, NULL, status->scanner_state);
R = xx_ret_if_statement(E, NULL, NULL, NULL, status->scanner_state);
}

/* if(a) {} elseif(b) {} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN BRACKET_CLOSE xx_elseif_statements(L) . {
R = xx_ret_if_statement(E, NULL, NULL, L, status->scanner_state);
}

/* if(a) {} else {} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN BRACKET_CLOSE ELSE BRACKET_OPEN BRACKET_CLOSE . {
R = xx_ret_if_statement(E, NULL, NULL, status->scanner_state);
R = xx_ret_if_statement(E, NULL, NULL, NULL, status->scanner_state);
}

/* if(a) {} elseif(b) {} else {} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN BRACKET_CLOSE xx_elseif_statements(L) ELSE BRACKET_OPEN BRACKET_CLOSE . {
R = xx_ret_if_statement(E, NULL, L, NULL, status->scanner_state);
}

/* if(a) {...} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE . {
R = xx_ret_if_statement(E, L, NULL, status->scanner_state);
R = xx_ret_if_statement(E, L, NULL, NULL, status->scanner_state);
}

/* if(a) {...} elseif(b) {...} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE xx_elseif_statements(S) . {
R = xx_ret_if_statement(E, L, S, NULL, status->scanner_state);
}

/* if(a) {...} else {...} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE ELSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
R = xx_ret_if_statement(E, L, S, status->scanner_state);
R = xx_ret_if_statement(E, L, NULL, S, status->scanner_state);
}

/* if(a) {...} elseif(b) {...} else {...} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE xx_elseif_statements(ES) ELSE BRACKET_OPEN xx_statement_list(S) BRACKET_CLOSE . {
R = xx_ret_if_statement(E, L, ES, S, status->scanner_state);
}

/* if(a) {...} else {} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE ELSE BRACKET_OPEN BRACKET_CLOSE . {
R = xx_ret_if_statement(E, L, NULL, status->scanner_state);
R = xx_ret_if_statement(E, L, NULL, NULL, status->scanner_state);
}

/* if(a) {...} elseif(b) {} else {} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE xx_elseif_statements(S) ELSE BRACKET_OPEN BRACKET_CLOSE . {
R = xx_ret_if_statement(E, L, S, NULL, status->scanner_state);
}

/* if(a) {} else {...} */
xx_if_statement(R) ::= IF xx_eval_expr(E) BRACKET_OPEN BRACKET_CLOSE ELSE BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE . {
R = xx_ret_if_statement(E, NULL, L, status->scanner_state);
R = xx_ret_if_statement(E, NULL, NULL, L, status->scanner_state);
}

xx_elseif_statements(R) ::= xx_elseif_statements(C) xx_elseif_statement(K) . {
R = xx_ret_list(C, K);
}

xx_elseif_statements(R) ::= xx_elseif_statement(K) . {
R = xx_ret_list(NULL, K);
}

/* elseif(b) {} */
xx_elseif_statement(R) ::= ELSEIF xx_eval_expr(E) BRACKET_OPEN BRACKET_CLOSE . {
R = xx_ret_if_statement(E, NULL, NULL, NULL, status->scanner_state);
}

/* elseif(b) {...} */
xx_elseif_statement(R) ::= ELSEIF xx_eval_expr(E) BRACKET_OPEN xx_statement_list(L) BRACKET_CLOSE . {
R = xx_ret_if_statement(E, L, NULL, NULL, status->scanner_state);
}

xx_switch_statement(R) ::= SWITCH xx_eval_expr(E) BRACKET_OPEN BRACKET_CLOSE . {
Expand Down
2 changes: 2 additions & 0 deletions parser/scanner.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,8 @@

#define XX_T_CBLOCK 451

#define XX_T_ELSEIF 452

/* List of tokens and their names */
typedef struct _xx_token_names {
unsigned int code;
Expand Down
6 changes: 6 additions & 0 deletions parser/scanner.re
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,12 @@ int xx_get_token(xx_scanner_state *s, xx_scanner_token *token) {
return 0;
}
'elseif' {
s->active_char += sizeof("elseif")-1;
token->opcode = XX_T_ELSEIF;
return 0;
}
'do' {
s->active_char += sizeof("do")-1;
token->opcode = XX_T_DO;
Expand Down
Loading

0 comments on commit db0c6e7

Please sign in to comment.