mirror of
https://github.com/johnkerl/miller.git
synced 2026-07-28 10:13:59 +00:00
triple-for multi-continuation 1st light
This commit is contained in:
parent
eb15c07e33
commit
8769fb18f7
6 changed files with 73 additions and 39 deletions
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue