--- a/SyntaxHighlighter2.st Wed Feb 05 19:59:07 2014 +0100
+++ b/SyntaxHighlighter2.st Wed Feb 05 19:59:09 2014 +0100
@@ -26,7 +26,8 @@
"{ Package: 'stx:libtool' }"
SyntaxHighlighter subclass:#SyntaxHighlighter2
- instanceVariableNames:'elements lastVariableElements lastSelectorElement'
+ instanceVariableNames:'elements lastVariableElements lastSelectorElement
+ ignoreBadIdentifier'
classVariableNames:''
poolDictionaries:''
category:'Interface-CodeView-Syntax'
@@ -132,16 +133,54 @@
"format (recolor) an expression in a given class.
Return the text containing font changes and color information."
- ^ self
- format:aString parsingWith:[:parser | parser expression]
- in:aClass elementsInto:elements
+ |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
- elementsInto:(OrderedCollection new)
+ 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
@@ -169,7 +208,7 @@
Error handle:[:ex |
ex creator isHandled ifTrue:[
- ex reject.
+ ex reject.
].
(self parseErrorSignal handles:ex) ifFalse:[
"Parse error may happen when re-formatting incomplete code while editing"
@@ -196,9 +235,9 @@
eColor notNil ifTrue:[
"/ mhmh - which is better ...
"/ alternative1: color rest after error in red
- text
+ text
emphasizeFrom:(highlighter sourceStream position + 1)
- to:text size
+ to:text size
with:(#color->eColor).
] ifFalse:[
"/ alternative2: take original emphasis for rest
@@ -211,11 +250,11 @@
].
"/ alternative3: no emphasis for rest.
].
- ^text
+ ^text
]
"
self
- formatMethod:'foo
+ formatMethod:'foo
^ self bar:''hello''.
' , (Character doubleQuote asString) , 'some comment' , (Character doubleQuote asString) , '
@@ -225,6 +264,7 @@
"Modified: / 22-08-2006 / 13:32:04 / cg"
"Created: / 05-07-2011 / 10:39:21 / cg"
+ "Modified: / 28-05-2013 / 22:45:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
formatStatementList:aString in:aClass elementsInto: elements
@@ -249,12 +289,19 @@
^ elements
!
-elements:something
+elements:aParseTreeIndex
"the element collection, to collect variables, selectors etc. into"
- elements := something.
+ elements := aParseTreeIndex.
"Modified (comment): / 21-08-2011 / 09:13:31 / cg"
+!
+
+tree: aParseNode
+ super tree: aParseNode.
+ elements tree: aParseNode
+
+ "Created: / 16-02-2012 / 09:56:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!SyntaxHighlighter2 methodsFor:'initialization'!
@@ -262,16 +309,323 @@
initialize
super initialize.
- elements := SortedCollection new.
+ elements := ParseTreeIndex new.
lastVariableElements := 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>"
"Modified: / 21-08-2011 / 09:37:35 / cg"
+ "Modified: / 16-02-2012 / 09:59:58 / 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|
+
+ 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.
+
+ self checkPlausibilityOf:expr from: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: / 14-02-2010 / 17:54:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 19-01-2012 / 10:46:49 / cg"
+ "Created: / 16-02-2012 / 21:54:28 / 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 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.
+ self checkPlausibilityOf:expr from: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: / 14-02-2010 / 17:58:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 19-01-2012 / 10:47:01 / cg"
+ "Created: / 16-02-2012 / 21:54:35 / 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 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.
+ self checkPlausibilityOf:expr from: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.
+
+ self checkPlausibilityOf:expr from:pos to:pos2.
+ parseForCode ifFalse:[
+ self rememberSelectorUsed:sel receiver:receiver
+ ].
+
+ receiver := expr. "/ for next message
+ ].
+ ^ receiver
+
+ "Modified: / 14-02-2010 / 17:56:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 19-01-2012 / 10:47:37 / cg"
+ "Created: / 16-02-2012 / 21:54:45 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+binaryExpression
+ | node savedLastSelectorElement |
+
+ savedLastSelectorElement := lastSelectorElement.
+ lastSelectorElement := nil.
+ node := super binaryExpression.
+ (lastSelectorElement notNil and:[node ~~ #Error and:[node isMessage]]) ifTrue:[
+ lastSelectorElement node parent: node.
+ ].
+ lastSelectorElement := savedLastSelectorElement.
+ ^node
+
+ "Modified: / 19-01-2000 / 16:22:16 / cg"
+ "Created: / 16-02-2012 / 21:56:51 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
binaryExpressionFor:receiverArg
"parse a binary-expression; return a node-tree, nil or #Error"
@@ -349,132 +703,22 @@
!
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
- "
+ | node savedLastSelectorElement |
- |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.
+ savedLastSelectorElement := lastSelectorElement.
+ lastSelectorElement := nil.
+ node := super expression.
+ ((node ~~ #Error) and:[node isMessage]) ifTrue:[
+ [ lastSelectorElement notNil ] whileTrue:[
+ lastSelectorElement node parent: node.
+ lastSelectorElement := lastSelectorElement prev.
].
- [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.
- 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.
- ] 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.
- ] ifFalse:[
- (tokenType == #Error) ifTrue:[^ #Error].
- self syntaxError:('invalid cascade; ' , tokenType printString , ' unexpected')
- position:tokenPosition to:source position.
- ^ #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 position.
- ^ #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
+ lastSelectorElement := savedLastSelectorElement.
+ ^node
"Modified: / 19-01-2000 / 16:22:16 / cg"
- "Modified: / 14-02-2010 / 17:58:57 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 16-02-2012 / 23:39:15 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
keywordExpressionFor:receiverArg
@@ -621,64 +865,112 @@
unaryExpressionFor:receiverArg
"parse a unary-expression; return a node-tree, nil or #Error"
- |receiver expr sel pos pos2 lNr arguments|
+ |receiver expr sel pos pos2 lNr arguments savedLastSelectorElement|
+ savedLastSelectorElement := lastSelectorElement.
receiver := receiverArg.
(receiver == #Error) ifTrue:[^ #Error].
[ self isValidUnarySelector:tokenType ] whileTrue:[
- pos := tokenPosition.
- pos2 := pos + tokenName size - 1.
- lNr := tokenLineNr.
- sel := tokenName.
+ pos := tokenPosition.
+ pos2 := pos + tokenName size - 1.
+ lNr := tokenLineNr.
+ sel := tokenName.
- self markSelector:sel from:pos to:pos2 receiverNode:receiver.
- lastSelectorElement := nil.
+ lastSelectorElement := nil.
+ self markSelector:sel from:pos to:pos2 receiverNode:receiver.
- 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.
- self checkPlausibilityOf:expr from:pos to:pos2.
- ^ expr.
- ].
- ].
+ 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.
+ ].
+ lastSelectorElement node parent: expr.
+ expr lineNumber:lNr.
+ self checkPlausibilityOf:expr from: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.
+ 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.
+ lastSelectorElement node parent: expr.
- self checkPlausibilityOf:expr from:pos to:pos2.
+ self checkPlausibilityOf:expr from:pos to:pos2.
+ parseForCode ifFalse:[
+ self rememberSelectorUsed:sel receiver:receiver
+ ].
- receiver := expr. "/ for next message
+ receiver := expr. "/ for next message
].
+ lastSelectorElement := savedLastSelectorElement.
^ receiver
- "Modified: / 14-02-2010 / 17:56:21 / Jan Vrany <jan.vrany@fit.cvut.cz>"
"Modified: / 19-01-2012 / 10:47:37 / cg"
+ "Created: / 16-02-2012 / 23:50:17 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+variable
+ | node |
+
+ ignoreBadIdentifier := classToCompileFor isNil.
+ node := super variable.
+ ignoreBadIdentifier := false.
+ node isVariable ifTrue:[
+ | el prevEl |
+
+ el := elements newElementFor: node.
+ prevEl := lastVariableElements at:node name ifAbsent:[nil].
+ prevEl notNil ifTrue:[prevEl next:el].
+ lastVariableElements at:node name put:el.
+ elements add: el.
+ ].
+ ^node
+
+ "Modified: / 19-01-2000 / 16:22:16 / cg"
+ "Created: / 16-02-2012 / 22:21:33 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!SyntaxHighlighter2 methodsFor:'syntax detection'!
+markArgumentIdentifierFrom:pos1 to:pos2
+ | node el prevEl |
+
+ super markArgumentIdentifierFrom:pos1 to:pos2.
+ node := VariableNode methodArgumentNamed:(sourceText string copyFrom: pos1 to: pos2).
+ node startPosition: pos1 endPosition: pos2.
+ el := elements newElementFor: node.
+ prevEl := lastVariableElements at:node name ifAbsent:[nil].
+ prevEl notNil ifTrue:[prevEl next:el].
+ lastVariableElements at:node name put:el.
+ elements add: el.
+
+ "Created: / 24-07-2010 / 09:25:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+ "Modified: / 21-08-2011 / 09:27:26 / cg"
+ "Modified: / 16-02-2012 / 22:34:48 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
markAssignedVariable:v from:pos to:endPos
super markAssignedVariable:v from:pos to:endPos.
(v type == #GlobalVariable) ifTrue:[^self].
@@ -686,6 +978,13 @@
self rememberVariableElementFor:v name type:v type from:pos to:endPos assigned:true
!
+markBadIdentifierFrom:pos1 to:pos2
+
+ super markBadIdentifierFrom:pos1 to:pos2
+
+ "Created: / 17-03-2012 / 19:02:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
markGlobalClassIdentifierFrom:pos1 to:pos2
| name env cls |
@@ -709,8 +1008,19 @@
!
markLocalIdentifierFrom:pos1 to:pos2
+ | node el prevEl |
+
super markLocalIdentifierFrom:pos1 to:pos2.
- self rememberVariableElementFor:tokenName type:#MethodVariable from:pos1 to:pos2 assigned:false
+ node := VariableNode methodLocalNamed:(sourceText string copyFrom: pos1 to: pos2).
+ node startPosition: pos1 endPosition: pos2.
+ el := elements newElementFor: node.
+ prevEl := lastVariableElements at:node name ifAbsent:[nil].
+ prevEl notNil ifTrue:[prevEl next:el].
+ lastVariableElements at:node name put:el.
+ elements add: el.
+
+ "Modified: / 21-08-2011 / 09:27:26 / cg"
+ "Created: / 16-02-2012 / 22:36:41 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
markMethodArgumentIdentifierFrom:pos1 to:pos2
@@ -725,18 +1035,35 @@
| element selectorSymbol |
- super markSelector:selectorString from:pos1 to:pos2 receiverNode:aReceiverNode.
+ "Special hack for Java class references - I would like to have them
+ marked specially (and not as an error when the class is not yet loaded -
+ the code is correct as JavaClassAccessor loads it lazily"
+ (aReceiverNode isJavaPackageReference) ifTrue:[
+ self
+ markFrom:pos1 to:pos2
+ withEmphasis:preferences globalClassIdentifierEmphasis
+ color: preferences globalClassIdentifierColor
+ ] ifFalse:[
+ super markSelector:selectorString from:pos1 to:pos2 receiverNode:aReceiverNode.
+ ].
+
"don't create symbols for partial typed selectors"
selectorSymbol := selectorString asSymbolIfInterned.
- element := SyntaxElement from: pos1 to: pos2 type: #selector value: (selectorSymbol ? selectorString).
- lastSelectorElement ifNotNil:[lastSelectorElement next: element].
+ element := elements newElementFor: (SelectorNode value: selectorString from: pos1 to: pos2).
+
+ (lastSelectorElement notNil "and:[lastSelectorElement value = selectorString]") ifTrue:[
+ lastSelectorElement next: element.
+ ].
elements add: element.
- lastSelectorElement := element.
+ lastSelectorElement := "(self isValidUnarySelector:tokenType)"false
+ ifTrue:[nil]
+ ifFalse:[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>"
"Modified (format): / 21-08-2011 / 09:18:21 / cg"
+ "Modified: / 19-04-2012 / 09:53:59 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
markSelfFrom:pos1 to:pos2
@@ -748,12 +1075,12 @@
markUnknownIdentifierFrom:pos1 to:pos2
- classToCompileFor notNil
- ifTrue:[super markUnknownIdentifierFrom:pos1 to:pos2]
- ifFalse:[self markLocalIdentifierFrom: pos1 to: pos2].
+ ignoreBadIdentifier == true ifTrue:[ ^ self ].
- "Created: / 24-07-2010 / 09:51:38 / Jan Vrany <jan.vrany@fit.cvut.cz>"
- "Modified: / 02-08-2011 / 09:35:02 / cg"
+ super markUnknownIdentifierFrom:pos1 to:pos2
+
+ "Created: / 31.3.1998 / 19:09:26 / cg"
+ "Modified: / 31.3.1998 / 19:10:30 / cg"
!
markVariable:v from:pos1 to:pos2 assigned:assigned
@@ -794,14 +1121,14 @@
!SyntaxHighlighter2 class methodsFor:'documentation'!
version
- ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.18 2013-08-10 11:10:24 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.19 2014-02-05 18:59:09 cg Exp $'
!
version_CVS
- ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.18 2013-08-10 11:10:24 stefan Exp $'
+ ^ '$Header: /cvs/stx/stx/libtool/SyntaxHighlighter2.st,v 1.19 2014-02-05 18:59:09 cg Exp $'
!
version_SVN
- ^ '$Id: SyntaxHighlighter2.st,v 1.18 2013-08-10 11:10:24 stefan Exp $'
+ ^ '$Id: SyntaxHighlighter2.st,v 1.19 2014-02-05 18:59:09 cg Exp $'
! !