New Improved Clarion Challenge!

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.

Figure 1. The test application.

parser_fig1.gif (4878 bytes)

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.

Listing 1. The Test method.
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).

Listing 2. The derived methods.
!------------------------------------------------------------!
! 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.

Printer-friendly version

Reader Comments

To add a comment to this article you must log in.

 
 

Search

 

Advanced Search
Topical Index

Related Articles

Subscribe to
ClarionMag

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

More Info

Subscribe Now!

ClarionMag Blog

RSS Feeds

Updates via Email

Enter your Email


Powered by FeedBlitz

Quick Links