emitx iterate

This commit is contained in:
John Kerl 2020-12-27 11:03:49 -05:00
parent b38078930c
commit ab4cb3ebd9
4 changed files with 261 additions and 100 deletions

View file

@ -0,0 +1,103 @@
// ================================================================
// LEXER
!whitespace : ' ' | '\t' | '\n' | '\r' ;
!comment : '#' {.} '\n' ;
_letter : 'a'-'z' | 'A'-'Z' ;
_decdig : '0'-'9' ;
_idchar : _letter | _decdig | '_' ;
emit : 'e' 'm' 'i' 't' ;
// ================================================================
// IMPORT
<< import "miller/dsl" >>
// ================================================================
// PARSER
// ----------------------------------------------------------------
Root
: EmitStatement
<< dsl.NewAST($0) >>
;
// ----------------------------------------------------------------
// Examples:
// emit @a
// emit (@a, @b)
// emit @a, "x", "y"
// emit (@a, @b), "x", "y"
// First argument (single or in parentheses) must be non-indexed
// oosvar/localvar/fieldname, so we can use their names as keys in the emitted
// record. These restrictions are enforced in the CST logic, to keep this
// parser/AST logic simpler.
EmitStatement
: emit Rvalue
<< dsl.NewASTNodeUnary($0, $1, dsl.NodeTypeEmitStatement) >>
| emit Rvalue "," EmitArgs
<< dsl.NewASTNodeBinary($0, $1, $3, dsl.NodeTypeEmitStatement) >>
| emit "(" EmitArgs ")"
<< dsl.NewASTNodeUnary($0, $2, dsl.NodeTypeEmitStatement) >>
| emit "(" EmitArgs ")" "," EmitArgs
<< dsl.NewASTNodeBinary($0, $2, $5, dsl.NodeTypeEmitStatement) >>
;
// ----------------------------------------------------------------
EmitArgs
: Rvalue
<< dsl.NewASTNodeUnary(
nil,
$0,
dsl.NodeTypeFunctionCallsite,
) >>
| Rvalue "," EmitArgs
<< dsl.PrependChild(
$2,
$0,
) >>
;
// ----------------------------------------------------------------
FcnArgs
: Rvalue
<< dsl.NewASTNodeUnary(
nil,
$0,
dsl.NodeTypeFunctionCallsite,
) >>
// Allow trailing final comma, especially for multiline statements
| Rvalue ","
<< dsl.NewASTNodeUnary(
nil,
$0,
dsl.NodeTypeFunctionCallsite,
) >>
// Allow trailing final comma, especially for multiline statements
| Rvalue "," FcnArgs
<< dsl.PrependChild(
$2,
$0,
) >>
;
// ----------------------------------------------------------------
Rvalue
: Literal
| "(" Literal ")"
;
Literal
: "x" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
| "y" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
| "z" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
;

View file

@ -0,0 +1,96 @@
// ================================================================
// LEXER
!whitespace : ' ' | '\t' | '\n' | '\r' ;
!comment : '#' {.} '\n' ;
_letter : 'a'-'z' | 'A'-'Z' ;
_decdig : '0'-'9' ;
_idchar : _letter | _decdig | '_' ;
emit : 'e' 'm' 'i' 't' ;
// ================================================================
// IMPORT
<< import "miller/dsl" >>
// ================================================================
// PARSER
// ----------------------------------------------------------------
Root
: EmitStatement
<< dsl.NewAST($0) >>
;
// ----------------------------------------------------------------
// Examples:
// emit @a
// emit (@a, @b)
// emit @a, "x", "y"
// emit (@a, @b), "x", "y"
// First argument (single or in parentheses) must be non-indexed
// oosvar/localvar/fieldname, so we can use their names as keys in the emitted
// record. These restrictions are enforced in the CST logic, to keep this
// parser/AST logic simpler.
EmitStatement
: emit EmitArgs
<< dsl.NewASTNodeBinary($0, $1, $3, dsl.NodeTypeEmitStatement) >>
;
// ----------------------------------------------------------------
EmitArgs
: Rvalue
<< dsl.NewASTNodeUnary(
nil,
$0,
dsl.NodeTypeFunctionCallsite,
) >>
| Rvalue "," EmitArgs
<< dsl.PrependChild(
$2,
$0,
) >>
;
// ----------------------------------------------------------------
FcnArgs
: Rvalue
<< dsl.NewASTNodeUnary(
nil,
$0,
dsl.NodeTypeFunctionCallsite,
) >>
// Allow trailing final comma, especially for multiline statements
| Rvalue ","
<< dsl.NewASTNodeUnary(
nil,
$0,
dsl.NodeTypeFunctionCallsite,
) >>
// Allow trailing final comma, especially for multiline statements
| Rvalue "," FcnArgs
<< dsl.PrependChild(
$2,
$0,
) >>
;
// ----------------------------------------------------------------
Rvalue
: Literal
| "(" Literal ")"
| "[" Literal "]"
| "[" Literal "," Literal "]"
;
Literal
: "x" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
| "y" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
| "z" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
;

View file

