diff options
-rw-r--r-- | generic/tclCompExpr.c | 20 | ||||
-rw-r--r-- | tests/compExpr.test | 36 | ||||
-rw-r--r-- | tests/expr-old.test | 2 | ||||
-rw-r--r-- | tests/expr.test | 34 | ||||
-rw-r--r-- | tests/parseExpr.test | 8 |
5 files changed, 97 insertions, 3 deletions
diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c index 74610c7..5c5a491 100644 --- a/generic/tclCompExpr.c +++ b/generic/tclCompExpr.c @@ -164,6 +164,8 @@ enum Marks { * "=" is encountered. */ #define INVALID 5 /* A parse error. Used when any punctuation * appears that's not a supported operator. */ +#define COMMENT 6 /* Comment. Lasts to end of line or end of + * expression, whichever comes first. */ /* Leaf lexemes */ @@ -462,7 +464,7 @@ static const unsigned char Lexeme[] = { INVALID /* FS */, INVALID /* GS */, INVALID /* RS */, INVALID /* US */, INVALID /* SPACE */, 0 /* ! or != */, - QUOTED /* " */, INVALID /* # */, + QUOTED /* " */, 0 /* # */, VARIABLE /* $ */, MOD /* % */, 0 /* & or && */, INVALID /* ' */, OPEN_PAREN /* ( */, CLOSE_PAREN /* ) */, @@ -708,6 +710,10 @@ ParseExpr( int b; switch (lexeme) { + case COMMENT: + start += scanned; + numBytes -= scanned; + continue; case INVALID: msg = Tcl_ObjPrintf("invalid character \"%.*s\"", scanned, start); @@ -1892,7 +1898,7 @@ ParseLexeme( storage, if non-NULL. */ { const char *end; - int scanned; + int scanned, size; Tcl_UniChar ch = 0; Tcl_Obj *literal = NULL; unsigned char byte; @@ -1907,6 +1913,16 @@ ParseLexeme( return 1; } switch (byte) { + case '#': + /* + * Scan forward over the comment contents. + */ + for (size = 0; byte != '\n' && byte != 0 && size < numBytes; size++) { + byte = UCHAR(start[size]); + } + *lexemePtr = COMMENT; + return size - (byte == '\n'); + case '*': if ((numBytes > 1) && (start[1] == '*')) { *lexemePtr = EXPON; diff --git a/tests/compExpr.test b/tests/compExpr.test index 3b44af8..8803f17 100644 --- a/tests/compExpr.test +++ b/tests/compExpr.test @@ -371,10 +371,46 @@ test compExpr-7.2 {[Bug 1869989]: expr parser memleak} -constraints memory -setu unset end i tmp rename getbytes {} } -result 0 + +proc extract {opcodes descriptor} { + set instructions [dict values [dict get $descriptor instructions]] + return [lmap i $instructions { + if {[lindex $i 0] in $opcodes} {string cat $i} else continue + }] +} + +test compExpr-8.1 {TIP 582: expression comments} -setup {} -body { + extract {loadStk add} [tcl::unsupported::getbytecode script {expr { + $abc + # + $def + + $ghi + }}] +} -result {loadStk loadStk add} +test compExpr-8.2 {TIP 582: expression comments} -setup {} -body { + extract {loadStk add} [tcl::unsupported::getbytecode script {expr { + $abc + # + $def + # + $ghi }}] +} -result loadStk +test compExpr-8.3 {TIP 582: expression comments} -setup {} -body { + extract {loadStk add} [tcl::unsupported::getbytecode script {expr { + $abc + # + $def\ + + $ghi + }}] +} -result loadStk +test compExpr-8.4 {TIP 582: expression comments} -setup {} -body { + extract {loadStk add} [tcl::unsupported::getbytecode script {expr { + $abc + # + $def\\ + + $ghi + }}] +} -result {loadStk loadStk add} # cleanup catch {unset a} catch {unset b} +catch {rename extract ""} ::tcltest::cleanupTests return diff --git a/tests/expr-old.test b/tests/expr-old.test index 003ee00..de10da0 100644 --- a/tests/expr-old.test +++ b/tests/expr-old.test @@ -522,7 +522,7 @@ test expr-old-26.10b {error conditions} ieeeFloatingPoint { list [catch {expr 2.0/0.0} msg] $msg } {0 Inf} test expr-old-26.11 {error conditions} -body { - expr 2# + expr 2` } -returnCodes error -match glob -result * test expr-old-26.12 {error conditions} -body { expr a.b diff --git a/tests/expr.test b/tests/expr.test index 632f1c4..ef00464 100644 --- a/tests/expr.test +++ b/tests/expr.test @@ -7384,6 +7384,40 @@ foreach v1 $values r1 $results { } } unset -nocomplain values results ctr + +test expr-62.1 {TIP 582: comments} -body { + expr {1 # + 2} +} -result 1 +test expr-62.2 {TIP 582: comments} -body { + expr "1 #\n+ 2" +} -result 3 +test expr-62.3 {TIP 582: comments} -setup { + set ctr 0 +} -body { + expr { + # This is a demonstration of a comment + 1 + 2 + 3 + # and another comment + + 4 + 5 + # + [incr ctr] + + [incr ctr] + } +} -result 16 +# Buggy because line breaks aren't tracked inside expressions at all +test expr-62.4 {TIP 582: comments don't hide line breaks} -setup { + proc getline {} { + dict get [info frame -1] line + } + set base [getline] +} -constraints knownBug -body { + expr { + 0 + # a comment + + [getline] - $base + } +} -cleanup { + rename getline "" +} -result 5 # cleanup unset -nocomplain a diff --git a/tests/parseExpr.test b/tests/parseExpr.test index 47dbec5..8ca5fca 100644 --- a/tests/parseExpr.test +++ b/tests/parseExpr.test @@ -1073,6 +1073,14 @@ test parseExpr-22.21 {Bug d2ffcca163} -constraints testexprparser -body { testexprparser in\u0433(0) -1 } -returnCodes error -match glob -result {missing operand*} +test parseExpr-23.1 {TIP 582: comments} -constraints testexprparser -body { + testexprparser "7 # * 8 " -1 +} -result {- {} 0 subexpr 7 1 text 7 0 {}} +test parseExpr-23.2 {TIP 582: comments} -constraints testexprparser -body { + testexprparser "7 #\n* 8 " -1 +} -result {- {} 0 subexpr {7 # +*} 5 operator # 0 subexpr 7 1 text 7 0 subexpr * 1 text * 0 {}} + # cleanup cleanupTests return |