[squeak-dev] Clashing semantics for #asCollection between Stream parser(S) and MaClientServer

Levente Uzonyi leves at caesar.elte.hu
Tue Aug 13 00:47:24 UTC 2019


Hi Tim,

On Mon, 12 Aug 2019, tim Rowledge wrote:

> I just loaded the Xtreams and Levente's GoogleWikiCompiler into an image that already had Chris' MaClientServer package. 
>
> Running the GoogleWikiCompiler example failed! Oh noes!
>
> Turns out that in GoogleWikiCompiler>LinkShort: the use of 
> address, '.html'
> to merger a collection of characters with the string '.html' relies on the implementation semantics of #asCollection to leave a String as a String - after all, it's a collection of characters, right?
>
> However, Chris has changed that for MaClientServer such the String is returned as 
> Array with: theString
> which doesn't play nice with the above.
>
> I'm not entirely sure I like either approach really; #($a $b $c) , 'foo' doesn't seem like such a great thing to do, especially if you can't guarantee what the actual state of the 'address' object is (that's a bigger issue around the parser behaviour) BUT 'foo' asCollection -> #( 'foo') doesn't seem quite nice either. I could sort of appreciate 'foo' asCollection -> #($f $o $o) I suppose.
>
> The immediate solution within the context of the swiki parsing is to carefully make sure the address is actually a string, so no major issue for me today, but this does indicate a potentially problematic perplexity when mixing xtreams and client server packages.

If MaClientServer implements String >> #asCollection, then that's a 
mistake, which breaks #,.

I came to the conclusion that without a proper html generator, 
GoogleWikiCompiler cannot create correct output.
I have attached a version of GoogleWikiCompiler (attached), which uses our 
internal tool: StreamingHtmlCanvas (also attached) to generate html.
Yes, that's another dependency, but that's how things go, isn't it? :)

Also, I had to convert the address variable to a string in links actions. 
I think you've done the same in your image.

Levente

>
> tim
> --
> tim Rowledge; tim at rowledge.org; http://www.rowledge.org/tim
> Fractured Idiom:- VISA LA FRANCE - Don't leave chateau without it
-------------- next part --------------
A non-text attachment was scrubbed...
Name: StreamingHtmlCanvas-klub.33.mcz
Type: application/zip
Size: 14368 bytes
Desc: 
URL: <http://lists.squeakfoundation.org/pipermail/squeak-dev/attachments/20190813/3e25b305/attachment.zip>
-------------- next part --------------
PEGActor subclass: #GoogleWikiCompiler
	instanceVariableNames: ''
	classVariableNames: ''
	poolDictionaries: ''
	category: 'GoogleWikiCompiler'!
!GoogleWikiCompiler commentStamp: '<historical>' prior: 0!
This actor is used to convert text with wiki mark-up into an XML document with xhtml tags.

Shared Variables
	Anchor	<NodeTag>
	Break	<NodeTag>
	Division	<NodeTag>
	Heading1	<NodeTag>
	Heading2	<NodeTag>
	Heading3	<NodeTag>
	Heading4	<NodeTag>
	Href	<NodeTag>
	ListItem	<NodeTag>
	OrderedList	<NodeTag>
	Paragraph	<NodeTag>
	Preformatted	<NodeTag>
	Span	<NodeTag>
	Style	<NodeTag>
	Table	<NodeTag>
	TableBody	<NodeTag>
	TableData	<NodeTag>
	TableHead	<NodeTag>
	TableHeading	<NodeTag>
	TableRow	<NodeTag>
	UnorderedList	<NodeTag>

!


!GoogleWikiCompiler methodsFor: 'Lexical' stamp: 'ul 8/10/2019 22:17'!
Bold: flow

	<action: 'Bold' arguments: #(2)>
	^GoogleWikiDomNode strong: flow! !

!GoogleWikiCompiler methodsFor: 'Lexical' stamp: 'ul 8/10/2019 14:58'!
Escape: escape

	<action: 'Escape'>
	^escape first! !

!GoogleWikiCompiler methodsFor: 'Lexical' stamp: 'ul 8/10/2019 22:31'!
Italic: flow

	<action: 'Italic' arguments: #(2)>
	^GoogleWikiDomNode em: flow! !

!GoogleWikiCompiler methodsFor: 'Lexical' stamp: 'ul 8/11/2019 21:51'!
LinkFull: flow address: address

	<action: 'LinkFull' arguments: #(2 3)>
	^GoogleWikiDomNode a
		attributes: { 'href' -> (address as: String) };
		children: flow;
		yourself! !

