Thursday, March 25, 2010

Decimating the WikiBase

The Wiki was invented by a talented programmer who wanted to let his friends store patterns of software design modeled after Christopher Alexander's work in A Pattern Language.

The original Perl code is known as WikiBase, and after removing the HyperPerl structure, inspired by Donald Knuth's Literate Programming ideas, the code runs to about:

300 lines

Below is a functionally equivalent Grogix program, which I wrote in about an hour, and which could be better, but runs to about:

30 lines

The difference is Grogix, not me. Operational Grammars compact the multiplicative effects in a system, and clarify system structures and their appropriate order of emergence. Real-world context is pushed into the interface, and all that remains is the unfolding structure.

When looking at this example, please remember that an Operational Grammar represents a full executing system, not just the syntax of a language.

In this example, I've made some changes from previous posts.

1) The ellipses are gone, because people inferred that something was missing, which was not the case.

2) I've marked the three parts of a Conditional Production with '@' and '::' :

nonterminal@condition :: template

3) I've removed the keyword for the 'default' condition. So a default condition looks like:

nonterminal@ :: text

And of course the default condition goes at the end of any run of productions for the same nonterminal. They are evaluated in order.

4) I also changed the right-hand side's {{nonterminal::parameter1,parameter2}} notation to {{ nonterminal( parameter1,parameter2 ) }}. These compose, so: {{ nonterminal1( parameter1, nonterminal2( parameter1, parameter2 ) ) }} ... note the productions access parameters with $1, $2 etc ... these will be name-able in the future.

5) As before, every nonterminal is a potential persistent data type, where its access by .value triggers the persistence mechanism in the interface.

The interface is somewhat different than in the previous example, allowing usages like the patterns-parsing of "wiki_strings" -- that's the strength of the interface-separation approach. New kinds of interface functionality can be added, but it's still a grammar, representing the structure of execution of a system.


WikiBase.gx

. start@ :: {{ wiki }}

. wiki@url_name(page) :: {{wiki_page}}
. wiki@url_name(edit) :: {{wiki_edit_page}}
. wiki@ :: {{wiki_page}}

. wiki_page@url_name(page) :: {{ html_page( *page, wiki_content(*page) ) }}
. wiki_page@ :: {{ html_page( "WikiHome", wiki_content("WikiHome") ) }}

. wiki_edit_page@ :: {{ html_page( *edit, wiki_edit ( *edit ) ) }}

. wiki_content@ :: {{ wiki_top ($1) }} {{ wiki_text ($1) }} {{ edit_link ($1)}} {{ wiki_footer }}

. wiki_edit@ :: {{ wiki_top ($1) }} {{ wiki_form ( wiki_text ) }} {{ wiki_footer }}

. wiki_text@url_name(edit) :: {{ wiki_text.value }}
. wiki_text@ :: {{ wiki_strings (wiki_text.value) }}

. edit_link@ :: {{a_link ("/edit="+$1,"Edit "+$1)}}

. wiki_strings@pattern("\<[^<>]*\>") ::
. wiki_strings@pattern("([A-Z][a-z]+)+") :: {{ a_link("/page="+*1,*1) }}
. wiki_strings@pattern("---+") :: {{ hr }}
. wiki_strings@pattern("\*") ::    •

. wiki_top@ :: <div style="font-weight:bold;">{{ a_link( "/page="+$1, $1 ) }}</div>
. wiki_footer@ :: copyright © {{*year}}

. wiki_form@ :: <form action="/page={{*page}}" method="post">{{form_textarea(*page)}}{{form_button}}</form>

. form_textarea@ :: <textarea name="{{*page}}">{{wiki_text}}</textarea>
. form_button@ :: <input type="submit" name="button" value="save">

. a_link@ :: <a href="{{$1}}">{{$2}}</a>

. hr@ :: <hr \>
. br@ :: <br \>

. html_page@ :: {{ html_header( $1 ) }} {{ html_body( $2 ) }}
. html_header@ :: {{doctype}} <head><title>{{ $1 }}</title>{{html_meta}}</head>
. html_body@ :: <body>{{ $1 }}</body>
. html_meta@ :: <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
. doctype@ :: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">


There are tools I'll build that should make this kind of programming even easier. I imagine an Eclipse plug-in that has two easily-switchable navigation modes: (1) scrolls around the whole grammar and (2) shows only the parent and child productions of whatever production your cursor is on. I'm guessing that this mode, with state discrimination added, could help expand the overlaid trees of conditional grammars, assisting our comprehension of even more complex systems, and producing a kind of "programming by borrowing" of grammar sub-trees ... anyway, much of the problem of navigating complex systems is mitigated by the one-grammar-per-system idea. It's a great model for portability, with a built-in idea for well-defined separation and integration between engine and interface. Additional systems (especially the interfaces) will have their own grammars too ... each layer in a real-world "interface stack" can be a system with its own operational grammar.

No comments:

Post a Comment