@ -8,9 +8,7 @@ _letter : 'a'-'z' | 'A'-'Z' ;
_decdig : '0'-'9' ;
_idchar : _letter | _decdig | '_' ;
emit : 'e' 'm' 'i' 't' ;
emitp : 'e' 'm' 'i' 't' 'p' ;
emitf : 'e' 'm' 'i' 't' 'f' ;
emit : 'e' 'm' 'i' 't' ;
// ================================================================
// IMPORT
@ -24,10 +22,6 @@ emitf : 'e' 'm' 'i' 't' 'f' ;
Root
: EmitStatement
<< dsl.NewAST($0) >>
| EmitPStatement
<< dsl.NewAST($0) >>
| EmitFStatement
<< dsl.NewAST($0) >>
;
// ----------------------------------------------------------------
@ -41,52 +35,10 @@ Root
// record. These restrictions are enforced in the CST logic, to keep this
// parser/AST logic simpler.
EmitStatement
: emit Rvalue
<< dsl.NewASTNodeUnary($0, $1, dsl.NodeTypeEmitStatement) >>
| emit Rvalue "," EmitArgs
: emit EmitArgs
<< dsl.NewASTNodeBinary($0, $1, $3, dsl.NodeTypeEmitStatement) >>
| emit "(" EmitArgs ")"
<< dsl.NewASTNodeUnary($0, $2, dsl.NodeTypeEmitStatement) >>
| emit "(" EmitArgs ")" "," EmitArgs
<< dsl.NewASTNodeBinary($0, $2, $5, dsl.NodeTypeEmitStatement) >>
;
// Examples: syntactically identical to emit.
EmitPStatement
: emitp Rvalue
<< dsl.NewASTNodeUnary($0, $1, dsl.NodeTypeEmitPStatement) >>
| emitp Rvalue "," EmitArgs
<< dsl.NewASTNodeBinary($0, $1, $3, dsl.NodeTypeEmitPStatement) >>
| emitp "(" EmitArgs ")"
<< dsl.NewASTNodeUnary($0, $2, dsl.NodeTypeEmitPStatement) >>
| emitp "(" EmitArgs ")" "," EmitArgs
<< dsl.NewASTNodeBinary($0, $2, $5, dsl.NodeTypeEmitPStatement) >>
;
// Examples:
// emitf @a
// emitf @a, b, $c
// Each argument must be a non-indexed oosvar/localvar/fieldname, so we can use
// their names as keys in the emitted record. These restrictions are enforced
// in the CST logic, to keep this parser/AST logic simpler.
EmitFStatement
: emitf EmitArgs
<< dsl.AdoptChildren(
dsl.NewASTNodeNestable(
$0,
dsl.NodeTypeEmitFStatement,
),
$1,
) >>
;
// ----------------------------------------------------------------
EmitArgs
: Rvalue
@ -96,7 +48,6 @@ EmitArgs
dsl.NodeTypeFunctionCallsite,
) >>
// Allow trailing final comma, especially for multiline statements
| Rvalue "," EmitArgs
<< dsl.PrependChild(
$2,
@ -132,7 +83,14 @@ FcnArgs
// ----------------------------------------------------------------
Rvalue
: Literal
| "(" Literal ")"
| "[" Literal "]"
| "[" Literal "," Literal "]"
;
Literal
: "x" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
| "y" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
| "z" << dsl.NewASTNodeZary($0, dsl.NodeTypeStringLiteral) >>
;
;

View file

@ -336,56 +336,60 @@ func parseTerminalUsage(args []string, argc int, argi int) bool {
func loadMlrrcOrDie(
options *clitypes.TOptions,
) {
// TODO: finish porting
// char* env_mlrrc = getenv("MLRRC");
// if (env_mlrrc != nil) {
// if env_mlrrc == "__none__" {
// return;
// }
// if (tryLoadMlrrc(popts, env_mlrrc)) {
// return;
// }
// }
//
// char* env_home = getenv("HOME");
// if (env_home != nil) {
// char* path = mlr_paste_2_strings(env_home, "/.mlrrc");
// (void)tryLoadMlrrc(popts, path);
// free(path);
// }
//
// (void)tryLoadMlrrc(popts, "./.mlrrc");
env_mlrrc := os.Getenv("MLRRC")
if env_mlrrc != "" {
if env_mlrrc == "__none__" {
return
}
if tryLoadMlrrc(options, env_mlrrc) {
return
}
}
env_home := os.Getenv("HOME")
if env_home != "" {
path := env_home + "/.mlrrc"
tryLoadMlrrc(options, path)
}
tryLoadMlrrc(options, "./.mlrrc")
}
//static int tryLoadMlrrc(cli_opts_t* popts, char* path) {
// FILE* fp = fopen(path, "r");
// if (fp == nil) {
// return false;
// }
//
// char* line = nil;
// size_t linecap = 0;
// int rc;
// int lineno = 0;
//
// while ((rc = getline(&line, &linecap, fp)) != -1) {
// lineno++;
// char* line_to_destroy = strdup(line);
// if (!handle_mlrrc_line_1(popts, line_to_destroy)) {
// fmt.Fprintf(os.Stderr, "Parse error at file \"%s\" line %d: %s\n",
// path, lineno, line);
// os.Exit(1);
// }
// free(line_to_destroy);
// }
//
// fclose(fp);
// if (line != nil) {
// free(line);
// }
//
// return true;
//}
func tryLoadMlrrc(
options *clitypes.TOptions,
path string,
) bool {
// TODO: finish porting
// FILE* fp = fopen(path, "r");
// if (fp == nil) {
return false
// }
//
// char* line = nil;
// size_t linecap = 0;
// int rc;
// int lineno = 0;
//
// while ((rc = getline(&line, &linecap, fp)) != -1) {
// lineno++;
// char* line_to_destroy = strdup(line);
// if (!handle_mlrrc_line_1(popts, line_to_destroy)) {
// fmt.Fprintf(os.Stderr, "Parse error at file \"%s\" line %d: %s\n",
// path, lineno, line);
// os.Exit(1);
// }
// free(line_to_destroy);
// }
//
// fclose(fp);
// if (line != nil) {
// free(line);
// }
//
// return true;
}
// Chomps trailing CR, LF, or CR/LF; comment-strips; left-right trims.