!GoogleWikiCompiler methodsFor: 'Lexical' stamp: 'ul 8/11/2019 21:50'!
LinkShort: address

	<action: 'LinkShort' arguments: #(2)>
	^GoogleWikiDomNode a
		attributes: { 'href' -> ((address as: String), '.html') };
		children: address;
		yourself! !

!GoogleWikiCompiler methodsFor: 'Lexical' stamp: 'ul 8/10/2019 22:37'!
Underline: flow

	<action: 'Underline' arguments: #(2)>
	^GoogleWikiDomNode span
		attributes: { 'style' -> 'text-decoration: underline' };
		children: flow;
		yourself! !


!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:17'!
Code: text

	<action: 'Code' arguments: #(2)>
	^GoogleWikiDomNode code: text! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 15:01'!
Empty

	<action: 'Empty' arguments: #()>
	^nil! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:30'!
Heading1: flow

	<action: 'Heading1' arguments: #(3)>
	^GoogleWikiDomNode h1: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:31'!
Heading2: flow

	<action: 'Heading2' arguments: #(3)>
	^GoogleWikiDomNode h2: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:31'!
Heading3: flow

	<action: 'Heading3' arguments: #(3)>
	^GoogleWikiDomNode h3: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:31'!
Heading4: flow

	<action: 'Heading4' arguments: #(3)>
	^GoogleWikiDomNode h4: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:33'!
ListItem: bullets flow: flow

	<action: 'Bullet1' arguments: #(2 3)>
	<action: 'Bullet2' arguments: #(2 3)>
	<action: 'Bullet3' arguments: #(2 3)>
	<action: 'Hash1' arguments: #(2 3)>
	<action: 'Hash2' arguments: #(2 3)>
	<action: 'Hash3' arguments: #(2 3)>

	^GoogleWikiDomNode li: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:33'!
OrderedList: bullets

	<action: 'OrderedList'>
	^GoogleWikiDomNode ol: bullets! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:34'!
OrderedListN: bullets

	<action: 'OrderedList2'>
	<action: 'OrderedList3'>

	^GoogleWikiDomNode li: (GoogleWikiDomNode ol: bullets)! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:34'!
Page: lines

	<action: 'Page'>
	^GoogleWikiDomNode div: lines! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:34'!
Paragraph: flow

	<action: 'Paragraph'>
	^GoogleWikiDomNode p: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:35'!
Preformatted: text

	<action: 'Code' arguments: #(2)>
	^GoogleWikiDomNode pre: text! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:36'!
Table: header rows: rows

	<action: 'Table' arguments: #(1 2)>
	^GoogleWikiDomNode table: {
		GoogleWikiDomNode thead: header.
		GoogleWikiDomNode tbody: rows }! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:36'!
TableCell: flow

	<action: 'Cell'>
	^GoogleWikiDomNode td: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:36'!
TableHeadingCell: flow

	<action: 'HeadingCell'>
	^GoogleWikiDomNode th: flow! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:36'!
TableRow: cells

	<action: 'TableRow' arguments: #(3)>
	<action: 'HeadingRow' arguments: #(3)>
	^GoogleWikiDomNode tr: cells! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:37'!
UnorderedList: bullets

	<action: 'UnorderedList'>
	^GoogleWikiDomNode ul: bullets! !

!GoogleWikiCompiler methodsFor: 'Structural' stamp: 'ul 8/10/2019 22:37'!
UnorderedListN: bullets

	<action: 'UnorderedList2'>
	<action: 'UnorderedList3'>
	^GoogleWikiDomNode li: (GoogleWikiDomNode ul: bullets)! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

GoogleWikiCompiler class
	instanceVariableNames: ''!

!GoogleWikiCompiler class methodsFor: 'utilities' stamp: 'ul 8/10/2019 23:40'!
process: input
	"Convert input into an xhtml XML document.
	"
	"	input	<ReadStream>	text with wiki markup
		^		<GoogleWikiDomNode>
	"
	"
		self process: 'Single paragraph with *bold* and _italic_ text and a [link]' reading
	"

	^self parser
		parse: 'Page'
		stream: input
		actor: self new! !


!GoogleWikiCompiler class methodsFor: 'examples' stamp: 'ul 8/10/2019 23:36'!
example
	" self example "

	| input output |
	input := 'Single paragraph with *bold* and _italic_ text and a [link]' reading.
	output := self process: input.
	^output! !


