Extending the Pier Parser

Early versions of Pier included the syntax to embed Smalltalk code into a page. This was a nice feature for power users, but caused certain confusion among others. Moreover it also caused potential security issues, when the permissions weren’t setup properly. Never the less, as there were some people complaining about the missing feature, I am going to show how to extend Pier and its pluggable parser to support this functionality.

1. Creating a new Node Type

First let’s create a new node type, a subclass of PRText:

PRText subclass: #PRCode
instanceVariableNames: ''
classVariableNames: ''
poolDictionaries: ''
category: 'Pier-Executable'

2. Register with the Parser

Let’s specify an initializer method on the class side to register it with the parser. We choose a single pipe character as the new markup:

PRCode class>>markup
^ '|'
PRCode class>>initialize
PRDocumentParser textMatcher at: self markup put: self

Next we need to implement the hook method #parse: aString markup: aMarkupString with: aParser to parse the string. In our case this is simple as we just want to return a new instance of PRCode with the contents:

PRDocumentParser class>>parse: aString markup: aMarkupString with: aParser
^ self new text: aString

3. Plugging into the Visitors

Next we have to make sure that the new node type plays well with the visitor framework:

PRCode>>accept: aVisitor
aVisitor visitCode: self
PRVisitor>>visitCode: anObject
self visitText: anObject

Now we add the different #visitCode: implementations in specific visitors. First this is the visitor to serialize a parsed node back to Wiki syntax:

PRWikiWriter>>visitCode: anObject
self nextPutAll: anObject class markup.
self nextPutAll: anObject text.
self nextPutAll: anObject class markup

And second, this is the XHTML visitor that should evaluate the code and display it on the resulting output stream:

PRViewRenderer>>visitCode: anObject
html render: (Compiler
evaluate: anObject text
for: self component
logged: false)

That’s all for a very basic implementation. Now we can write in any document |TimeStamp current| to embed the current time. Since self refers to the current component, we can embed the current page title into the document by writing: |self context structure title|. Or, you can write Seaside rendering code to create a link that calls the counter example: | [ :html | html anchor callback: [ self call: WACounter new ]; with: 'Start Counter' ] |. The possibilites are endless.

To use the presented code in a productive environment, some error handling has to be added. Propre sandboxing would also be a requirement.

Posted by Lukas Renggli at 12 April 2007, 8:41 am with tags pier, parser, tutorial link

Comments

Very cool work Lukas. And it so simple to extend it :-)

However, it doesn’t seem possible to use a non-markup syntax. How about:

This is a title
---------------

Is it possible to have this kind of syntax?

Posted by Damien Cassou at 12 April 2007, 2:22 pm link

Indeed, the syntax you suggest is not easy to implement with the current framework, however it is possible to write an entirely new parser that can coexist with the existing one.

The syntax Pier is using origins in SWiki and SmallWiki. It follows two simple patterns:

  • Line prefixes. Characters at the beginning of a line are used to specify the type of the line: header !, ordered list #, unordered list -, table |, etc.
  • Markup pairs. Pairs of special markup strings are used within the text to create links (* and +) and formattings ('', "", ^^, etc).
Posted by Lukas Renggli at 12 April 2007, 2:34 pm link

Need to write cool plugin ...

Posted by Philippe Marschall at 13 April 2007, 1:32 am link

See ShoutPier at: http://mc.lukas-renggli.ch/pieraddons/

Posted by Philippe Marschall at 13 April 2007, 4:37 pm link

I feel so free to post a screenshot of this excellent plugin. I already see many possible uses, among them all the code examples on the upcoming web site of Seaside.

shoutpier.gif

Posted by Lukas Renggli at 13 April 2007, 8:34 pm link

It would certainly be suited for code posts in a certain blog as well ;)

One issue that remains is finding out if the code to parse is a DoIt or a method

Posted by Philippe Marschall at 17 April 2007, 12:19 pm link