1
Other / new tutorial about the if-then-else structure
« on: August 23, 2002, 12:47:54 AM »
hi friend,
i've written this new tutorial about the use of an implied if-then-else structure in filters. it was originated from the discussion i had on this forum with hpguru, sidki, jor, jd and tegghead. but, as always, also members who hadn't part in that discussion have contributed because all here have learned a lot from their posts, so thank you all.
here is the tutorial. i have written it in a couple of hours so i'm sure there are many other things that could be added: let me know your comments and suggestions.
-------------------- start here -----------------------------
***********************************************************
THE PROXOMITRON FILTERS TUTORIAL
How write filters using an implied if-then-else structure
by altosax
Created August 22, 2002 - Updated August 23, 2002
***********************************************************
INTRODUCTION
This tutorial explains how write filters able to perform an if-then-else check to be used with The Proxomitron, by Scott R. Lemmon. If you don't understand what i wrote in this tutorial, please read the Proxomitron help first.
UNDERSTAND THE PROBLEM
The Proxomitron matching language is a specific language created by Scott R. Lemmon with a subset of characters and symbols used for the regular expressions, to allow the user to write himself his own filters.
Although it is much powerful, and allows the user to write really complex filters, this means that The Proxomitron matching language is not a programming language and can not provide some logical structures you can find in the high level programming languages.
A useful structure that the user could need while he is writing a filter is the if-then-else check. This way he could test when a condition is true and do something otherwise do something other.
The main intent of this tutorial is to show the way this can be done using The Proxomitron language and its built-in commands.
SOME EXAMPLES REQUIRING AN IF-THEN-ELSE
The following examples comes from the real questions posted by some Proxomitron users at http://asp.flaaten.dk/pforum/ that have originated the discussion about the way to write an implied if-then-else structure in the filters.
- Example 1
Suppose you have to close the <head> tag when </head> is missing.
To solve this problem you can think this:
IF </head> exists
THEN do nothing
ELSE
IF </head> is missing
THEN add it
- Example 2
You want to set the image border to 0 both if the border attribute exists or not.
To solve this problem you can think this:
IF the border attribute exists
THEN set it to 0
ELSE
IF the border attribute not exists
THEN add it
- Example 3
You want to write a simple filter to view the page comments.
To solve this problem you can think this:
IF the opening comment tag is encountered
THEN modify it to something other
ELSE
IF the closing comment tag is encountered
THEN modify it to something other
HOW WRITE THE IF-THEN-ELSE
The most effective way to write this kind of structure in a filter is to use 2 different matching expressions separated by an OR function, each using a SET command.
This table shows the corrispondences:
IF = first matching expression
THEN = first SET command
ELSE = |
IF = second matching expression
THEN = second SET command
If you have to test more than an IF case, you can add to the basic structure the required number of else-if-then as follows:
ELSE = |
IF = new matching expression
THEN = new SET command
After doing this, you simply have to replace the variables set in the if clauses.
SOLVING THE PROPOSED EXAMPLES
Here you can view how easy is to solve the previous problems using an if-then-else structure.
- Example 1
We have to close the <head> tag when </head> is missing.
IF </head> exists = first matching expression
THEN do nothing = first SET command
ELSE = |
IF </head> is missing = second matching expression
THEN add it = second SET command
Match = "</head>$SET(1=</head>)"
"|"
"<body$SET(1=</head><body)"
Replace = "1"
We can learn from this example that:
a) "do nothing" is equal to "set the variable to what matched";
b) when the code we are searching for is missing we have to match what follows then inject it in front of what matched.
- Example 2
We have to set the image border to 0 both if the border attribute exists or not.
IF the border attribute exists = first matching expression
THEN set it to 0 = first SET command
ELSE = |
IF the border attribute not exists = second matching expression
THEN add it = second SET command
Bounds = "<im(g|age)s*>"
Match = "1 border=$AV(*)3$SET(2=border="0")"
"|"
"1>$SET(2=border="0">)"
Replace = "1 23"
This time we had to use Bounds to define the limit where the filter have to be applied. Also, in the second clause, we have to leave out of the matching variables the closing > parens, otherwise the added attribute could never be inserted into the tag. This is the same as before: we need to match what follows to inject our code in front of it.
- Example 3
We have to write a simple filter to view the page comments.
IF the opening comment tag is encountered = first matching expression
THEN modify it to something other = first SET command
ELSE = |
IF the closing comment tag is encountered = second matching expression
THEN modify it to something other = second SET command
Match = "<!--$SET(1=<small><!--)"
"|"
"-->$SET(1=--></small>)"
Replace = "1"
This last filter differs from the first and the second because they check if something we are looking for is present or not in the html code, while the third filter check for different code. As we'll see in the next paragraph, this kind of filter can not be simplified while the first 2 can do.
SIMPLIFY THE MATCHING EXPRESSION WHEN POSSIBLE
Using the if-then-else structure helps a lot to write filters but after doing it you always have to try tweaking them to simplify, improve or make them more effective. So, the if-then-else structure can be considered a way to address the solution but the result it provides often requires some further modifies to come to a definitive version of the filters you wrote.
To better understand what this means, the filters used as examples in this tutorial will be tweaked to show how to achieve their final form.
- Example 1
Match = "</head>$SET(1=</head>)"
"|"
"<body$SET(1=</head><body)"
Replace = "1"
The first IF clause matches when </head> is present, but in this case we don't need to set the 1 variable because we can store directly </head> into 1. Also, in the second IF clause, we can store what matched in the 2 variable:
Match = "(</head>)1"
"|"
"(<body)2$SET(1=</head>)"
Replace = "12"
Because this filter applies just one time each page we can also use the STOP command to exclude it for the rest of the page, so its final version is:
Match = "(</head>)1$STOP()"
"|"
"(<body)2$SET(1=</head>)"
Replace = "12$STOP()"
- Example 2
Bounds = "<im(g|age)s*>"
Match = "1 border=$AV(*)3$SET(2=border="0")"
"|"
"1>$SET(2=border="0">)"
Replace = "1 23"
Both the IF clauses set the 2 variables to border="0" so we can directly replace it without set anything:
Bounds = "<im(g|age)s*>"
Match = "1 border=$AV(*)3>"
"|"
"1>"
Replace = "1 border="0"3>"
Because the IF clauses are very similar, we can also merge them using a check for something OR nothing:
Bounds = "<im(g|age)s*>"
Match = "1 (border=$AV(*)3|)>"
Replace = "1 border="0"3>"
- Example 3
Match = "<!--$SET(1=<small><!--)"
"|"
"-->$SET(1=--></small>)"
Replace = "1"
In this case we can't do anything to simplify or improve the filter so it is really the case where we need an if-then-else structure and this is true every time we have to match different code and replace it with different replacement expressions.
CONCLUSION
The use of an implied if-then-else structure can represent a useful trick to write filters. It should not be seen as a result but as a way to come to a solution: although the filters can be written without knowing anything about it, when this trick can be applied provides an easy way to solve problems in writing a filter.
NOTE
I believe in the Open Source Definition and in the Open Source Community. This tutorial is provided as public domain and copyleft. You can freely distribute and/or modify it but, please, don't remove this note.
------------------------ end here -------------------------
also, i've attached it to this message in a .txt zipped format that you can easily download:
http://uploaded/altosax/2002823191958_tutorial2.zip
<edit>: this is the more recent version, that you can find also in p-faq
regards to all,
altosax.
Edited by - altosax on 01 Sep 2002 19:02:21
i've written this new tutorial about the use of an implied if-then-else structure in filters. it was originated from the discussion i had on this forum with hpguru, sidki, jor, jd and tegghead. but, as always, also members who hadn't part in that discussion have contributed because all here have learned a lot from their posts, so thank you all.
here is the tutorial. i have written it in a couple of hours so i'm sure there are many other things that could be added: let me know your comments and suggestions.
-------------------- start here -----------------------------
***********************************************************
THE PROXOMITRON FILTERS TUTORIAL
How write filters using an implied if-then-else structure
by altosax
Created August 22, 2002 - Updated August 23, 2002
***********************************************************
INTRODUCTION
This tutorial explains how write filters able to perform an if-then-else check to be used with The Proxomitron, by Scott R. Lemmon. If you don't understand what i wrote in this tutorial, please read the Proxomitron help first.
UNDERSTAND THE PROBLEM
The Proxomitron matching language is a specific language created by Scott R. Lemmon with a subset of characters and symbols used for the regular expressions, to allow the user to write himself his own filters.
Although it is much powerful, and allows the user to write really complex filters, this means that The Proxomitron matching language is not a programming language and can not provide some logical structures you can find in the high level programming languages.
A useful structure that the user could need while he is writing a filter is the if-then-else check. This way he could test when a condition is true and do something otherwise do something other.
The main intent of this tutorial is to show the way this can be done using The Proxomitron language and its built-in commands.
SOME EXAMPLES REQUIRING AN IF-THEN-ELSE
The following examples comes from the real questions posted by some Proxomitron users at http://asp.flaaten.dk/pforum/ that have originated the discussion about the way to write an implied if-then-else structure in the filters.
- Example 1
Suppose you have to close the <head> tag when </head> is missing.
To solve this problem you can think this:
IF </head> exists
THEN do nothing
ELSE
IF </head> is missing
THEN add it
- Example 2
You want to set the image border to 0 both if the border attribute exists or not.
To solve this problem you can think this:
IF the border attribute exists
THEN set it to 0
ELSE
IF the border attribute not exists
THEN add it
- Example 3
You want to write a simple filter to view the page comments.
To solve this problem you can think this:
IF the opening comment tag is encountered
THEN modify it to something other
ELSE
IF the closing comment tag is encountered
THEN modify it to something other
HOW WRITE THE IF-THEN-ELSE
The most effective way to write this kind of structure in a filter is to use 2 different matching expressions separated by an OR function, each using a SET command.
This table shows the corrispondences:
IF = first matching expression
THEN = first SET command
ELSE = |
IF = second matching expression
THEN = second SET command
If you have to test more than an IF case, you can add to the basic structure the required number of else-if-then as follows:
ELSE = |
IF = new matching expression
THEN = new SET command
After doing this, you simply have to replace the variables set in the if clauses.
SOLVING THE PROPOSED EXAMPLES
Here you can view how easy is to solve the previous problems using an if-then-else structure.
- Example 1
We have to close the <head> tag when </head> is missing.
IF </head> exists = first matching expression
THEN do nothing = first SET command
ELSE = |
IF </head> is missing = second matching expression
THEN add it = second SET command
Match = "</head>$SET(1=</head>)"
"|"
"<body$SET(1=</head><body)"
Replace = "1"
We can learn from this example that:
a) "do nothing" is equal to "set the variable to what matched";
b) when the code we are searching for is missing we have to match what follows then inject it in front of what matched.
- Example 2
We have to set the image border to 0 both if the border attribute exists or not.
IF the border attribute exists = first matching expression
THEN set it to 0 = first SET command
ELSE = |
IF the border attribute not exists = second matching expression
THEN add it = second SET command
Bounds = "<im(g|age)s*>"
Match = "1 border=$AV(*)3$SET(2=border="0")"
"|"
"1>$SET(2=border="0">)"
Replace = "1 23"
This time we had to use Bounds to define the limit where the filter have to be applied. Also, in the second clause, we have to leave out of the matching variables the closing > parens, otherwise the added attribute could never be inserted into the tag. This is the same as before: we need to match what follows to inject our code in front of it.
- Example 3
We have to write a simple filter to view the page comments.
IF the opening comment tag is encountered = first matching expression
THEN modify it to something other = first SET command
ELSE = |
IF the closing comment tag is encountered = second matching expression
THEN modify it to something other = second SET command
Match = "<!--$SET(1=<small><!--)"
"|"
"-->$SET(1=--></small>)"
Replace = "1"
This last filter differs from the first and the second because they check if something we are looking for is present or not in the html code, while the third filter check for different code. As we'll see in the next paragraph, this kind of filter can not be simplified while the first 2 can do.
SIMPLIFY THE MATCHING EXPRESSION WHEN POSSIBLE
Using the if-then-else structure helps a lot to write filters but after doing it you always have to try tweaking them to simplify, improve or make them more effective. So, the if-then-else structure can be considered a way to address the solution but the result it provides often requires some further modifies to come to a definitive version of the filters you wrote.
To better understand what this means, the filters used as examples in this tutorial will be tweaked to show how to achieve their final form.
- Example 1
Match = "</head>$SET(1=</head>)"
"|"
"<body$SET(1=</head><body)"
Replace = "1"
The first IF clause matches when </head> is present, but in this case we don't need to set the 1 variable because we can store directly </head> into 1. Also, in the second IF clause, we can store what matched in the 2 variable:
Match = "(</head>)1"
"|"
"(<body)2$SET(1=</head>)"
Replace = "12"
Because this filter applies just one time each page we can also use the STOP command to exclude it for the rest of the page, so its final version is:
Match = "(</head>)1$STOP()"
"|"
"(<body)2$SET(1=</head>)"
Replace = "12$STOP()"
- Example 2
Bounds = "<im(g|age)s*>"
Match = "1 border=$AV(*)3$SET(2=border="0")"
"|"
"1>$SET(2=border="0">)"
Replace = "1 23"
Both the IF clauses set the 2 variables to border="0" so we can directly replace it without set anything:
Bounds = "<im(g|age)s*>"
Match = "1 border=$AV(*)3>"
"|"
"1>"
Replace = "1 border="0"3>"
Because the IF clauses are very similar, we can also merge them using a check for something OR nothing:
Bounds = "<im(g|age)s*>"
Match = "1 (border=$AV(*)3|)>"
Replace = "1 border="0"3>"
- Example 3
Match = "<!--$SET(1=<small><!--)"
"|"
"-->$SET(1=--></small>)"
Replace = "1"
In this case we can't do anything to simplify or improve the filter so it is really the case where we need an if-then-else structure and this is true every time we have to match different code and replace it with different replacement expressions.
CONCLUSION
The use of an implied if-then-else structure can represent a useful trick to write filters. It should not be seen as a result but as a way to come to a solution: although the filters can be written without knowing anything about it, when this trick can be applied provides an easy way to solve problems in writing a filter.
NOTE
I believe in the Open Source Definition and in the Open Source Community. This tutorial is provided as public domain and copyleft. You can freely distribute and/or modify it but, please, don't remove this note.
------------------------ end here -------------------------
also, i've attached it to this message in a .txt zipped format that you can easily download:
http://uploaded/altosax/2002823191958_tutorial2.zip
<edit>: this is the more recent version, that you can find also in p-faq
regards to all,
altosax.
Edited by - altosax on 01 Sep 2002 19:02:21