compiler/PPCCodeGenerator.st
changeset 503 ff58cd9f1f3c
parent 500 cf3cbf3933f1
parent 502 1e45d3c96ec5
child 506 e5d63143737f
--- a/compiler/PPCCodeGenerator.st	Fri Jun 19 08:13:39 2015 +0100
+++ b/compiler/PPCCodeGenerator.st	Fri Jul 24 15:37:23 2015 +0100
@@ -9,7 +9,6 @@
 	category:'PetitCompiler-Visitors'
 !
 
-
 !PPCCodeGenerator class methodsFor:'as yet unclassified'!
 
 new
@@ -34,6 +33,88 @@
     ^ arguments guards
 ! !
 
+!PPCCodeGenerator methodsFor:'code generation'!
+
+generateChoiceChildOf: choiceNode atIndex: choiceChildNodeIndex useGuards: useGuards storeResultInto: resultVar
+
+    | children |
+
+    children := choiceNode children.
+    useGuards ifTrue:[
+        self addGuard: (children at: choiceChildNodeIndex) ifTrue: [ 
+                    compiler add: 'self clearError.'.
+                    compiler 
+                          codeAssignParsedValueOf:[ self visit:(children at: choiceChildNodeIndex) ]
+                          to: resultVar.
+                    compiler add: 'error ifFalse: [ '.
+                    compiler codeReturn: resultVar.  
+                    compiler add: ' ].'.
+                ] ifFalse:[ 
+                    compiler add: 'error := true.'.
+                ].
+                compiler add: 'error ifTrue:[ '.
+                choiceChildNodeIndex < children size ifTrue:[ 
+                    self generateChoiceChildOf: choiceNode atIndex: choiceChildNodeIndex + 1 useGuards: useGuards storeResultInto: resultVar.
+                ] ifFalse:[ 
+                    compiler codeError: 'no choice suitable'.
+                ].
+                compiler addOnLine: '].'.
+    
+    ] ifFalse:[ 
+                choiceChildNodeIndex <= children size ifTrue:[ 
+                    compiler add: 'self clearError.'.
+                    compiler 
+                          codeAssignParsedValueOf:[ self visit:(children at: choiceChildNodeIndex) ]
+                          to: resultVar.
+                    compiler add: 'error ifFalse: [ '.
+                    compiler codeReturn: resultVar.  
+                    compiler add: ' ].'.
+                    self generateChoiceChildOf: choiceNode atIndex: choiceChildNodeIndex + 1 useGuards: useGuards storeResultInto: resultVar.
+                ] ifFalse:[ 
+                    compiler codeError: 'no choice suitable'.
+                ].
+    ].
+
+    
+!
+
+generateSequenceChildOf: sequenceNode atIndex: sequenceNodeChildIndex useMememntoVar: mementoVar storeResultInto: elementVars
+        | child childValueVar |
+
+        child := sequenceNode children at: sequenceNodeChildIndex.
+        childValueVar := elementVars at: sequenceNodeChildIndex.
+        compiler codeAssignParsedValueOf: [ self visit:child ] 
+                                      to: childValueVar.
+        child acceptsEpsilon ifFalse: [   
+            compiler codeIfErrorThen: [
+                "Handle error in the first element in a special way,
+                 because one does not need to do backtracking  if the first element fails."
+                (sequenceNodeChildIndex == 1) ifTrue: [                         
+                    compiler codeReturn: 'failure'
+                ] ifFalse: [
+                    compiler smartRestore: sequenceNode from: mementoVar.
+                    compiler codeReturn: 'failure.'.
+                ]
+            ] else:[ 
+                sequenceNode returnParsedObjectsAsCollection ifTrue:[
+                    compiler add: self retvalVar , ' at: ', sequenceNodeChildIndex asString, ' put: ', childValueVar, '.'.
+                ].
+                (sequenceNodeChildIndex < sequenceNode children size) ifTrue:[ 
+                    self generateSequenceChildOf: sequenceNode atIndex: sequenceNodeChildIndex + 1 useMememntoVar: mementoVar storeResultInto: elementVars.
+                ].
+            ]
+
+        ] ifTrue:[
+            sequenceNode returnParsedObjectsAsCollection ifTrue:[
+                compiler add: self retvalVar , ' at: ', sequenceNodeChildIndex asString, ' put: ', childValueVar, '.'.
+            ].
+            (sequenceNodeChildIndex < sequenceNode children size) ifTrue:[ 
+                    self generateSequenceChildOf: sequenceNode atIndex: sequenceNodeChildIndex + 1 useMememntoVar: mementoVar storeResultInto: elementVars.
+
+            ].
+        ]
+! !
+
 !PPCCodeGenerator methodsFor:'guards'!
 
 addGuard: node ifTrue: trueBlock ifFalse: falseBlock
@@ -401,54 +482,13 @@
 !
 
 visitChoiceNode: node
-    |  whitespaceConsumed allowGuard elementVar coding |
-
-
-    elementVar := compiler allocateTemporaryVariableNamed: 'element'.
-    whitespaceConsumed := self addGuardTrimming: node.
-    allowGuard := whitespaceConsumed.
+    |  whitespaceConsumed useGuards resultVar  |
 
