In continuation of earlier discussions on ColdFusion-like template parser...

Over the holidays (Marry Christmas to you all by the way!), I was conversing with some monks (via email as well as at the monastery) who mentioned that I should hammer down concrete specs of my design for the final ColdFusion-like template parser. Pertaining to these suggestions (and eager to seek further help and facilitate greater dialogue), I thought to write this little 'design' document and post it on perlmonks for review/suggestions etc. Some concerns that I have with the current design is that if implemented as is, my parser module will require more resources depending on how deeply nested the source template is (speaking of tag nesting). I'm wondering if any monk would have useful suggestions in that regard?
--------------------------------------------------------- ColdFusion::Parser Main class that deals with opening template files, managing cache, and creating initial instance of the ColdFusion::ParseTree object to transform raw template text into a parse tree that could later be processed. Here's a quick outline of what this class does: 1. Read from a template file (or buffer etc.) 2. Initialize ColdFusion::ParseRules. 3. Initialize ColdFusion::ParseTree by passing it the ParseRules object along with template text (references). 4. Processes resultant parse tree (aka 'tag stack'). ColdFusion::ParseRules used by : ColdFusion::ParseTree created by: ColdFusion::Parser This class describes how a chunk of template text should be parsed. Various tags may have their own variations of this class specific to their needs. However, this is only a remote possibility. For the most part, there's going to be a signle instance of this class created inside ColdFusion::Parser and passed along (as a reference) to all 'child' objects. By deriving custom classes from this base class, one should be able to create his own variation of a template parser to handle various other templating formats (such as ASP etc.) Also, this class describes various tag<->object mappings. For example, a 'cfoutput' tag may be associated to 'ColdFusion::TAG::Output'. This mapping is looked up inside ColdFusion::ParseTree to determine which 'tag' object should be created to handle specific Coldfusion tag. ColdFusion::ParseTree used by : ColdFusion::Parser, ColdFusion::TAGS::* created by : ColdFusion::Parser, ColdFusion::TAGS::* uses : ColdFusion::ParseRules Munches on a chunk of a ColdFusion-like template producing a tag parse tree in the end. Here's it's parse logic in point form: 1. Search for first recognized tag (consulting ColdFusion::ParseRules object). 2. If found, create a new tag object tasked to handle this tag (based on tag<->object mapping supplied by the ColdFusion::ParseRules object). 3. Complete initializing the newly created tag object by searching for it's end tag (in the template text) and setting tag's body to whatever's found enclosed within the pair opening/closing tags. 4. Repeat until entire template is parsed. Note: the first instance of a ParseTree class (initialized inside Parser class) will thus create 1-st level of the parse tree. The task of completing entire tree rests on nested tags each of which will use ParseTree objects to transform their bodies into tag trees. Here's an example of how 1-st level parse tree might look like: Source template: --------------------- <HTML> <HEAD> </HEAD> <BODY> Hello World! Welcome, <cfoutput>#foo_name#</cfoutput>! <cfif bool eq 1> <cfif foo = bar> <cfif bar = foo> </cfif> </cfif> BOOL is true! <cfelse> BOOL is false! </cfif> </BODY> </HTML> --------------------- 1-st level parse tree: --------------------- 'parse_tree' => [ '<HTML>', '<HEAD>', '</HEAD>', '<BODY>Hello World! Welcome, ', bless({ 'property' => { 'single' => '0', 'nested' => '0', 'attributes' => [ 'query' ] }, 'body' => '<cfoutput>#foo_name#</cfoutput>!', 'attributes' => {} }, 'Template::Parser::TAG::Output' ), bless({ 'property' => { 'single' => '0', 'nested' => 1, 'attributes' => [] }, 'body' => '<cfif bool eq 1> <cfif foo = bar> <cfif bar = foo> </cfif> </cfif> BOOL is true! <cfelse> BOOL is false! </cfif>' }, 'Template::Parser::TAG::Control::If' ), '</BODY>', '</HTML>' ], ------------------------- * produced by 'rough' version of ColdFusion template par +ser. By observing this sample parse tree, you should notice t +wo tag objects 'handling' first (top level) occurance of <cfoutput> and <cfif> tags respectively. ---------------------------------------------------------

Any comments/suggestions? ;-)

PS: I'm hoping to make draft copies of my code available on my private ftp for you to look at and hack soon ;).

"There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith

Replies are listed 'Best First'.
Alternative parsing algorithm.
by vladb (Vicar) on Dec 26, 2001 at 06:20 UTC
    This document describes alternative parsing strategy and compares it to the earlier thought approach. For reference, here's original 'algorithm':
      Alright! I've implemented alternative parsing algorithm and it works sweat. So far I haven't had any bugs with it (not that I'm aware of ;-). I'm nearly done implementing two tags now: 'cfoutput' and 'cfif'. The parser recognizes them correctly and seems to be building a parse tree that is ready for 'execution' provided the actual tag handler classes are coded completely.

      Certainly, realizing there's little fun without actually seeing bits and pieces of the code, I'm going to provided here (or my ftp) as soon as I'm finished polishing it. I might also provide little snippets of a larger code in form of a separate runnable perl script, but I've got to find the time ;).

      To sum up, nesting problem seems to have been dealt with! ;D

      "There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith
      For anyone who might wonder where to look at the code, I've made a draft copy available on my home node scratch pad.

      Please, take a look and send in any relavent comments ;-)

      thanks.

      "There is no system but GNU, and Linux is one of its kernels." -- Confession of Faith
Don't do it
by chromosundrift (Novice) on Jun 06, 2002 at 15:28 UTC

    It's going to be very difficult. Cold Fusion Markup Language is insufficiently documented and so poorly designed that you will likely go mad trying to do this. Please contact me for more information, because I have a collection of cold fusion stupidities. Remember that
    <cfthisSortOf <cfthing> is=encouraged>

    And if you can find someone who can tell you exactly where you are supposed to put # symbols and where not (without trying it out first) then you're a better man than I. No matter how many user groups and mailing lists I went to, there was simply no clue to be found.

    Cold Fusion was written by non-programmers for non-programmers.

    Of course if you do manage to do it, I'd be very interested. I'm especially interested in how you can rig up Cold Fusion for doing automated testing for your parser. It would be best not to do it across http, but I don't think there is another way.