Object subclass: #PParser instanceVariableNames: 'curEnv lists tags' classVariableNames: '' poolDictionaries: '' category: nil ! !PParser methodsFor: 'general'! init curEnv := nil. lists := OrderedCollection new. tags := OrderedCollection new. " create some of the elements of syntax " tags add: (ParserTagState new init: 'code' enterSyn: '[=' leaveSyn: '=]'); add: (ParserTagState new init: 'i' enterSyn: '///' leaveSyn: '///'); add: (ParserTagState new init: 'b' enterSyn: '(**' leaveSyn: '**)'); add: (ParserTagState new init: 'strike' enterSyn: '-s-' leaveSyn: '-s-'); add: (ParserWPLink new init); add: (ParserPlain new init: '—' syn: '---'); add: (ParserPlain new init: '→' syn: '-->'); add: (ParserPlain new init: '←' syn: '<--'); add: (ParserPlain new init: '↔' syn: '<->'). ! listFromMarker: marker marker = $* ifTrue: [^ #UL]. marker = $# ifTrue: [^ #OL]. ^nil. ! unwindUntil: pos " Pop the invalidated elements off the list stack. " (lists size) to: pos by: -1 do: [: idx| Transcript show: ''. ]. ! environFromMarker: marker marker = $ ifTrue: [^ 'pre']. marker = $^ ifTrue: [^ 'blockquote']. ^nil. ! parseLine: line | first inLists charPosition envTag | charPosition := 0. line size > 0 ifTrue: [ first := line at: 1. ] ifFalse: [first := nil]. envTag := self environFromMarker: first. envTag = nil ifTrue: [ curEnv = nil ifFalse: [Transcript show:''. curEnv := nil.]. ] ifFalse: [ curEnv = nil ifTrue: [ Transcript show:'<', envTag ,'>'. ] ifFalse: [ curEnv = envTag ifFalse: [ Transcript show: '<', envTag, '>'. ]]. curEnv := envTag. curEnv = 'pre' ifTrue: [ "preformatted text is taken literally" Transcript showCr: (line allButFirst). ^nil ] ifFalse: [ charPosition := charPosition + 1 ]. ]. inLists := true. [inLists & (charPosition+1 <= line size)] whileTrue: [ | char | charPosition := charPosition + 1. char := line at: charPosition. inLists ifTrue: [ | listType | listType := self listFromMarker: char. inLists := (listType = nil) not. (lists size < charPosition or: [((lists at: charPosition) = listType) not ]) ifTrue: [ "The rest of the symbols (if any) are no longer relevant" self unwindUntil: charPosition. ] . (listType = nil) not & (lists size < charPosition) ifTrue: [ lists add: listType. Transcript show: '<', (self tagFromList: listType), '>'. ]. "ending the stack of list symbols?" inLists not & (lists size > 0) ifTrue: [Transcript show: '
  • '.]. ]. ]. " stop here if there's nothing on the line " first = nil ifTrue: [Transcript cr. ^nil]. [charPosition <= line size] whileTrue: [ | match tagidx | match := false. tagidx := 1. [match not & (tagidx <= tags size)] whileTrue: [ | dist | dist := (tags at: tagidx) try: line at: charPosition. dist > 0 ifTrue: [ match := true. charPosition := charPosition + dist. ]. tagidx := tagidx + 1. ]. match ifFalse: [ Transcript show: (self sub: (line at: charPosition)). charPosition := charPosition + 1. ]. ]. lists size > 0 ifTrue: [ Transcript show: '
  • '. ]. " newlines seem to be messing with Blogger " "Transcript cr." ! sub: char "Blogger doesn't like it when I do this. char = $< ifTrue:[^'<']. char = $> ifTrue:[^'>']." ^char asString. ! tagFromList: list list = #UL ifTrue: [^ 'ul']. list = #OL ifTrue: [^ 'ol']. !! Object subclass: #ParserTagState instanceVariableNames: 'state enter leave tag' classVariableNames: '' poolDictionaries: '' category: nil ! ! ParserTagState methodsFor: 'general' ! init: stateTag enterSyn: enterSyn leaveSyn: leaveSyn state := false. tag := stateTag. enter := enterSyn. leave := leaveSyn. ! try: line at: pos state ifTrue: [ ^self tryLeave: line at: pos ] ifFalse: [ ^self tryEnter: line at: pos ]. ! tryEnter: line at: pos (line subMatch: enter startingAt: pos) ifTrue: [ state := true. Transcript show: '<', tag, '>'. ^(enter size)]. ^0. ! tryLeave: line at: pos (line subMatch: leave startingAt: pos) ifTrue: [ state := false. Transcript show: ''. ^(leave size)]. ^0. !! ! SequenceableCollection methodsFor:'testing' ! subMatch: subCollection startingAt: idx | subIndex | (idx + subCollection size - 1) > self size ifTrue:[^false]. subIndex := 1. self from: idx to: (idx + subCollection size - 1) do: [:char | (char = (subCollection at: subIndex)) ifFalse: [^false]. subIndex := subIndex + 1. ]. ^true. !! ParserTagState subclass: #ParserWPLink instanceVariableNames: 'startPos' classVariableNames: '' poolDictionaries: '' category: nil ! ! ParserWPLink methodsFor: 'general' ! init state := false. ! tryEnter: line at: pos (line subMatch: '[[' startingAt: pos) ifTrue: [ state := true. startPos := pos + 2. ^((line indexOfRegex:'\]\]' startingAt: pos ifAbsent:[pos]) first - pos) ]. ^0. ! tryLeave: line at: pos (line subMatch: ']]' startingAt: pos) ifTrue: [ |dest| state := false. dest := line copyFrom: startPos to: pos - 1. Transcript show: '', dest, ''. ^2]. ^0. !! Object subclass: #ParserPlain instanceVariableNames: 'syntax element' classVariableNames: '' poolDictionaries: '' category: nil ! ! ParserPlain methodsFor: 'general' ! init: html syn: syn syntax := syn. element := html. ! try: line at: pos (line subMatch: syntax startingAt: pos) ifTrue: [ Transcript show: element. ^(syntax size)]. ^0. !! p := PParser new. p init. " p parseLine: 'Normal line'. p parseLine: ' preformatted line'. p parseLine: ' ...or lines'. p parseLine: '^quoted line'. p parseLine: '*bullet1'. p parseLine: '**bullet2'. p parseLine: 'Normal line'. p parseLine: '-s-stuck out-s- arr-->ow [=typewriter ///ital/// still typewriter=]'. p parseLine: '* [[Wikipedia]]'. p parseLine: 'my favorite punctuation --- the dash.'. " in := FileStream stdin. [in atEnd not] whileTrue: [ p parseLine: in nextLine. ]. p parseLine: ''. "close all list tags."