-    allowGuard ifTrue:[
-        coding := 
-            [ :children :index |
-                self addGuard: (children at: index) ifTrue: [ 
-                    compiler add: 'self clearError.'.
-                    compiler 
-                          codeAssignParsedValueOf:[ self visit:(children at:index) ]
-                          to:elementVar.
-                    compiler add: 'error ifFalse: [ '.
-                    compiler codeReturn: elementVar.  
-                    compiler add: ' ].'.
-                ] ifFalse:[ 
-                    compiler add: 'error := true.'.
-                ].
-                compiler add: 'error ifTrue:[ '.
-                index < children size ifTrue:[ 
-                    coding value: children value: index + 1.
-                ] ifFalse:[ 
-                    compiler codeError: 'no choice suitable'.
-                ].
-                compiler add: '] '.
-        ]
-    ] ifFalse:[ 
-        coding := 
-            [ :children :index |
-                index <= children size ifTrue:[ 
-                    compiler add: 'self clearError.'.
-                    compiler 
-                          codeAssignParsedValueOf:[ self visit:(children at:index) ]
-                          to:elementVar.
-                    compiler add: 'error ifFalse: [ '.
-                    compiler codeReturn: elementVar.  
-                    compiler add: ' ].'.
-                    coding value: children value: index + 1.
-                ] ifFalse:[ 
-                    compiler codeError: 'no choice suitable'.
-                ].
-            ]
-    ].
-
-    coding value: node children value: 1.
+    resultVar := compiler allocateTemporaryVariableNamed: 'element'.
+    whitespaceConsumed := self addGuardTrimming: node.
+    useGuards := whitespaceConsumed.
+    self generateChoiceChildOf: node atIndex: 1 useGuards: useGuards storeResultInto: resultVar
+    
 
     "Modified: / 29-05-2015 / 07:17:36 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
@@ -462,12 +502,10 @@
     compiler 
           codeAssignParsedValueOf:[ self visit:node child ]
           to:self retvalVar.
-    compiler add: 'context atEnd ifTrue: ['.
-    compiler codeReturn.        
-    compiler add: '] ifFalse: ['.
-    compiler codeError: 'End of input expected'.
-    compiler add: '].'.
-
+    compiler codeIf: 'context atEnd' 
+                then: [ compiler codeReturn ]
+                else: [ compiler codeError: 'End of input expected' ].
+        
     "Modified: / 26-05-2015 / 19:03:09 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 !
 
@@ -762,14 +800,13 @@
 
 visitSequenceNode: node
 
-    | elementVars mementoVar canBacktrack coding |
+    | elementVars mementoVar canBacktrack  |
 
     elementVars := node preferredChildrenVariableNames.
     elementVars do:[:e | 
         compiler allocateTemporaryVariableNamed: e.  
     ].
 
-
     canBacktrack := (node children allButFirst allSatisfy: [:e | e acceptsEpsilon ]) not.
 
 "       self addGuardTrimming: node.
@@ -783,45 +820,7 @@
     node returnParsedObjectsAsCollection ifTrue:[
         compiler codeAssign: 'Array new: ', node children size asString, '.' to: self retvalVar.
     ].
-
-    coding := [ :index |
-        | child childValueVar |
-
-        child := node children at: index.
-        childValueVar := elementVars at: index.
-        compiler codeAssignParsedValueOf: [ self visit:child ] 
-                                      to: childValueVar.
-        child acceptsEpsilon ifFalse: [   
-            compiler codeIfErrorThen: [
-                "Handle error in the first element specially"
-                "TODO: JK, please explain here why!!!!!!"
-                index == 1 ifTrue:[                         
-                    compiler add: 'error ifTrue: [ ^ failure ].'.
-                ] ifFalse:[
-                    compiler smartRestore: node from: mementoVar.
-                    compiler codeReturn: 'failure.'.
-                ]
-            ] else:[ 
-                node returnParsedObjectsAsCollection ifTrue:[
-                    compiler add: self retvalVar , ' at: ', index asString, ' put: ', childValueVar, '.'.
-                ].
-                (index < node children size) ifTrue:[ 
-                    coding value: index + 1.
-                ].
-            ]
-
-        ] ifTrue:[
-            node returnParsedObjectsAsCollection ifTrue:[
-                compiler add: self retvalVar , ' at: ', index asString, ' put: ', childValueVar, '.'.
-            ].
-            (index < node children size) ifTrue:[ 
-                coding value: index + 1.
-            ].
-        ]
-    ].
-
-    coding value:1.
-
+    self generateSequenceChildOf: node atIndex: 1 useMememntoVar: mementoVar storeResultInto: elementVars.
     compiler codeReturn
 
     "Modified (comment): / 16-06-2015 / 06:38:02 / Jan Vrany <jan.vrany@fit.cvut.cz>"
@@ -1051,10 +1050,3 @@
     "Modified: / 15-06-2015 / 17:59:23 / Jan Vrany <jan.vrany@fit.cvut.cz>"
 ! !
 
-!PPCCodeGenerator class methodsFor:'documentation'!
-
-version_HG
-
-    ^ '$Changeset: <not expanded> $'
-! !
-