compiler/PPCTokenizingCodeGenerator.st
changeset 465 f729f6cd3c76
parent 460 87a3d30ab570
parent 464 f6d77fee9811
child 467 dd13296df294
--- a/compiler/PPCTokenizingCodeGenerator.st	Wed May 20 16:47:52 2015 +0100
+++ b/compiler/PPCTokenizingCodeGenerator.st	Thu May 21 14:35:34 2015 +0100
@@ -26,43 +26,102 @@
 
 tokenGenerator: whatever
     tokenGenerator := whatever
+!
+
+tokenGuards
+    "When tokenizing, do not use guards"
+    ^ arguments guards
+! !
+
+!PPCTokenizingCodeGenerator methodsFor:'guards'!
+
+addGuard: node ifTrue: trueBlock ifFalse: falseBlock
+    |  guard id |
+    guard := PPCTokenGuard on: node.
+    (self guards not or: guard makesSense not) ifTrue: [ ^ false ].
+    
+    id := compiler idFor: guard firstToken.
+
+    compiler add: 'self ', id asString.
+
+    trueBlock isNil ifFalse: [ 
+        compiler addOnLine: ' ifTrue: ['.
+        compiler indent.
+        trueBlock value.
+        compiler dedent.
+        falseBlock isNil 	ifTrue: [ compiler addOnLine: '].' ]
+                              	ifFalse: [ compiler add: ']'. ]
+    ].
+    falseBlock isNil ifFalse: [ 
+        compiler addOnLine: ' ifFalse: ['.
+        compiler indent.
+        falseBlock value.
+        compiler dedent.
+        compiler addOnLine: '].'.
+    ].
+    ^ true
 ! !
 
 !PPCTokenizingCodeGenerator methodsFor:'visiting'!
 
+visitAndNode: node
+    | mementoVar currentTokenVar |
+    
+    mementoVar := compiler allocateTemporaryVariableNamed: 'memento'.
+    currentTokenVar := compiler allocateTemporaryVariableNamed: 'currentToken'.
+
+    compiler smartRemember: node child to: mementoVar.
+    compiler codeAssign: '{ currentTokenValue . currentTokenType }.' to: currentTokenVar.
+
+    compiler codeStoreValueOf: [ self visit: node child  ] intoVariable: self retvalVar.
+
+    compiler smartRestore: node child from: mementoVar.
+    compiler codeAssign: '(', currentTokenVar, ' at: 1).' to: 'currentTokenValue'.
+    compiler codeAssign: '(', currentTokenVar, ' at: 2).' to: 'currentTokenType'.
+
+    compiler codeReturn.
+!
+
 visitChoiceNode: node
 "       true ifTrue: [ ^ super visitChoiceNode: node ]."
-    "HACK alert: We are inside token..."
+    | possibleError |
+    possibleError := true.
 
-    (node firstSetWithTokens contains: [ :e | e isTokenNode not ]) ifTrue: [ ^ super visitChoiceNode: node ].
-         
     node children do: [ :child |
         | tokenMethodName |
         
-        child firstSetWithTokens do: [ :first |
-            "For each child, for each first compile this:"
-            tokenMethodName := compiler idFor: first.
-            compiler add: '(self currentTokenTypeIs: ', tokenMethodName storeString, ')'.
-            compiler addOnLine: ' ifTrue: ['.
-            compiler indent.
+        child acceptsEpsilon ifTrue: [  
+            possibleError := false.
             compiler codeStoreValueOf: [ self visit: child ] intoVariable: self retvalVar.
-            compiler add: 'error ifFalse: ['.
-            compiler indent.
-            compiler codeReturn: self retvalVar.
-            compiler dedent.
-            compiler add: '] ifTrue: ['.
-            compiler indent.
-            compiler codeClearError.
-            compiler codeAssign: 'nil.' to: 'currentTokenType'.
-            compiler add: 'context position: currentTokenValue start - 1.'.
-            compiler dedent.
-            compiler add: ']'.
-            compiler dedent.
-            compiler add: '].'
+            compiler codeReturn
+        ] ifFalse: [
+            child firstSetWithTokens do: [ :first |
+                "For each child, for each first compile this:"
+            
+                tokenMethodName := compiler idFor: first.
+                compiler add: '(self ', tokenMethodName asString, ')'.
+                compiler addOnLine: ' ifTrue: ['.
+                compiler indent.
+                    compiler codeStoreValueOf: [ self visit: child ] intoVariable: self retvalVar.
+                    compiler add: 'error ifFalse: ['.
+                    compiler indent.
+                        compiler codeReturn: self retvalVar.
+                    compiler dedent.
+                    compiler add: '] ifTrue: ['.
+                    compiler indent.
+                        compiler codeClearError.
+                        compiler codeAssign: 'nil.' to: 'currentTokenType'.
+                        compiler add: 'context position: currentTokenValue start - 1.'.
+                    compiler dedent.
+                    compiler add: ']'.
+                compiler dedent.
+                compiler add: '].'
+            ]
         ]
     ].
-
-    compiler codeError: 'no choice found'.
+    possibleError ifTrue: [
+        compiler codeError: 'no choice found'.
+    ]
 
     "Modified: / 10-05-2015 / 07:37:53 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
@@ -75,23 +134,19 @@
         | firstSet |
         firstSet := child firstSetWithTokens.
         self assert: firstSet size = 1.
-        dictionary at: child 
-            put: firstSet anyOne.
-            
+        dictionary at: child put: firstSet anyOne.
     ].
     "Tokens are unique"
     self assert: dictionary values asSet size = node children size.
     
-"	currentTokenVar := compiler allocateTemporaryVariableNamed: 'currentToken'.
-    compiler codeAssign: 'self currentTokenType.' to: currentTokenVar.
-"	node children do: [ :child |
+    node children do: [ :child |
         | tokenMethodName |
         tokenMethodName := compiler idFor: (dictionary at: child).
-        compiler add: '(self currentTokenTypeIs: ', tokenMethodName storeString, ')'.
+        compiler add: '(self ', tokenMethodName asString, ')'.
         compiler addOnLine: ' ifTrue: ['.
         compiler indent.
-        compiler codeStoreValueOf: [ self visit: child ] intoVariable: self retvalVar.
-        compiler codeReturn: self retvalVar.
+            compiler codeStoreValueOf: [ self visit: child ] intoVariable: self retvalVar.
+            compiler codeReturn: self retvalVar.
         compiler dedent.
         compiler add: '].'
     ].
@@ -116,7 +171,22 @@
 !
 
 visitTokenConsumeNode: node
+    | id |
+    id := (compiler idFor: node child).
+    compiler add: 'self ', id asString, ' ifTrue: ['.
+        compiler indent.
+        compiler codeAssign: 'nil.' to: 'currentTokenType'.
+        compiler codeReturn: 'currentTokenValue'.
+        compiler dedent.
+    compiler add: '] ifFalse: ['.
+    compiler indent.
+    compiler codeError: id asString, ' expected'.
+    compiler dedent.
+    compiler add: '].'.
+
+"
     compiler codeReturn: 'self consume: ', (compiler idFor: node child) storeString, '.'
+"
 !
 
 visitTokenNode: node
@@ -127,7 +197,6 @@
     self visit: node tokenizer.
     self visit: node whitespace.
     
-"	compiler codeNextToken."
     compiler codeHaltIfShiftPressed.
     compiler codeStoreValueOf: [ self visit: node parser ] intoVariable: self retvalVar.
     compiler codeReturn.