diff options
-rw-r--r-- | ChangeLog | 9 | ||||
-rw-r--r-- | match.c | 34 | ||||
-rw-r--r-- | txr.1 | 12 |
3 files changed, 45 insertions, 10 deletions
@@ -1,5 +1,14 @@ 2012-03-30 Kaz Kylheku <kaz@kylheku.com> + * match.c (h_var): Disallow the variable named by the symbol t + by throwing an exception. Allow nil, but wherever nil occurs, + do not produce a binding. + + * txr.1: State the restrictions against using t in the section + on Variables and also describe the nil ignore feature. + +2012-03-30 Kaz Kylheku <kaz@kylheku.com> + * txr.1: Correction: backtracking does NOT take place into a block which completed. @@ -463,8 +463,11 @@ static val h_var(match_line_ctx *c) val pat = third(elem); val modifiers = fourth(elem); val modifier = first(modifiers); - val pair = assoc(sym, c->bindings); /* var exists already? */ + val pair = if2(sym, assoc(sym, c->bindings)); /* exists? */ + if (sym == t) + sem_error(elem, lit("t is not a bindable symbol"), nao); + if (gt(length_list(modifiers), one)) { sem_error(elem, lit("multiple modifiers on variable ~s"), sym, nao); @@ -511,7 +514,8 @@ static val h_var(match_line_ctx *c) } LOG_MATCH("var spanning form", new_pos); - c->bindings = acons(sym, sub_str(c->dataline, c->pos, new_pos), new_bindings); + if (sym) + c->bindings = acons(sym, sub_str(c->dataline, c->pos, new_pos), new_bindings); c->pos = new_pos; /* This may have another variable attached */ if (pat) { @@ -526,7 +530,8 @@ static val h_var(match_line_ctx *c) return nil; } LOG_MATCH("count based var", past); - c->bindings = acons(sym, trim_str(sub_str(c->dataline, c->pos, past)), c->bindings); + if (sym) + c->bindings = acons(sym, trim_str(sub_str(c->dataline, c->pos, past)), c->bindings); c->pos = past; /* This may have another variable attached */ if (pat) { @@ -537,7 +542,8 @@ static val h_var(match_line_ctx *c) sem_error(elem, lit("invalid modifier ~s on variable ~s"), modifier, sym, nao); } else if (pat == nil) { /* no modifier, no elem -> to end of line */ - c->bindings = acons(sym, sub_str(c->dataline, c->pos, nil), c->bindings); + if (sym) + c->bindings = acons(sym, sub_str(c->dataline, c->pos, nil), c->bindings); c->pos = length_str(c->dataline); } else if (type(pat) == STR) { val find = search_str(c->dataline, pat, c->pos, modifier); @@ -546,7 +552,8 @@ static val h_var(match_line_ctx *c) return nil; } LOG_MATCH("var delimiting string", find); - c->bindings = acons(sym, sub_str(c->dataline, c->pos, find), c->bindings); + if (sym) + c->bindings = acons(sym, sub_str(c->dataline, c->pos, find), c->bindings); c->pos = plus(find, length_str(pat)); } else if (consp(pat) && first(pat) != var_s) { val find = search_form(c, pat, modifier); @@ -557,7 +564,8 @@ static val h_var(match_line_ctx *c) return nil; } LOG_MATCH("var delimiting form", fpos); - c->bindings = acons(sym, sub_str(c->dataline, c->pos, fpos), c->bindings); + if (sym) + c->bindings = acons(sym, sub_str(c->dataline, c->pos, fpos), c->bindings); c->pos = if3(flen == t, t, plus(fpos, flen)); } else if (consp(pat)) { /* Unbound var followed by var: the following one must either @@ -566,7 +574,7 @@ static val h_var(match_line_ctx *c) val next_pat = third(pat); val next_modifiers = fourth(pat); val next_modifier = first(fourth(pat)); - val pair = assoc(second_sym, c->bindings); /* var exists already? */ + val pair = if2(second_sym, assoc(second_sym, c->bindings)); /* exists? */ if (gt(length_list(next_modifiers), one)) { sem_error(elem, lit("multiple modifiers on variable ~s"), @@ -585,10 +593,15 @@ static val h_var(match_line_ctx *c) /* Text from here to start of regex match goes to this variable. */ - c->bindings = acons(sym, sub_str(c->dataline, c->pos, fpos), c->bindings); + if (sym) + c->bindings = acons(sym, sub_str(c->dataline, c->pos, fpos), + c->bindings); /* Text from start of regex match to end goes to the second variable */ - c->bindings = acons(second_sym, sub_str(c->dataline, fpos, plus(fpos, flen)), c->bindings); + if (second_sym) + c->bindings = acons(second_sym, + sub_str(c->dataline, fpos, plus(fpos, flen)), + c->bindings); LOG_MATCH("double var regex (first var)", fpos); c->pos = fpos; LOG_MATCH("double var regex (second var)", plus(fpos, flen)); @@ -616,7 +629,8 @@ static val h_var(match_line_ctx *c) LOG_MISMATCH("string"); return nil; } - c->bindings = acons(sym, sub_str(c->dataline, c->pos, find), c->bindings); + if (sym) + c->bindings = acons(sym, sub_str(c->dataline, c->pos, find), c->bindings); c->pos = plus(find, len); } else { sem_error(elem, lit("variable followed by invalid element"), nao); @@ -572,6 +572,11 @@ The forms with an * indicate a long match, see Longest Match below. The last two forms with the embedded regexp /RE/ or number have special semantics, see Positive Match below. +The identifier t cannot be used as a name; it is a reserved symbol which +denotes the value true. An attempt to use the variable @t will result +in an exception. The symbol nil can be used as a variable name, +but it has special semantics, described in a section below. + When the @NAME form is used, the name itself may consist of any combination of one or more letters, numbers, and underscores. It may not look like a number, so that for instance 123 is not a valid name, but 12A is valid. Case is @@ -820,6 +825,13 @@ This syntax is processed without consideration of what other syntax follows. A positive match may be directly followed by an unbound variable. +.SS Symbol nil as a Variable + +If the symbol nil is used as a variable, it behaves like a variable which +has no binding. Furthermore, no binding is created. @nil allows the +variable matching syntax to be used to skip material, in ways different +from and complementary to @(skip). + .SS Regular Expressions Regular expressions are a language for specifying sets of character strings. |