initial checkin
authorClaus Gittinger <cg@exept.de>
Fri, 01 Jul 2011 16:19:38 +0200
changeset 10022 a51c7fd32748
parent 10021 af3ee96d9f16
child 10023 68c1f1618b7d
initial checkin
SyntaxHighlighter2.st
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SyntaxHighlighter2.st	Fri Jul 01 16:19:38 2011 +0200
@@ -0,0 +1,741 @@
+"
+ COPYRIGHT (c) 2006 by eXept Software AG
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+"{ Package: 'stx:libtool' }"
+
+SyntaxHighlighter subclass:#SyntaxHighlighter2
+	instanceVariableNames:'elements lastSelectorElement lastVariableElement'
+	classVariableNames:''
+	poolDictionaries:''
+	category:'Interface-CodeView-Syntax'
+!
+
+!SyntaxHighlighter2 class methodsFor:'documentation'!
+
+copyright
+"
+ COPYRIGHT (c) 2006 by eXept Software AG
+	      All Rights Reserved
+
+ This software is furnished under a license and may be used
+ only in accordance with the terms of that license and with the
+ inclusion of the above copyright notice.   This software may not
+ be provided or otherwise made available to, or used by, any
+ other person.  No title to or ownership of the software is
+ hereby transferred.
+"
+! !
+
+!SyntaxHighlighter2 class methodsFor:'highlighting'!
+
+formatClassDefinition:aString in:aClass elementsInto: elements
+    "format (recolor) a class definition expression in a given class.
+     Return the text containing font changes and color information."
+
+    ^ self formatExpression:aString in:aClass elementsInto: elements
+
+    "Created: / 10-04-2011 / 18:18:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+formatExpression:aString in:aClass elementsInto: elements
+    "format (recolor) an expression in a given class.
+     Return the text containing font changes and color information."
+
+    |parser tree text endPos|
+
+    aString isNil ifTrue:[^ nil].
+
+    parser := self for:(ReadStream on:aString string) in:aClass.
+    parser elements: elements.
+    parser ignoreErrors:true.
+    parser ignoreWarnings:true.
+    parser sourceText:(text := aString string asText).
+    "/ use an array here - this can be changed much faster using #at:put:
+    text emphasisCollection:(Array new:aString size).
+
+    parser nextToken.
+    tree := parser "expression"statementList.
+    "/ now, convert the emphasis-array to a runArray
+    text emphasisCollection:(text emphasis asRunArray).
+
+    tree == #Error ifTrue:[
+        "/ mhmh - which is better ...
+        "/ alternative1: color rest after error in red
+"/        text 
+"/            emphasizeFrom:(parser sourceStream position) 
+"/            to:text size 
+"/            with:(#color->Color red).
+
+
+        "/ alternative2: take original emphasis for rest
+
+        endPos := parser sourceStream position1Based.
+        endPos >= text size ifTrue:[
+            ^ text
+        ].
+        ^ ((text copyTo:endPos) , (aString copyFrom:(endPos+1))).
+
+        "/ alternative3: no emphasis for rest.
+
+"/        ^ text "/ aString
+    ].
+    ^ text
+
+    "
+     self
+        formatExpression:'(1 + 2) max:5' 
+        in:UndefinedObject
+    "
+
+    "Created: / 25-07-2010 / 08:56:05 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 25-07-2010 / 10:57:00 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+formatMethod:aString in:aClass using:preferencesOrNil elementsInto: elements
+    "format (recolor) a method in a given class.
+     Return the text containing font changes and color information."
+
+    |highlighter tree text endPos eColor|
+
+    aString isNil ifTrue:[^ nil].
+
+    Error handle:[:ex |
+        ex signal isHandled ifTrue:[
+            ex reject.    
+        ].
+        (self parseErrorSignal handles:ex) ifFalse:[
+            "Parse error may happen when re-formatting incomplete code while editing"
+            ('SyntaxHighlighter [info]: error during highlight: ' , ex description) infoPrintCR.
+            "/ ex suspendedContext fullPrintAll.
+        ].
+        ^ aString
+    ] do:[
+        highlighter := self for:(ReadStream on:aString string) in:aClass.
+        highlighter elements: elements.
+        preferencesOrNil notNil ifTrue:[highlighter preferences:preferencesOrNil].
+        "/ highlighter ignoreErrors:true.
+        highlighter ignoreWarnings:true.
+        highlighter sourceText:(text := aString string asText).
+        "/ use an array here - this can be changed much faster using #at:put:
+        text emphasisCollection:(Array new:aString size).
+
+        tree := highlighter parseMethod.
+        "/ now, convert the emphasis-array to a runArray
+        text emphasisCollection:(text emphasis asRunArray).
+
+        tree == #Error ifTrue:[
+            eColor := UserPreferences current errorColor.
+            eColor notNil ifTrue:[
+                "/ mhmh - which is better ...
+                "/ alternative1: color rest after error in red
+                text 
+                    emphasizeFrom:(highlighter sourceStream position1Based) 
+                    to:text size 
+                    with:(#color->eColor).
+            ] ifFalse:[
+                "/ alternative2: take original emphasis for rest
+
+                endPos := highlighter sourceStream position1Based.
+                endPos >= text size ifTrue:[
+                    ^ Array with: text with: highlighter elements
+                ].
+                ^ ((text copyTo:endPos) , (aString copyFrom:(endPos+1)))
+            ].
+            "/ alternative3: no emphasis for rest.
+        ].
+        ^text 
+    ]
+    "
+     self
+        formatMethod:'foo 
+    ^ self bar:''hello''.
+
+    ' , (Character doubleQuote asString) , 'some comment' , (Character doubleQuote asString) , '
+'
+        in:UndefinedObject
+    "
+
+    "Modified: / 22-08-2006 / 13:32:04 / cg"
+    "Created: / 25-07-2010 / 08:56:29 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SyntaxHighlighter2 methodsFor:'accessing'!
+
+elements
+    ^ elements
+!
+
+elements:something
+    elements := something.
+! !
+
+!SyntaxHighlighter2 methodsFor:'initialization'!
+
+initialize
+
+    super initialize.
+    elements := SortedCollection new.
+    lastVariableElement := Dictionary new.
+
+    "Created: / 14-02-2010 / 13:08:27 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 25-06-2010 / 13:04:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SyntaxHighlighter2 methodsFor:'parsing-expressions'!
+
+binaryExpressionFor:receiverArg
+    "parse a binary-expression; return a node-tree, nil or #Error"
+
+    |receiver expr arg sel pos1 pos2 lno note|
+
+    receiver := receiverArg.
+    (receiver == #Error) ifTrue:[^ #Error].
+
+    "special kludge: since Scanner cannot know if -digit is a binary
+     expression or a negative constant, handle cases here"
+
+    [(tokenType == #BinaryOperator) 
+     or:[(tokenType == $|)
+     or:[(tokenType == $^ and:[parserFlags allowCaretAsBinop])
+         or:[((tokenType == #Integer) or:[tokenType == #Float])
+             and:[tokenValue < 0]]]]
+    ] whileTrue:[
+        "/ kludge alarm: in a function-call argList, #, is not a binarySelector
+        inFunctionCallArgument == true ifTrue:[
+            ((tokenType == #BinaryOperator) and:[tokenName = ',']) ifTrue:[
+                ^ receiver
+            ].
+        ].
+
+        pos1 := tokenPosition.
+        lno := tokenLineNr.
+
+        "/ kludge alarm: bar, caret and minus are not scanned as binop
+        (tokenType == $|) ifTrue:[
+            sel := '|'.
+            sel := self selectorCheck:sel for:receiver position:tokenPosition to:tokenPosition.
+            self nextToken.
+        ] ifFalse:[
+            (tokenType == $^) ifTrue:[
+                sel := '^'.
+                sel := self selectorCheck:sel for:receiver position:tokenPosition to:tokenPosition.
+                self nextToken.
+            ] ifFalse:[
+                (tokenType == #BinaryOperator) ifTrue:[
+                    sel := tokenName.
+                    sel := self selectorCheck:sel for:receiver position:tokenPosition to:(tokenPosition + tokenName size - 1).
+                    self nextToken
+                ] ifFalse:[
+                    sel := '-'.
+                    token := tokenValue := tokenValue negated.
+                    tokenPosition := tokenPosition + 1. "/ to skip the sign
+                ]
+            ].
+        ].
+
+        pos2 := pos1 + sel size - 1.
+        self markSelector:sel from:pos1 to:pos2 receiverNode:receiver.
+        lastSelectorElement := nil.
+
+        arg := self unaryExpression.
+        (arg == #Error) ifTrue:[^ #Error].
+
+        expr := BinaryNode receiver:receiver selector:sel arg:arg fold:foldConstants.
+        expr isErrorNode ifTrue:[
+            self parseError:(expr errorString) position:pos1 to:tokenPosition.
+            errorFlag := false. "ok, user wants it - so he'll get it"
+            expr := BinaryNode receiver:receiver selector:sel arg:arg fold:nil.
+        ].
+        expr lineNumber:lno.
+        expr selectorPosition:pos1.
+
+        (ignoreErrors or:[ignoreWarnings]) ifFalse:[
+            note := self plausibilityCheck:expr.
+            note notNil ifTrue:[
+                self warning:note position:pos1 to:pos2
+            ].
+        ].
+        parseForCode ifFalse:[
+            self rememberSelectorUsed:sel receiver:receiver
+        ].
+        receiver := expr.   "/ for next message
+    ].
+    ^ receiver
+
+    "Modified: / 09-01-1998 / 19:05:18 / stefan"
+    "Modified: / 19-01-2000 / 16:22:04 / cg"
+    "Modified: / 14-02-2010 / 17:54:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+expression
+    "parse a cascade-expression; return a node-tree, nil or #Error.
+
+     expression ::= keywordExpression
+                    | keywordExpression cascade
+
+     cascade ::= ';' expressionSendPart
+                 | cascade ';' expressionSendPart
+
+     expressionSendPart ::= { KEYWORD binaryExpression }
+                            | BINARYOPERATOR unaryExpression
+                            | IDENTIFIER
+    "
+
+    |receiver arg sel args pos pos2 lno tokenEnd realReceiver positions|
+
+    pos := tokenPosition.
+    receiver := self keywordExpression.
+    (receiver == #Error) ifTrue:[^ #Error].
+    (tokenType == $;) ifTrue:[
+        receiver isMessage ifFalse:[
+            self syntaxError:'left side of cascade must be a message expression'
+                    position:pos to:tokenPosition.
+            realReceiver := receiver. "/ only to allow continuing.
+        ] ifTrue:[
+            realReceiver := receiver receiver.
+        ].
+        [tokenType == $;] whileTrue:[
+            self nextToken.
+            (tokenType == #Identifier) ifTrue:[
+                tokenEnd := tokenPosition + tokenName size - 1.
+                self markSelector:tokenName from:tokenPosition to:tokenEnd receiverNode:realReceiver.
+                sel := tokenName.
+                sel := self selectorCheck:tokenName for:realReceiver position:tokenPosition to:tokenEnd.
+                receiver := CascadeNode receiver:receiver selector:sel.
+                receiver lineNumber:tokenLineNr.
+                parseForCode ifFalse:[
+                    self rememberSelectorUsed:sel
+                ].
+                self nextToken.
+            ] ifFalse:[
+                (tokenType == #BinaryOperator) ifTrue:[
+                    tokenEnd := tokenPosition + tokenName size - 1.
+                    self markSelector:tokenName from:tokenPosition to:tokenEnd receiverNode:realReceiver.
+                    lastSelectorElement := nil.
+                    sel := tokenName.
+                    sel := self selectorCheck:tokenName for:realReceiver position:tokenPosition to:tokenEnd.
+                    lno := tokenLineNr. 
+                    self nextToken.
+                    arg := self unaryExpression.
+                    (arg == #Error) ifTrue:[^ #Error].
+                    receiver := CascadeNode receiver:receiver selector:sel arg:arg.
+                    receiver lineNumber:lno.
+                    parseForCode ifFalse:[
+                        self rememberSelectorUsed:sel
+                    ].
+                ] ifFalse:[
+                    (tokenType == #Keyword) ifTrue:[
+                        tokenEnd := tokenPosition + tokenName size - 1.
+                        positions := OrderedCollection with:(tokenPosition to:tokenEnd).
+                        pos := tokenPosition.
+                        pos2 := tokenEnd.
+                        lno := tokenLineNr. 
+                        sel := tokenName.
+                        self nextToken.
+                        arg := self binaryExpression.
+                        (arg == #Error) ifTrue:[^ #Error].
+                        args := Array with:arg.
+                        [tokenType == #Keyword] whileTrue:[
+                            tokenEnd := tokenPosition + tokenName size - 1.
+                            positions add:(tokenPosition to:tokenEnd).
+                            sel := sel , tokenName.
+                            self nextToken.
+                            arg := self binaryExpression.
+                            (arg == #Error) ifTrue:[^ #Error].
+                            args := args copyWith:arg.
+                            pos2 := tokenEnd
+                        ].
+                        positions do:[:p |
+                            self markSelector:sel from:p start to:p stop receiverNode:realReceiver.
+                        ].
+                        lastSelectorElement := nil.                                
+
+                        sel := self selectorCheck:sel for:realReceiver position:pos to:pos2.
+
+                        receiver := CascadeNode receiver:receiver selector:sel args:args.
+                        receiver lineNumber:lno.
+                        parseForCode ifFalse:[
+                            self rememberSelectorUsed:sel
+                        ].
+                    ] ifFalse:[
+                        (tokenType == #Error) ifTrue:[^ #Error].
+                        self syntaxError:('invalid cascade; ' , tokenType printString , ' unexpected')
+                                position:tokenPosition to:source position1Based - 1.
+                        ^ #Error
+                    ]
+                ]
+            ]
+        ].
+
+        "obscure (unspecified ?) if selector follows; Question:
+
+        is
+                'expr sel1; sel2 sel3'
+
+        to be parsed as: 
+                (t := expr.
+                 t sel1.
+                 t sel2) sel3
+
+         or:
+                (t := expr.
+                 t sel1.
+                 t sel2 sel3)
+        "
+        ((tokenType == #Identifier) 
+         or:[(tokenType == #BinaryOperator)
+             or:[tokenType == #Keyword]]) ifTrue:[
+            self syntaxError:'ambigous cascade - please group using (...)'
+                    position:tokenPosition to:source position1Based - 1.
+            ^ #Error
+"/            self warning: "syntaxError:" 'possibly ambigous cascade - please group using (...)'
+"/                    position:tokenPosition to:source position - 1.
+"/            tokenType == #Identifier ifTrue:[
+"/                ^ self unaryExpressionFor:receiver
+"/            ].
+"/            tokenType == #BinaryOperator ifTrue:[
+"/                ^ self binaryExpressionFor:receiver
+"/            ].
+"/            ^ self keywordExpressionFor:receiver
+        ]
+    ].
+    ^ receiver
+
+    "Modified: / 19-01-2000 / 16:22:16 / cg"
+    "Modified: / 14-02-2010 / 17:58:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+keywordExpressionFor:receiverArg
+    "parse a keyword-expression; return a node-tree, nil or #Error.
+
+     keywordExpression ::= binaryexpression
+                           | { KEYWORD-PART binaryExpression }
+    "
+
+    |expr receiver sel arg args posR1 posR2 pos1 pos2 lno note positions constVal|
+
+    receiver := receiverArg.
+    posR1 := tokenPosition.
+    (tokenType == #Keyword) ifFalse:[^ receiver].
+
+    pos1 := posR2 := tokenPosition.
+    pos2 := tokenPosition + tokenName size - 1.
+    positions := OrderedCollection with:(pos1 to:pos2).
+    sel := tokenName.
+    lno := tokenLineNr.
+    self nextToken.
+    arg := self binaryExpression.
+    (arg == #Error) ifTrue:[^ #Error].
+    args := Array with:arg.
+    [tokenType == #Keyword] whileTrue:[
+        sel := sel , tokenName.
+        pos2 := tokenPosition + tokenName size - 1.
+        positions add:(tokenPosition to:pos2).
+        self nextToken.
+        arg := self binaryExpression.
+        (arg == #Error) ifTrue:[^ #Error].
+        args := args copyWith:arg.
+    ].
+
+    positions do:[:p |
+        self markSelector:sel from:p start to:p stop receiverNode:receiver.
+    ].
+    lastSelectorElement := nil.
+    sel := self selectorCheck:sel for:receiver positions:positions.
+
+    ignoreWarnings ifFalse:[
+        (Class definitionSelectors includes:sel) ifTrue:[
+            (receiver isVariable and:[receiver isUndeclared]) ifTrue:[
+                "this is not an error - the undefined class may be loaded after this code!!"
+                self warning:('as yet undefined superclass: ' , receiver name) position:pos1 to:pos2.
+            ].
+        ].
+    ].
+
+    expr := MessageNode receiver:receiver selector:sel args:args fold:foldConstants.
+    expr isErrorNode ifTrue:[
+        self parseError:(expr errorString) position:pos1 to:pos2.
+        errorFlag := false. "ok, user wants it - so he'll get it"
+        expr := MessageNode receiver:receiver selector:sel args:args fold:nil.
+    ].
+    expr lineNumber:lno.
+    (ignoreErrors or:[ignoreWarnings]) ifFalse:[
+        note := self plausibilityCheck:expr.
+        note notNil ifTrue:[
+            self warning:note position:pos1 to:pos2
+        ].
+    ].
+    parseForCode ifFalse:[
+        self rememberSelectorUsed:sel receiver:receiver
+    ].
+
+"/        (contextToEvaluateIn isNil and:[selfValue isNil]) ifTrue:[    "/ do not check this for doits
+"/            receiver isSuper ifTrue:[
+"/                sel ~= selector ifTrue:[
+"/                    self warnCommonMistake:'possible bad super message (selector should be same as in current method) ?'
+"/                                  position:posR1 to:posR2-1
+"/                ].
+"/            ].
+"/        ].
+"/
+
+    (sel = #ifTrue: or:[sel = #ifFalse: or:[sel = #ifTrue:ifFalse: or:[sel = #ifFalse:ifTrue:]]]) ifTrue:[
+        (expr receiver withConstantValueDo:[:val | constVal := val]) ifTrue:[
+            |indexOfArgNotExecuted|
+
+            "/ receiver evaluates to a constant
+            constVal == true ifTrue:[
+                (sel startsWith: #ifFalse:) ifTrue:[
+                    indexOfArgNotExecuted := 1.
+                ] ifFalse:[
+                    indexOfArgNotExecuted := 2.
+                ]
+            ].
+            constVal == false ifTrue:[
+                (sel startsWith: #ifTrue:) ifTrue:[
+                    indexOfArgNotExecuted := 1.
+                ] ifFalse:[
+                    indexOfArgNotExecuted := 2.
+                ]
+            ].
+            indexOfArgNotExecuted == 2 ifTrue:[
+                args size == 1 ifTrue:[ indexOfArgNotExecuted := nil]
+            ].
+
+            indexOfArgNotExecuted notNil ifTrue:[
+                |argIsNotExecuted|
+
+                "/ self warning:'receiver is constant; arg',indexOfArgNotExecuted printString,' is never executed' position:pos1 to:tokenPosition.
+                argIsNotExecuted := expr args at:indexOfArgNotExecuted.
+                argIsNotExecuted isBlockNode ifTrue:[
+                    self markCommentFrom:argIsNotExecuted startPosition to:argIsNotExecuted endPosition.
+                ].
+            ].
+        ].
+    ].
+
+    (ignoreErrors or:[ignoreWarnings]) ifFalse:[
+        (sel = #and: or:[sel = #or:]) ifTrue:[
+            expr arg1 isBlock ifFalse:[
+                (expr arg1 isVariable
+                and:[ (expr arg1 name asLowercase includesString:'block')]) ifFalse:[
+                    self warnCommonMistake:'(possible common mistake) missing block brackets ?'
+                              position:pos2+1 to:tokenPosition-1
+                ]
+            ].
+            ^ expr.
+        ].
+
+        (sel = #whileTrue: or:[sel = #whileFalse:]) ifTrue:[
+            expr receiver isBlock ifFalse:[
+                (expr receiver isVariable
+                and:[ (expr receiver name asLowercase includesString:'block')]) ifFalse:[
+                    self warnCommonMistake:'(possible common mistake) missing block brackets ?'
+                              position:pos1 to:pos2
+                ]
+            ].
+            ^ expr.
+        ].
+
+        (sel = #ifTrue: or:[sel = #ifFalse:]) ifTrue:[
+            expr receiver isMessage ifTrue:[
+                (expr receiver selector = #whileTrue or:[expr receiver selector = #whileFalse]) ifTrue:[
+                    self warnCommonMistake:'strange receiver expression'
+                              position:pos1 to:pos2
+                ].
+            ].
+            ^ expr
+        ].
+    ].
+
+    ^ expr.
+
+    "Modified: / 19-01-2000 / 16:22:22 / cg"
+    "Modified: / 14-02-2010 / 17:58:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+unaryExpressionFor:receiverArg
+    "parse a unary-expression; return a node-tree, nil or #Error"
+
+    |receiver expr sel pos pos2 note lNr arguments|
+
+    receiver := receiverArg.
+    (receiver == #Error) ifTrue:[^ #Error].
+
+    [ self isValidUnarySelector:tokenType ] whileTrue:[
+        pos := tokenPosition.
+        pos2 := pos + tokenName size - 1.
+        lNr := tokenLineNr.
+        sel := tokenName.
+
+        self markSelector:sel from:pos to:pos2 receiverNode:receiver.
+        lastSelectorElement := nil.
+
+        self nextToken.
+        tokenType == $( ifTrue:[
+            parserFlags allowSqueakExtensions == true ifTrue:[
+                "/ croquet/squeak extension - c/java-style arguments
+                arguments := self functionCallArgList.
+                "/ synthetic selector: foo[:[with:[with:[...]]]]
+                arguments notEmpty ifTrue:[
+                    sel := sel , ':'.
+                    arguments size - 1 timesRepeat:[ sel := sel , 'with:' ].
+                ].
+                sel := self selectorCheck:sel for:receiver position:pos to:pos2.
+                expr := MessageNode receiver:receiver selector:sel args:arguments fold:foldConstants.
+                expr isErrorNode ifTrue:[
+                    self parseError:(expr errorString) position:pos to:pos2.
+                    errorFlag := false. "ok, user wants it - so he'll get it"
+                    expr := MessageNode receiver:receiver selector:sel args:arguments fold:nil.
+                ].
+                expr lineNumber:lNr.
+                (ignoreErrors or:[ignoreWarnings]) ifFalse:[
+                    note := self plausibilityCheck:receiver.
+                    note notNil ifTrue:[
+                        self warning:note position:pos to:pos2
+                    ].
+                ].
+                parseForCode ifFalse:[
+                    self rememberSelectorUsed:sel receiver:receiver
+                ].
+                ^ expr.
+            ].
+        ].
+
+        sel := self selectorCheck:sel for:receiver position:pos to:pos2.
+        expr := UnaryNode receiver:receiver selector:sel fold:foldConstants.
+        expr isErrorNode ifTrue:[
+            self warning:(expr errorString , '.\\If you proceed, that error will happen at runtime.') withCRs position:pos to:pos2.
+            errorFlag := false. "ok, user wants it - so he'll get it"
+            expr := UnaryNode receiver:receiver selector:sel fold:nil.
+        ].
+        expr lineNumber:lNr.
+
+        (ignoreErrors or:[ignoreWarnings]) ifFalse:[
+            note := self plausibilityCheck:expr.
+            note notNil ifTrue:[
+                self warning:note position:pos to:pos2
+            ].
+        ].
+        parseForCode ifFalse:[
+            self rememberSelectorUsed:sel receiver:receiver
+        ].
+
+        receiver := expr.   "/ for next message
+    ].
+    ^ receiver
+
+    "Modified: / 16-07-2006 / 16:15:22 / cg"
+    "Modified: / 14-02-2010 / 17:56:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SyntaxHighlighter2 methodsFor:'syntax detection'!
+
+markArgumentIdentifierFrom:pos1 to:pos2
+
+    | element prev |
+
+    super markArgumentIdentifierFrom:pos1 to:pos2.
+    element := SyntaxElement from: pos1 to: pos2 type: #variable value: tokenName.
+    prev := lastVariableElement at: tokenName ifAbsent:[nil].
+    prev ifNotNil:[prev next:element].
+    lastVariableElement at: tokenName put:element.
+    elements add: element.
+
+    "Created: / 24-07-2010 / 09:25:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+markGlobalClassIdentifierFrom:pos1 to:pos2
+
+    | name env cls |
+
+    super markGlobalClassIdentifierFrom:pos1 to:pos2.
+
+    name := token isString ifTrue:[token asSymbolIfInterned] ifFalse:[nil].
+    name ifNotNil:
+        [env := (classToCompileFor ? UndefinedObject) theNonMetaclass environment.
+        cls := env isNameSpace 
+                ifTrue:[env at: name]
+                ifFalse:[nil].
+        cls ifNil:[
+        cls := Smalltalk at: name]].
+
+    elements add:
+        (SyntaxElement from: pos1 to: pos2 type: #class value: cls)
+
+    "Created: / 14-02-2010 / 14:08:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 15-02-2010 / 10:53:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+markLocalIdentifierFrom:pos1 to:pos2
+    | element prev |
+
+    super markLocalIdentifierFrom:pos1 to:pos2.
+    element := SyntaxElement from: pos1 to: pos2 type: #variable value: tokenName.
+    prev := lastVariableElement at: tokenName ifAbsent:[nil].
+    prev ifNotNil:[prev next:element].
+    lastVariableElement at: tokenName put:element.
+    elements add: element.
+
+    "Created: / 24-07-2010 / 09:28:55 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+markSelector:selectorString from:pos1 to:pos2 receiverNode:aReceiverNode
+
+    | element |
+
+    super markSelector:selectorString from:pos1 to:pos2 receiverNode:aReceiverNode.
+
+    element := SyntaxElement from: pos1 to: pos2 type: #selector value: selectorString asSymbol.
+    lastSelectorElement 
+        ifNotNil:[lastSelectorElement next: element].
+    elements add: element.
+    lastSelectorElement := element.
+
+    "Created: / 14-02-2010 / 17:40:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 14-02-2010 / 19:24:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+markUnknownIdentifierFrom:pos1 to:pos2
+
+    classToCompileFor 
+        ifNotNil:[super markUnknownIdentifierFrom:pos1 to:pos2]
+        ifNil:[self markLocalIdentifierFrom: pos1 to: pos2].
+
+    "Created: / 24-07-2010 / 09:51:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+markVariable:v from:pos1 to:pos2
+
+    | element prev |
+    super markVariable:v from:pos1 to:pos2.
+    (v type == #GlobalVariable) ifTrue:[^self].
+
+    element := SyntaxElement from: pos1 to: pos2 type: #variable value: v name.
+
+    prev := lastVariableElement at: v name ifAbsent:[nil].
+    prev ifNotNil:[prev next:element].
+    lastVariableElement at: v name put:element.
+    elements add: element.
+
+    "Created: / 25-06-2010 / 13:03:37 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 25-06-2010 / 14:23:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!SyntaxHighlighter2 class methodsFor:'documentation'!
+
+version_CVS
+    ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.1 2011-07-01 14:19:38 cg Exp $'
+!
+
+version_SVN
+    ^ '§Id: SyntaxHighlighter2.st 7715 2011-04-10 16:32:58Z vranyj1 §'
+! !