![]() |
|
Published 1999-06-21 Printer-friendly version
Last month's Clarion Challenge was a bit more complex than the previous challenge, so there were correspondingly fewer entries. It was also a much more difficult to evaluate since the specification was somewhat open-ended.
In fact, it became clear that it would not be possible to fairly compare the various entries given how differently they had been implemented. Accordingly, I've written the challenge and have asked the entrants to adapt their code to a very specific code framework. This will also make it a lot easier for anyone who's still interested to submit some code, since it's much more a case now of plugging and playing your code within a defined test environment. This same approach will be used for all future challenges, although I expect they'll be considerably smaller in scope.
This revised challenge includes a test application adapted from that used for the previous Clarion Challenge, and shown in Figure 1.

The test application isn't an APP file - instead it's made up of one source file (parser.clw) and one project file (parser.prj). To run the application use Project|Set and choose a File Type of Project File (*.prj). Select parser.prj. You can then compile and run as you would an APP (but you don't have to wait for code to generate).
The parser application uses two classes to implement the code. There is a base class called ParserBaseClass. This class is NOT to be modified. All changes are to be made to a derived class called MyParser. I've split the challenge into two classes for exactly the same reason that your ABC applications consist of base classes and derived classes. The base class contains code and data that must be the same for all implementations, and the derived class contains entrant-specific code.
The Test method shown in Listing 1 is declared in the base class.
ParserBaseClass.Test procedure
!------------------------------------------------------------!
! DO NOT MODIFY THIS METHOD!!! And do NOT derive it.
!------------------------------------------------------------!
TempString string(200)
x long
code
self.Reset()
self.AddDelimiter(' ')
self.SetString('This is the test string, which should '|
& 'have its words alternating between '|
& 'upper case and lower case. The actual test will '|
& 'parse Clarion code and capitalize keywords.')
self.BeforeTest()
loop x = 1 to self.GetTokenCount()
TempString = self.GetToken(x)
if x % 2
TempString = upper(TempString)
else
TempString = lower(TempString)
end
self.PutToken(x,TempString)
end
return
The Test method is the only method you may not derive. All the rest are fair game, although in the example I've only derived those methods I think you're likely to want to use. Whatever you do with the derived class keep in mind that you cannot change how the test is executed.
All of the derived methods (in MyParser class) are virtual methods, which essentially means they function like embeds and will be called automatically by the Test method, even though that method is declared in the base class. These methods are shown in Listing 2 (they're in the source file - you don't need to copy from the listing).
!------------------------------------------------------------!
! You may not modify anything above this point except for
! the MyParser class declaration at the top of the file.
!------------------------------------------------------------!
MyParser.AddDelimiter procedure(string Delim)
!------------------------------------------------------------!
! You don't need to modify this method but you may wish to
! if you have a better idea for how to store delimiters.
! By default this method adds records to the DelimQ. To get
! the delimiters that have been added you can query the queue
! as you would any other queue.
!------------------------------------------------------------!
code
self.DelimQ.Delim = Delim
add(self.DelimQ)
MyParser.BeforeTest procedure
!------------------------------------------------------------!
! Write code here to prepare for the test, if necessary.
! This method is called automatically by the test procedure
! before the test is run. You will most likely want to use
! this method if you parse your string before calling any of
! the string manipulation methods. If you do everything
! on the fly then you probably won't need this method
!------------------------------------------------------------!
code
MyParser.GetTokenCount procedure
!------------------------------------------------------------!
! Write code here to count the number of tokens. By default
! you have a queue (self.DelimQ) of delimiters which you
! can use to examine the text string (self.Text).
!------------------------------------------------------------!
code
return(0) ! Replace this code!
MyParser.GetToken procedure(long Index)
!------------------------------------------------------------!
! Write code here to get a specific token. In the example
! text a token is an individual words, but if the string
! were some Clarion code and the period is a delimiter then
! if the string were "MyParser.GetToken" GetToken(1) would
! return "MyParser" and GetToken(2) would return "GetToken"
!------------------------------------------------------------!
code
return('') ! Replace this code!
MyParser.PutToken procedure(long Index,string Text)
!------------------------------------------------------------!
! Write code here to set a specified token in the string to
! a new value. For instance, if the string is
! "MyParser.GetToken" and the period is a delimiter then
! calling PutToken(1,'SomeOtherParser') would change the
! string to "SomeOtherParser.GetToken".
!------------------------------------------------------------!
code
return(False) ! Replace this code!
All of these methods are implemented at the end of parser.clw. If you want to derive another method just follow the example of how these methods are declared in the class declaration at the top of parser.clw, and implemented at the end of parser.clw. Most likely you'll be able to complete the challenge just by writing code for the methods in Listing 2. You may also want to add some variables to MyParser so that you can share them between methods. See the declaration for ParserBaseClass for an example, and email us if you have questions.
Also please note that although this way of declaring and implementing a class in a single source file clearly works, it isn't recommended for most work. You're generally better off keeping base class declarations in INC files and code in CLW files as ABC does.
Click here to download the parser shell application and project file.
NOTE: This challenge is now closed.
Click here to see the results.
Copyright © 1999-2008 by CoveComm Inc. All Rights Reserved. Reproduction in any form without the express written consent of CoveComm Inc., except as described in the subscription agreement, is prohibited.
Clarion Magazine ISSN 1718-9942
One year: $159
(reg $189, save $30)
(includes all back issues since '99)
Renewals from $109
Two years: $249
(reg $289, save $40)
Renewals from $199