[Pharo-project] learning rewrite rules
Hi, I am trying to write a rewrite rule to replace something like: browser showOn: #xxx; from: #yyy; using: [ browser list ... browser tree ... ] to something like: browser transmit to: #xxx; from: #yyy; andShow: [:a | a list ... a tree ... ] I managed to do the following: RBParseTreeRewriter new replace: '`@browser showOn: `@target; from: `@origin; using: [ ``@.statements ]' with: '`@browser transmit to: `@target; from: `@origin; andShow: [:a | ``@.statements]'; yourself However, the problem here is that I do not know how to replace all the "browser" appearances with "a" inside the andShow: block. I tried multiple variations like the one below, but I could not seem to get it to work as I want. replace: '`@browser showOn: `@target; from: `@origin; using: [ `@browser ``@.statements]' with: '`@browser transmit to: `@target; from: `@origin; andShow: [:a | a ``@.statements]'; Can anyone point me into the right direction? Cheers, Doru -- www.tudorgirba.com "What we can governs what we wish."
However, the problem here is that I do not know how to replace all the "browser" appearances with "a" inside the andShow: block. I tried multiple variations like the one below, but I could not seem to get it to work as I want.
    replace: '`@browser showOn: `@target; from: `@origin; using: [         `@browser ``@.statements]' with: '`@browser transmit to: `@target; from: `@origin; andShow: [:a | a ``@.statements]';
Can anyone point me into the right direction?
Yes, you can put in the replacement code some code snippets like `{ :context | ... } Replace the "..." with some Smalltalk code that returns a parse tree node (or a collection of parse-tree nodes). The context-variable is a dictionary containing the current bindings of the matched nodes. So you can perform a sub-rewrite on ``@.statements to replace all accesses to `@browser with the variable a; and you return the transformed tree. Lukas -- Lukas Renggli www.lukas-renggli.ch
Thanks. I will look into this. In the meantime, I have another question: is there a way to specify that a certain pattern can appear multiple times and that I am interested in all occurrences? For example, I can have multiple appearances of "browser xyz" inside the following block: browser showOn: #xxx; from: #yyy; using: [ browser list ... browser tree ... browser text ] If I try to match it like: '`@browser showOn: `@target; from: `@origin; using: [ `@browser ``@.statements]' It seems to only get those appearances which contain a single appearance of browser inside the block. Cheers, Doru On 3 Nov 2010, at 16:55, Lukas Renggli wrote:
However, the problem here is that I do not know how to replace all the "browser" appearances with "a" inside the andShow: block. I tried multiple variations like the one below, but I could not seem to get it to work as I want.
replace: '`@browser showOn: `@target; from: `@origin; using: [ `@browser ``@.statements]' with: '`@browser transmit to: `@target; from: `@origin; andShow: [:a | a ``@.statements]';
Can anyone point me into the right direction?
Yes, you can put in the replacement code some code snippets like
`{ :context | ... }
Replace the "..." with some Smalltalk code that returns a parse tree node (or a collection of parse-tree nodes). The context-variable is a dictionary containing the current bindings of the matched nodes. So you can perform a sub-rewrite on ``@.statements to replace all accesses to `@browser with the variable a; and you return the transformed tree.
Lukas
-- Lukas Renggli www.lukas-renggli.ch
-- www.tudorgirba.com "Be rather willing to give than demanding to get."
If I try to match it like: Â '`@browser showOn: `@target; from: `@origin; using: [ `@browser ``@.statements]'
The match expression `@browser ``@.statements doesn't make sense. Statements (.) cannot be a message selector that would be expected after a receiver. Also, you cannot have a selector list (@) if you don't give also an argument list to match. So the closest valid thing is `@browser `message which looks for unary message sends (recursive is not necessary here either, because there is nothing to recurse into), or `@browser `@message: ``@message which looks for arbitrary message sends and recursively into all arguments.
It seems to only get those appearances which contain a single appearance of browser inside the block.
As I wrote in the previous mail you need to do it with nested rewrites. Inside the block you match for any sequence of statements: `@.statements And as replacement you use the `{ :context | ... } trick to perform a new rewrite somehow along the following untested lines: `{ :context | RBParseTreeRewriter new " replace whatever matched to `@browser with the variable a " replaceTree: (context at: '`@browser') with: (RBParser parseExpression: 'a'); " execute on the list of statements " executeTree: (context at: '`@.statements'); " return the rewritten tree " tree } Cheers, Lukas -- Lukas Renggli www.lukas-renggli.ch
participants (2)
-
Lukas Renggli -
Tudor Girba