Received: from mx0.gmx.net (mx0.gmx.net [213.165.64.100]) by h1439878.stratoserver.net (8.14.2/8.14.2/Debian-2build1) with SMTP id q12G09qX030103 for ; Thu, 2 Feb 2012 17:00:10 +0100 Received: (qmail 11537 invoked by alias); 2 Feb 2012 16:00:04 -0000 Delivered-To: GMX delivery to rainer.schoepf@gmx.net Received: (qmail invoked by alias); 02 Feb 2012 16:00:04 -0000 Received: from relay.uni-heidelberg.de (EHLO relay.uni-heidelberg.de) [129.206.100.212] by mx0.gmx.net (mx044) with SMTP; 02 Feb 2012 17:00:04 +0100 Received: from listserv.uni-heidelberg.de (listserv.uni-heidelberg.de [129.206.100.94]) by relay.uni-heidelberg.de (8.14.1/8.14.1) with ESMTP id q12FvN5C000699 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Thu, 2 Feb 2012 16:57:23 +0100 Received: from listserv.uni-heidelberg.de (localhost.localdomain [127.0.0.1]) by listserv.uni-heidelberg.de (8.13.1/8.13.1) with ESMTP id q12FU3v1005897; Thu, 2 Feb 2012 16:57:22 +0100 Received: by LISTSERV.UNI-HEIDELBERG.DE (LISTSERV-TCP/IP release 16.0) with spool id 2059285 for LATEX-L@LISTSERV.UNI-HEIDELBERG.DE; Thu, 2 Feb 2012 16:57:22 +0100 Received: from relay2.uni-heidelberg.de (relay2.uni-heidelberg.de [129.206.210.211]) by listserv.uni-heidelberg.de (8.13.1/8.13.1) with ESMTP id q12FvMEW004404 for ; Thu, 2 Feb 2012 16:57:22 +0100 Received: from mail-lpp01m010-f49.google.com (mail-lpp01m010-f49.google.com [209.85.215.49]) by relay2.uni-heidelberg.de (8.13.8/8.13.8) with ESMTP id q12FvHk9014041 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=FAIL) for ; Thu, 2 Feb 2012 16:57:20 +0100 Received: by laam7 with SMTP id m7so1891100laa.22 for ; Thu, 02 Feb 2012 07:57:16 -0800 (PST) MIME-Version: 1.0 Received: by 10.112.100.164 with SMTP id ez4mr918776lbb.46.1328198236834; Thu, 02 Feb 2012 07:57:16 -0800 (PST) Received: by 10.152.13.106 with HTTP; Thu, 2 Feb 2012 07:57:16 -0800 (PST) References: <20120202102957.GB14566@csmvddesktop> <4F2A68F9.1010508@morningstar2.co.uk> <20120202111808.GA15304@csmvddesktop> <20120202131844.GA16372@csmvddesktop> <20120202133153.GA16604@csmvddesktop> Content-Type: text/plain; charset=ISO-8859-1 X-Spam-Whitelist: Message-ID: Date: Thu, 2 Feb 2012 10:57:16 -0500 Reply-To: Mailing list for the LaTeX3 project Sender: Mailing list for the LaTeX3 project From: Bruno Le Floch Subject: Re: Mapping Functions Versions for All and Some To: LATEX-L@listserv.uni-heidelberg.de In-Reply-To: <20120202133153.GA16604@csmvddesktop> Precedence: list List-Help: , List-Unsubscribe: List-Subscribe: List-Owner: List-Archive: X-GMX-Antispam: 0 (BackTrace mail analyze); Detail=5D7Q89H36p4L00VTXC6D4q0N+AH0PUCnGL2vqOgpaBYL16oitsMrgDt/NQNpSCZFFjDOy 97xb7Zpf+wZnd5ZXNcvLDXR3Wg3wRjdQbwEMh8=V1; X-Resent-By: Forwarder X-Resent-For: rainer.schoepf@gmx.net X-Resent-To: rainer@rainer-schoepf.de Status: R X-Status: X-Keywords: X-UID: 7007 Hello Marc, > : Now here is the question. What I'd like to know if there's an easy way > : for a substitution of the form > : a[expression] -> \csname myA[expression]\endcsname \regex_replace_all:nnN { a \[ (.+?) \] } { \c{ myA \[ \1 \] } } \l_your_tl or, if the names "a" and "myA" are actually stored in some variables (in particular, if they contain characters that may be unsafe in regular expressions), say, \l_array_name_tl and \l_rec_name_tl, you can use the \u escape sequence (specific to l3regex, not present in Perl or PCRE): \regex_replace_all:nnN { \u{l_array_name_tl} \[ (.+?) \] } { \c{ \u{l_rec_name_tl} \[ \1 \] } } \l_your_tl =================================== Feel free to ask details about the syntax: I'm not happy with how it's explained in the doc. Here is a possible approach for parsing the whole thing. I'm not entirely sure what you have in mind as a syntax, so I may be a tad wrong in the following. I'm basing myself on your example \NewRecDef{myA}{ a[i]=1 | 0 <= i && i <= 1, a[i]=a[i-1]+a[i-2] | true } So the input is a comma list of expressions of the form a[i]= | and given a value of i, we compute a[i] by looping through the comma list, testing the , stopping at the first one that yields "true", and evaluating the , possibly calling a recursively. If I understand correctly, you want to use regular expressions to parse that. I think it is possible. A starting point is as follows. I'm using \tl_replace_all whenever possible rather than the more powerful regex features, because the former is roughly 100 times faster. \RequirePackage{xparse,l3regex} \ExplSyntaxOn \cs_generate_variant:Nn \tl_replace_all:Nnn { Nx } \tl_new:N \l_nrd_name_tl \tl_new:N \l_nrd_input_tl \tl_new:N \l_nrd_tmp_tl \tl_new:N \l_nrd_array_name_tl \tl_new:N \l_nrd_index_name_tl \tl_new:N \l_nrd_expression_tl \tl_new:N \l_nrd_bool_expr_tl \int_new:N \l_nrd_arg_int \seq_new:N \l_nrd_tmp_seq \seq_new:N \l_nrd_parsed_seq \DeclareDocumentCommand{\NewRecDef}{mm} { \tl_set:Nn \l_nrd_name_tl {#1} \seq_clear:N \l_nrd_parsed_seq \clist_map_inline:nn {#2} { \regex_extract_once:nnNTF { ^(\w+)\[(\w+)\]\=(.+?)\|(.+) } {##1} \l_nrd_tmp_seq { % at this stage, \l_nrd_tmp_seq has 5 items, % 0th: a[i]=1 | 0 <= i && i <= 1 \seq_pop:NN \l_nrd_tmp_seq \l_nrd_tmp_tl % 1st: a (array name) \seq_pop:NN \l_nrd_tmp_seq \l_nrd_array_name_tl % 2nd: i (index name) \seq_pop:NN \l_nrd_tmp_seq \l_nrd_index_name_tl % 3rd: 1 (or more general expression) \seq_pop:NN \l_nrd_tmp_seq \l_nrd_expression_tl \tl_replace_all:Nxn \l_nrd_bool_expr_tl \l_nrd_index_name_tl { \l_nrd_arg_int } \regex_replace_all:nnN { \u{l_nrd_array_name_tl} \[ (.+?) \] } { \c{nrd_array:n} \cB\{ \1 \cE\} } \l_nrd_expression_tl % \tl_show:N \l_nrd_expression_tl % 4th: 0<=i&&i<=1 \seq_pop:NN \l_nrd_tmp_seq \l_nrd_bool_expr_tl \tl_set:Nx \l_nrd_bool_expr_tl { ( \l_nrd_bool_expr_tl ) } \tl_replace_all:Nxn \l_nrd_bool_expr_tl \l_nrd_index_name_tl { \l_nrd_arg_int } \tl_replace_all:Nnn \l_nrd_bool_expr_tl { ( } { ( \nrd_test:w [ } \tl_replace_all:Nnn \l_nrd_bool_expr_tl { ) } { ] ) } \tl_replace_all:Nxn \l_nrd_bool_expr_tl { \tl_to_str:n {&&} } { ] && \nrd_test:w [ } \tl_replace_all:Nxn \l_nrd_bool_expr_tl { \tl_to_str:n {||} } { ] || \nrd_test:w [ } % \tl_show:N \l_nrd_bool_expr_tl \seq_put_right:Nx \l_nrd_parsed_seq { \exp_not:N \bool_if:nTF { \exp_not:V \l_nrd_bool_expr_tl } { \message { test ~ " \tl_to_str:N \l_nrd_bool_expr_tl " ~ succeeded ! } % do something with \l_nrd_expression_tl \exp_not:N \prg_map_break: } } } { \msg_error:nnx { nrd } { wrong-input } { \tl_to_str:n {##1} } } } } \cs_new:Npn \nrd_test:w [ #1 ] { \str_if_eq:xxTF {#1} {true} { \c_true_bool } { \str_if_eq:xxTF {#1} {false} { \c_false_bool } { \int_compare_p:n {#1} } } } \ExplSyntaxOff So, roughly the idea is that each item of the clist has the form [] = | and we extract the , , and using a regex. Then in the , replace all occurrences of by \l_nrd_arg_int, and [] by \nrd_array:n {}, where we expect to be a valid integer expression now that we've replaced by \l_nrd_arg_int. On the other hand, the is converted to a boolean expression in the sense of LaTeX3, which requires us to wrap each of the comparisons in \int_compare_p:n. Since I don't know how complicated those comparisons can be, I did the opposite, which is to wrap each operator: (, ), &&, ||, with the relevant \nrd_test:w [ or ]. I'm not using braces here because the output must be brace-balanced in all cases. At the end of the day, \nrd_test:w [#1] tests whether its argument is "true", "false", or an integer comparison (remember, "i" got converted to \l_nrd_arg_int). Presumably, using those expressions, you can reach your goal. > I think I've solved the problem, so I probably won't need to know > about the substitution. If the answer is easy, I'd still like to > know. Otherwise, please forget about it. I hope the first part of that email was easy enough; the second part probably wasn't :). I assume that you are going to post the final solution on TeX.sx? Cheers, Bruno