SmallSense__SmalltalkParser.st
changeset 96 12fe1a59dfd1
parent 85 d6a3fdbd87db
child 161 5ff416530ac4
child 174 3e08d765d86f
--- a/SmallSense__SmalltalkParser.st	Wed Sep 18 02:36:36 2013 +0100
+++ b/SmallSense__SmalltalkParser.st	Fri Sep 20 01:55:35 2013 +0100
@@ -3,7 +3,7 @@
 "{ NameSpace: SmallSense }"
 
 SyntaxHighlighter subclass:#SmalltalkParser
-	instanceVariableNames:'error'
+	instanceVariableNames:'errorRecovery error'
 	classVariableNames:''
 	poolDictionaries:''
 	category:'SmallSense-Smalltalk'
@@ -31,6 +31,15 @@
     "Created: / 27-11-2011 / 09:45:03 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
+!SmalltalkParser methodsFor:'initialization'!
+
+initialize
+    super initialize.
+    errorRecovery := true
+
+    "Created: / 19-09-2013 / 11:25:01 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
 !SmalltalkParser methodsFor:'parsing'!
 
 blockStatementList
@@ -141,6 +150,83 @@
 
     "Created: / 14-12-1999 / 15:11:37 / cg"
     "Created: / 09-07-2011 / 22:23:25 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+statement
+    "parse a statement; return a node-tree or #Error.
+
+     statement ::= '^' expression
+                   | PRIMITIVECODE
+                   | expression
+    "
+
+    |expr node lnr code pos|
+
+    pos := tokenPosition.
+
+    (tokenType == $^) ifTrue:[
+        ^ self returnStatement
+    ].
+
+    (tokenType == #Primitive) ifTrue:[
+        code := tokenValue.
+        node := PrimitiveNode code:code.
+        node startPosition: tokenPosition endPosition: source position + 1.
+        self nextToken.
+        node isOptional ifFalse:[
+            hasNonOptionalPrimitiveCode := true
+        ].
+        hasPrimitiveCode := true.
+        ^ node
+    ].
+
+    (tokenType == #EOF) ifTrue:[
+        currentBlock notNil ifTrue:[
+            self syntaxError:'missing '']'' at end of block'.
+            errorRecovery ifTrue:[
+                tokenType := $].
+                ^ error.
+            ].
+        ] ifFalse:[
+            self syntaxError:'period after last statement'.
+            errorRecovery ifTrue:[
+                tokenType := $..
+                ^ error.
+            ].  
+        ].
+        ^ #Error
+    ].
+
+    (tokenType == $.) ifTrue:[
+        (parserFlags allowEmptyStatements
+        or:[parserFlags allowSqueakExtensions == true]) ifTrue:[
+            "/ allow empty statement
+            self warnAboutEmptyStatement.
+            node := StatementNode expression:nil.
+            node startPosition:pos.
+            ^ node
+        ].
+    ].
+
+    lnr := tokenLineNr.
+
+    expr := self expression.
+    (expr == #Error) ifTrue:[^ #Error].
+
+"/    classToCompileFor notNil ifTrue:[
+"/        currentBlock isNil ifTrue:[
+"/            expr isPrimary ifTrue:[
+"/                self warning:'useless computation - missing ^ ?'
+"/            ]
+"/        ]
+"/    ].
+
+    node := StatementNode expression:expr.
+    parserFlags fullLineNumberInfo ifTrue:[node lineNumber:lnr].
+    node startPosition:pos.
+    ^ node
+
+    "Created: / 19-09-2013 / 11:32:07 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
 !SmalltalkParser methodsFor:'parsing-expressions'!
@@ -168,7 +254,7 @@
         "/ would be parsed as unary message foo; detect this here, instead of high up in the calling hierarchy,
         "/ where it is difficult to provide a reasonable error message
         tokenType == #':=' ifTrue:[
-            | positionOfPeriod exprLast |
+            | positionOfPeriod exprLast exprLastParent |
 
             "/ Find the very last unary send node, Consider:
             "/    x := 2
@@ -180,8 +266,10 @@
             "/    x := 2 between: 0 and: self max
             "/    y := false  
 
+            exprLastParent := nil.
             exprLast := expr.
             [ exprLast isMessage and: [ exprLast isUnaryMessage not ] ] whileTrue:[
+                exprLastParent := exprLast.
                 exprLast := exprLast args last.
             ].
             (exprLast isMessage and: [ exprLast isUnaryMessage ] ) ifTrue:[
@@ -189,6 +277,13 @@
             ].
             positionOfPeriod notNil ifTrue:[
                 "/Try to recover
+                "/ Strip the last unary message whose selector is actually a variable name..."
+                exprLastParent notNil ifTrue:[
+                    exprLastParent args at: exprLastParent args size put: exprLast receiver.
+                ] ifFalse:[
+                    "/ no nesting, the expr itself is errorneouts...    
+                     expr := expr receiver.
+                ].
                 expr := ParseErrorNode new
                         startPosition:expr startPosition endPosition: positionOfPeriod - 1;
                         errorString: ('":=" unexpected. Probably missing "." in previous expression.');
@@ -203,7 +298,7 @@
     ^ expr
 
     "Created: / 16-09-2013 / 17:23:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
-    "Modified: / 16-09-2013 / 23:18:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+    "Modified: / 19-09-2013 / 11:47:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
 primary