!GoogleWikiCompiler class methodsFor: 'accessing' stamp: 'ul 8/10/2019 23:45'!
parser

	^PEGParser parserPEG
		parse: 'Grammar'
		stream: PEGParser grammarWiki reading
		actor: PEGParserParser new! !


Object subclass: #GoogleWikiDomNode
	instanceVariableNames: 'tag attributes children'
	classVariableNames: ''
	poolDictionaries: ''
	category: 'GoogleWikiCompiler'!

!GoogleWikiDomNode methodsFor: 'converting' stamp: 'ul 8/11/2019 19:40'!
asString

	^StreamingHtmlCanvas render: [ :html | self renderOn: html ]! !


!GoogleWikiDomNode methodsFor: 'rendering' stamp: 'ul 8/11/2019 19:41'!
renderChildNodes: childNodes of: element on: html

	childNodes ifNil: [ ^self ].
	childNodes class == self class ifTrue: [ ^element with: childNodes ].
	childNodes isString ifTrue: [ ^element with: childNodes ].
	childNodes isCharacter ifTrue: [ ^element with: childNodes ].
	childNodes isCollection ifTrue: [
		^childNodes do: [ :each | self renderChildNodes: each of: element on: html ] ].
	self error: 'Unexpected child nodes'! !

!GoogleWikiDomNode methodsFor: 'rendering' stamp: 'ul 8/11/2019 21:50'!
renderChildNodes: childNodes on: html

	childNodes ifNil: [ ^self ].
	childNodes class == self class ifTrue: [ ^childNodes renderOn: html ].
	childNodes isString ifTrue: [ ^html text: childNodes ].
	childNodes isCharacter ifTrue: [ ^html text: childNodes ].
	childNodes isCollection ifTrue: [
		^childNodes do: [ :each | 
			self renderChildNodes: each on: html ] ].
	self error: 'Unexpected child nodes'! !

!GoogleWikiDomNode methodsFor: 'rendering' stamp: 'ul 8/11/2019 21:49'!
renderOn: html

	| element |
	element := html perform: tag.
	attributes ifNotNil: [
		attributes do: [ :association |
			element
				addAttribute: association key
				value: association value ] ].
	element with: [ self renderChildNodes: children on: html ]! !


!GoogleWikiDomNode methodsFor: 'accessing' stamp: 'ul 8/10/2019 22:15'!
attributes: aCollectionOfAssociations

	attributes := aCollectionOfAssociations! !

!GoogleWikiDomNode methodsFor: 'accessing' stamp: 'ul 8/10/2019 23:38'!
children: anObject

	children := anObject! !

!GoogleWikiDomNode methodsFor: 'accessing' stamp: 'ul 8/10/2019 22:15'!
tag: aSymbol

	tag := aSymbol! !

"-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- "!

GoogleWikiDomNode class
	instanceVariableNames: ''!

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:15'!
a

	^self new
		tag: #a;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:17'!
code: children

	^self new
		tag: #code;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:34'!
div: children

	^self new
		tag: #div;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:31'!
em: children

	^self new
		tag: #em;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:30'!
h1: children

	^self new
		tag: #h1;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:31'!
h2: children

	^self new
		tag: #h2;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:31'!
h3: children

	^self new
		tag: #h3;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:31'!
h4: children

	^self new
		tag: #h4;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:32'!
li: children

	^self new
		tag: #li;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:33'!
ol: children

	^self new
		tag: #ol;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:34'!
p: children

	^self new
		tag: #p;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:35'!
pre: children

	^self new
		tag: #pre;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:37'!
span

	^self new
		tag: #span;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:17'!
strong: children

	^self new
		tag: #strong;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:35'!
table: children

	^self new
		tag: #table;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:35'!
tbody: children

	^self new
		tag: #tbody;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:35'!
td: children

	^self new
		tag: #td;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:35'!
th: children

	^self new
		tag: #th;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:35'!
thead: children

	^self new
		tag: #thead;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:35'!
tr: children

	^self new
		tag: #tr;
		children: children;
		yourself! !

!GoogleWikiDomNode class methodsFor: 'instance creation' stamp: 'ul 8/10/2019 22:33'!
ul: children

	^self new
		tag: #ul;
		children: children;
		yourself! !


More information about the Squeak-dev mailing list