mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-01 12:11:15 +00:00
add CST validation for unique variable names in two-variable and multivariable for-loops
This commit is contained in:
parent
a878fff553
commit
8a7d24ede0
4 changed files with 95 additions and 14 deletions
|
|
@ -273,7 +273,6 @@ RAW AST:
|
|||
* full record "$*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for (k, k in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -286,7 +285,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,a), c in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -301,7 +299,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,b), a in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -316,7 +313,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,b), b in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -331,7 +327,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,a,c), d in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -347,7 +342,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,b,a), d in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -363,7 +357,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,b,c), a in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -379,7 +372,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,b,b), d in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -395,7 +387,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,b,c), b in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -411,7 +402,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr -n put -v for ((a,b,c), c in @*) {}
|
||||
DSL EXPRESSION:
|
||||
|
|
@ -427,7 +417,6 @@ RAW AST:
|
|||
* full oosvar "@*"
|
||||
* statement block
|
||||
|
||||
Exit status was 0; expected 1.
|
||||
|
||||
mlr --from ./reg-test/input/xyz2 put -q func f() { return {"a"."b":"c"."d",3:4}}; for (k,v in f()){print "k=".k.",v=".v}
|
||||
k=ab,v=cd
|
||||
|
|
@ -9,8 +9,10 @@ package cst
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"miller/dsl"
|
||||
"miller/lib"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
|
@ -122,6 +124,18 @@ func validateASTAux(
|
|||
}
|
||||
nextLevelInUDS = true
|
||||
}
|
||||
if astNode.Type == dsl.NodeTypeForLoopTwoVariable {
|
||||
err := validateForLoopTwoVariableUniqueNames(astNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if astNode.Type == dsl.NodeTypeForLoopMultivariable {
|
||||
err := validateForLoopMultivariableUniqueNames(astNode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Check: $-anything cannot be in begin/end
|
||||
if inBeginOrEnd {
|
||||
|
|
@ -241,6 +255,87 @@ func validateASTAux(
|
|||
return nil
|
||||
}
|
||||
|
||||
// Check against 'for (a, a in $*)' -- repeated 'a'.
|
||||
// AST:
|
||||
// * statement block
|
||||
// * double-variable for-loop "for"
|
||||
// * local variable "a"
|
||||
// * local variable "a"
|
||||
// * full record "$*"
|
||||
// * statement block
|
||||
|
||||
func validateForLoopTwoVariableUniqueNames(astNode *dsl.ASTNode) error {
|
||||
lib.InternalCodingErrorIf(astNode.Type != dsl.NodeTypeForLoopTwoVariable)
|
||||
lib.InternalCodingErrorIf(len(astNode.Children) != 4)
|
||||
keyVarNode := astNode.Children[0]
|
||||
valVarNode := astNode.Children[1]
|
||||
lib.InternalCodingErrorIf(keyVarNode.Type != dsl.NodeTypeLocalVariable)
|
||||
lib.InternalCodingErrorIf(valVarNode.Type != dsl.NodeTypeLocalVariable)
|
||||
keyVarName := string(keyVarNode.Token.Lit)
|
||||
valVarName := string(valVarNode.Token.Lit)
|
||||
if keyVarName == valVarName {
|
||||
return errors.New(
|
||||
fmt.Sprintf(
|
||||
"%s: redefinition of variable %s in the same scope.",
|
||||
os.Args[0],
|
||||
keyVarName,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// Check against 'for ((a,a), b in $*)' or 'for ((a,b), a in $*)' -- repeated 'a'.
|
||||
// AST:
|
||||
// * statement block
|
||||
// * multi-variable for-loop "for"
|
||||
// * parameter list
|
||||
// * local variable "a"
|
||||
// * local variable "b"
|
||||
// * local variable "a"
|
||||
// * full record "$*"
|
||||
// * statement block
|
||||
func validateForLoopMultivariableUniqueNames(astNode *dsl.ASTNode) error {
|
||||
lib.InternalCodingErrorIf(astNode.Type != dsl.NodeTypeForLoopMultivariable)
|
||||
keyVarsNode := astNode.Children[0]
|
||||
valVarNode := astNode.Children[1]
|
||||
lib.InternalCodingErrorIf(keyVarsNode.Type != dsl.NodeTypeParameterList)
|
||||
lib.InternalCodingErrorIf(valVarNode.Type != dsl.NodeTypeLocalVariable)
|
||||
|
||||
seen := make(map[string]bool)
|
||||
|
||||
for _, keyVarNode := range keyVarsNode.Children {
|
||||
lib.InternalCodingErrorIf(keyVarNode.Type != dsl.NodeTypeLocalVariable)
|
||||
name := string(keyVarNode.Token.Lit)
|
||||
_, present := seen[name]
|
||||
if present {
|
||||
return errors.New(
|
||||
fmt.Sprintf(
|
||||
"%s: redefinition of variable %s in the same scope.",
|
||||
os.Args[0],
|
||||
name,
|
||||
),
|
||||
)
|
||||
}
|
||||
seen[name] = true
|
||||
}
|
||||
|
||||
valVarName := string(valVarNode.Token.Lit)
|
||||
if seen[valVarName] {
|
||||
return errors.New(
|
||||
fmt.Sprintf(
|
||||
"%s: redefinition of variable %s in the same scope.",
|
||||
os.Args[0],
|
||||
valVarName,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
var VALID_LHS_NODE_TYPES = map[dsl.TNodeType]bool{
|
||||
dsl.NodeTypeArrayOrMapIndexAccess: true,
|
||||
dsl.NodeTypeArrayOrMapPositionalNameAccess: true,
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@ bugs:
|
|||
mlr put -q 'print | "tr \[a-z\] \[A-Z\]", "abi:".$a.$b.$i' s
|
||||
mlr: cannot parse DSL expression.
|
||||
|
||||
* ./reg-test/cases/case-c-dsl-break-continue.sh
|
||||
bug w/ break
|
||||
|
||||
* ./reg-test/cases/case-c-dsl-for-oosvar-loops.sh
|
||||
bug w/ non-unique for-loop names: e.g. 'for(a,a in $*)'
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue