triple-for multi-continuation 1st light

This commit is contained in:
John Kerl 2016-10-02 23:33:03 -04:00
parent eb15c07e33
commit 8769fb18f7
6 changed files with 73 additions and 39 deletions

View file

@ -119,6 +119,25 @@ mlr_dsl_ast_node_t* mlr_dsl_ast_node_set_function_name(
return pa;
}
// ----------------------------------------------------------------
int mlr_dsl_ast_node_cannot_be_bare_boolean(mlr_dsl_ast_node_t* pnode) {
switch (pnode->type) {
case MD_AST_NODE_TYPE_BOOLEAN_LITERAL:
case MD_AST_NODE_TYPE_FIELD_NAME:
case MD_AST_NODE_TYPE_INDIRECT_FIELD_NAME:
case MD_AST_NODE_TYPE_OOSVAR_KEYLIST:
case MD_AST_NODE_TYPE_NON_SIGIL_NAME:
case MD_AST_NODE_TYPE_OPERATOR:
case MD_AST_NODE_TYPE_ENV:
case MD_AST_NODE_TYPE_BOUND_VARIABLE:
return FALSE;
break;
default:
return TRUE;
break;
}
}
// ----------------------------------------------------------------
void mlr_dsl_ast_print(mlr_dsl_ast_t* past) {
printf("AST ROOT:\n");

View file

@ -114,6 +114,8 @@ mlr_dsl_ast_node_t* mlr_dsl_ast_node_prepend_arg(mlr_dsl_ast_node_t* pa, mlr_dsl
mlr_dsl_ast_node_t* mlr_dsl_ast_node_append_arg(mlr_dsl_ast_node_t* pa, mlr_dsl_ast_node_t* pb);
mlr_dsl_ast_node_t* mlr_dsl_ast_node_set_function_name(mlr_dsl_ast_node_t* pa, char* name);
int mlr_dsl_ast_node_cannot_be_bare_boolean(mlr_dsl_ast_node_t* pnode);
void mlr_dsl_ast_print(mlr_dsl_ast_t* past);
void mlr_dsl_ast_node_print(mlr_dsl_ast_node_t* pnode);
void mlr_dsl_ast_node_fprint(mlr_dsl_ast_node_t* pnode, FILE* o);

View file

@ -429,7 +429,7 @@ md_triple_for(A) ::=
MD_TOKEN_FOR(F) MD_TOKEN_LPAREN
md_triple_for_start(S)
MD_TOKEN_SEMICOLON
md_rhs(C)
md_triple_for_continuation(C)
MD_TOKEN_SEMICOLON
md_triple_for_update(U)
MD_TOKEN_RPAREN
@ -440,24 +440,6 @@ md_triple_for(A) ::=
A = mlr_dsl_ast_node_alloc_quaternary(F->text, MD_AST_NODE_TYPE_TRIPLE_FOR, S, C, U, L);
}
md_triple_for(A) ::=
MD_TOKEN_FOR(F) MD_TOKEN_LPAREN
md_triple_for_start(S)
MD_TOKEN_SEMICOLON
MD_TOKEN_SEMICOLON
md_triple_for_update(U)
MD_TOKEN_RPAREN
MD_TOKEN_LBRACE
md_statement_list(L)
MD_TOKEN_RBRACE.
{
A = mlr_dsl_ast_node_alloc_quaternary(F->text, MD_AST_NODE_TYPE_TRIPLE_FOR,
S,
mlr_dsl_ast_node_alloc("true", MD_AST_NODE_TYPE_BOOLEAN_LITERAL),
U,
L);
}
md_triple_for_start(A) ::= md_statement_not_braced_end(B). {
if (B->type == MD_AST_NODE_TYPE_NOP) {
A = mlr_dsl_ast_node_alloc_zary("triple_for_start_statements", MD_AST_NODE_TYPE_STATEMENT_LIST);
@ -473,6 +455,21 @@ md_triple_for_start(A) ::= md_triple_for_start(B) MD_TOKEN_COMMA md_statement_no
}
}
md_triple_for_continuation(A) ::= md_statement_not_braced_end(B). {
if (B->type == MD_AST_NODE_TYPE_NOP) {
A = mlr_dsl_ast_node_alloc_zary("triple_for_continuation_statements", MD_AST_NODE_TYPE_STATEMENT_LIST);
} else {
A = mlr_dsl_ast_node_alloc_unary("triple_for_continuation_statements", MD_AST_NODE_TYPE_STATEMENT_LIST, B);
}
}
md_triple_for_continuation(A) ::= md_triple_for_continuation(B) MD_TOKEN_COMMA md_statement_not_braced_end(C). {
if (B->type == MD_AST_NODE_TYPE_NOP) {
A = C;
} else {
A = mlr_dsl_ast_node_append_arg(B, C);
}
}
md_triple_for_update(A) ::= md_statement_not_braced_end(B). {
if (B->type == MD_AST_NODE_TYPE_NOP) {
A = mlr_dsl_ast_node_alloc_zary("triple_for_update_statements", MD_AST_NODE_TYPE_STATEMENT_LIST);

View file

@ -5,11 +5,12 @@
// there, and (b) because we get far better control over error messages here (vs. 'syntax error').
// The following flags are used as the CST is built from the AST for CST-build-time validation.
#define IN_BREAKABLE 0x00000200 // break/continue are only OK (recursively) inside for/while/do-while
#define IN_BEGIN_OR_END 0x00000400 // $stuff is not OK (recursively) inside begin/end
#define IN_FUNC_DEF 0x00000800 // local only valid in func/subr; no srec assignments in functions
#define IN_SUBR_DEF 0x00001000 // local only valid in func/subr
#define IN_MLR_FILTER 0x00002000 // Anywhere within mlr filter, the 'filter' keyword is invalid
#define IN_MLR_FINAL_FILTER 0x00004000 // mlr filter's final statement must be a bare boolean
#define IN_BREAKABLE 0x00000200 // break/continue are only OK (recursively) inside for/while/do-while
#define IN_BEGIN_OR_END 0x00000400 // $stuff is not OK (recursively) inside begin/end
#define IN_FUNC_DEF 0x00000800 // local only valid in func/subr; no srec assignments in functions
#define IN_SUBR_DEF 0x00001000 // local only valid in func/subr
#define IN_MLR_FILTER 0x00002000 // Anywhere within mlr filter, the 'filter' keyword is invalid
#define IN_MLR_FINAL_FILTER 0x00004000 // mlr filter's final statement must be a bare boolean
#define IN_TRIPLE_FOR_CONTINUE 0x00004000 // Final statement of triple-for continuation statements must be a bare boolean
#endif // CONTEXT_FLAGS_H

View file

@ -1385,7 +1385,7 @@ static mlr_dsl_cst_statement_t* alloc_triple_for(mlr_dsl_cst_t* pcst, mlr_dsl_as
mlr_dsl_cst_statement_t* pstatement = alloc_blank();
mlr_dsl_ast_node_t* pstart_statements_node = pnode->pchildren->phead->pvvalue;
mlr_dsl_ast_node_t* pcontinuation_statement_node = pnode->pchildren->phead->pnext->pvvalue;
mlr_dsl_ast_node_t* pcontinuation_statements_node = pnode->pchildren->phead->pnext->pvvalue;
mlr_dsl_ast_node_t* pupdate_statements_node = pnode->pchildren->phead->pnext->pnext->pvvalue;
mlr_dsl_ast_node_t* pbody_statements_node = pnode->pchildren->phead->pnext->pnext->pnext->pvvalue;
@ -1396,9 +1396,28 @@ static mlr_dsl_cst_statement_t* alloc_triple_for(mlr_dsl_cst_t* pcst, mlr_dsl_as
type_inferencing, context_flags & ~IN_BREAKABLE));
}
// xxx assert length 1
pstatement->ptriple_for_continuation_evaluator = rval_evaluator_alloc_from_ast(pcontinuation_statement_node,
pcst->pfmgr, type_inferencing, context_flags & ~IN_BREAKABLE);
// Continuation statements are split into the final boolean, and the statements before (if any).
pstatement->ptriple_for_pre_continuation_statements = sllv_alloc();
// Empty continuation for triple-for is an implicit TRUE.
if (pcontinuation_statements_node->pchildren->length == 0) {
pstatement->ptriple_for_continuation_evaluator = rval_evaluator_alloc_from_boolean(TRUE);
} else {
for (sllve_t* pe = pcontinuation_statements_node->pchildren->phead; pe != NULL && pe->pnext != NULL; pe = pe->pnext) {
mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue;
sllv_append(pstatement->ptriple_for_pre_continuation_statements,
mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node,
type_inferencing, context_flags & ~IN_BREAKABLE));
}
mlr_dsl_ast_node_t* pfinal_continuation_statement_node = pcontinuation_statements_node->pchildren->ptail->pvvalue;
if (mlr_dsl_ast_node_cannot_be_bare_boolean(pfinal_continuation_statement_node)) {
fprintf(stderr,
"%s: the final triple-for continutation statement must be a bare boolean.\n",
MLR_GLOBALS.bargv0);
exit(1);
}
pstatement->ptriple_for_continuation_evaluator = rval_evaluator_alloc_from_ast(pfinal_continuation_statement_node,
pcst->pfmgr, type_inferencing, (context_flags & ~IN_BREAKABLE) | IN_TRIPLE_FOR_CONTINUE);
}
pstatement->ptriple_for_update_statements = sllv_alloc();
for (sllve_t* pe = pupdate_statements_node->pchildren->phead; pe != NULL; pe = pe->pnext) {

View file

@ -58,16 +58,9 @@ rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, fmgr_
break;
default:
if (context_flags & IN_MLR_FINAL_FILTER) {
fprintf(stderr,
"%s: expressions for mlr filter must be single statements, evaluating to boolean.\n",
MLR_GLOBALS.bargv0);
exit(1);
} else {
fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
}
fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__);
exit(1);
break;
}
@ -94,6 +87,9 @@ rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, fmgr_
if ((pnode->type != MD_AST_NODE_TYPE_NON_SIGIL_NAME) && (pnode->type != MD_AST_NODE_TYPE_OPERATOR)) {
fprintf(stderr, "%s: internal coding error detected in file %s at line %d (node type %s).\n",
MLR_GLOBALS.bargv0, __FILE__, __LINE__, mlr_dsl_ast_node_describe_type(pnode->type));
printf("XXX\n");
mlr_dsl_ast_node_print(pnode);
printf("XXX\n");
exit(1);
}