help-smalltalk
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Help-smalltalk] [PATCH 3/3] stinst: rewrite parsing of literal arrays a


From: Paolo Bonzini
Subject: [Help-smalltalk] [PATCH 3/3] stinst: rewrite parsing of literal arrays and fix compilation of ##(...) within arrays
Date: Tue, 7 Jan 2014 12:35:57 +0100

packages/stinst/parser:
2014-01-07  Paolo Bonzini  <address@hidden>

        * RBParser.st: Move parsing of literal arrays to RBParser.  The
        scanner now returns just a RBLiteralArrayStartToken.
        * RBToken.st: Add RBLiteralArrayStartToken.
        * RewriteTests.st: Do not inspect the RBLiteralNode that is
        returned in TestFormat>>#testArrayRewrite, this will be covered
        by the parser tests.
        * RBScannerTests.st: Add tests for ##(...).
        * RBParserTests.st: Add more literal array tests.
---
 packages/stinst/parser/ChangeLog         |  11 +++
 packages/stinst/parser/RBParser.st       | 132 ++++++++++++++++++++-----------
 packages/stinst/parser/RBParserTests.st  |  42 ++++++++--
 packages/stinst/parser/RBScannerTests.st |  53 +++++++++++++
 packages/stinst/parser/RBToken.st        |  23 ++++++
 packages/stinst/parser/RewriteTests.st   |   2 -
 6 files changed, 208 insertions(+), 55 deletions(-)

diff --git a/packages/stinst/parser/ChangeLog b/packages/stinst/parser/ChangeLog
index a1c35cb..9f44c4d 100644
--- a/packages/stinst/parser/ChangeLog
+++ b/packages/stinst/parser/ChangeLog
@@ -1,5 +1,16 @@
 2014-01-07  Paolo Bonzini  <address@hidden>
 
+       * RBParser.st: Move parsing of literal arrays to RBParser.  The
+       scanner now returns just a RBLiteralArrayStartToken.
+       * RBToken.st: Add RBLiteralArrayStartToken.
+       * RewriteTests.st: Do not inspect the RBLiteralNode that is
+       returned in TestFormat>>#testArrayRewrite, this will be covered
+       by the parser tests.
+       * RBScannerTests.st: Add tests for ##(...).
+       * RBParserTests.st: Add more literal array tests.
+
+2014-01-07  Paolo Bonzini  <address@hidden>
+
        * RBFormatter.st: Add #acceptLiteralArrayNode:.
        * RBParseNodes.st: Implement RBLiteralArrayNode.
 
diff --git a/packages/stinst/parser/RBParser.st 
b/packages/stinst/parser/RBParser.st
index b953762..99b8d2b 100644
--- a/packages/stinst/parser/RBParser.st
+++ b/packages/stinst/parser/RBParser.st
@@ -538,9 +538,8 @@ Object subclass: RBParser [
     parseNegatedNumber [
        <category: 'private-parsing'>
        | token |
-       self step.
        token := currentToken.
-       (token value respondsTo: #negated) ifFalse: [
+       token value isNumber ifFalse: [
            ^self parserError: 'Number expected' ].
        token value negative ifTrue: [
            ^self parserError: 'Positive number expected' ].
@@ -562,17 +561,96 @@ Object subclass: RBParser [
        currentToken isIdentifier ifTrue: [^self parsePrimitiveIdentifier].
        currentToken isLiteral ifTrue: [^self parsePrimitiveLiteral].
        (currentToken isBinary and: [ currentToken value == #- ])
-           ifTrue: [^self parseNegatedNumber].
+           ifTrue: [^self step; parseNegatedNumber].
        currentToken isSpecial 
            ifTrue: 
                [currentToken value == $[ ifTrue: [^self parseBlock].
                currentToken value == ${ ifTrue: [^self parseArrayConstructor].
                currentToken value == $( ifTrue: [^self 
parseParenthesizedExpression]].
+       currentToken isLiteralArrayStart ifTrue: [^self parseLiteralArray].
        currentToken isPatternBlock ifTrue: [^self parsePatternBlock].
        currentToken isOptimized ifTrue: [^self parseOptimizedExpression].
        self parserError: 'Variable expected'
     ]
 
+    parseLiteralArray [
+       <category: 'private-parsing'>
+       | arrayStream start stop |
+       arrayStream := WriteStream on: (Array new: 10).
+       start := currentToken start.
+       self step.
+
+       [currentToken isSpecial and: [currentToken value == $)]]
+               whileFalse: 
+                   [arrayStream nextPut: self parseLiteralArrayParts].
+       stop := currentToken stop.
+       self step.
+       ^RBLiteralArrayNode 
+           left: start
+           nodes: arrayStream contents
+           right: stop
+    ]
+
+    parseByteArray [
+        "FIXME: it's ugly that this is both here for #( [1 2 3] )
+         and in RBScanner for #[1 2 3]."
+       <category: 'private-parsing'>
+       | byteStream number start stop |
+       byteStream := WriteStream on: (ByteArray new: 100).
+       start := currentToken start.
+
+       [self step.
+       currentToken isLiteral] whileTrue: 
+                   [number := currentToken value.
+                   (number isInteger and: [number between: 0 and: 255]) 
+                       ifFalse: [self scannerError: 'Expecting 8-bit integer'].
+                   byteStream nextPut: number].
+        (currentToken isSpecial and: [ currentToken value == $] ])
+             ifFalse: [self scannerError: ''']'' expected'].
+       stop := currentToken stop.
+       self step.      "]"
+       ^RBLiteralNode literalToken: (RBLiteralToken 
+           value: byteStream contents
+           start: start
+           stop: stop)
+    ]
+
+    parseLiteralArrayParts [
+       <category: 'private-parsing'>
+       currentToken isLiteral ifTrue: [^self parsePrimitiveLiteral].
+       currentToken isIdentifier
+           ifTrue: 
+               [| token value |
+               token := currentToken.
+               value := self parsePrimitiveIdentifier.
+               value isVariable ifTrue: [
+                   value := RBLiteralNode literalToken: (RBLiteralToken
+                           value: token value asSymbol
+                           start: token start
+                           stop: token stop)].
+               ^value].
+       currentToken isBinary
+           ifTrue: [
+                | token |
+                token := currentToken.
+                self step.
+                (token value == #- and: [token stop + 1 = currentToken start 
and: [
+                    currentToken isLiteral and: [
+                    currentToken value isNumber and: [
+                    currentToken value positive ]]]]) ifTrue: [^self 
parseNegatedNumber].
+                ^RBLiteralNode literalToken: (RBLiteralToken
+                           value: token value
+                           start: token start
+                           stop: token stop)].
+       currentToken isSpecial 
+           ifTrue: 
+               [currentToken value == $[ ifTrue: [^self parseByteArray].
+               currentToken value == $( ifTrue: [^self parseLiteralArray]].
+       currentToken isLiteralArrayStart ifTrue: [^self parseLiteralArray].
+       currentToken isOptimized ifTrue: [^self parseOptimizedExpression].
+       ^self parserError: 'literal array element expected'
+    ]
+
     parseResourceTag [
        <category: 'private-parsing'>
        | start |
@@ -1206,57 +1284,15 @@ Stream subclass: RBScanner [
        characterType == #binary 
            ifTrue: [^(self scanBinary: RBLiteralToken) stop: self 
previousStepPosition].
        currentCharacter == $' ifTrue: [^self scanStringSymbol].
-       currentCharacter == $( ifTrue: [^self scanLiteralArray].
+       currentCharacter == $( ifTrue: [
+                self step.
+                ^RBLiteralArrayStartToken start: tokenStart].
        currentCharacter == $[ ifTrue: [^self scanByteArray].
        currentCharacter == ${ ifTrue: [^self scanQualifier].
        currentCharacter == $# ifTrue: [^self scanExtendedLiterals].
        self scannerError: 'Expecting a literal type'
     ]
 
-    scanLiteralArray [
-       <category: 'private-scanning'>
-       | arrayStream start |
-       arrayStream := WriteStream on: (Array new: 10).
-       self step.
-       start := tokenStart.
-       
-       [self stripSeparators.
-       tokenStart := stream position.
-       currentCharacter == $)] 
-               whileFalse: 
-                   [arrayStream nextPut: self scanLiteralArrayParts.
-                   buffer reset].
-       self step.
-       ^RBLiteralToken 
-           value: arrayStream contents
-           start: start
-           stop: self previousStepPosition
-    ]
-
-    scanLiteralArrayParts [
-       <category: 'private-scanning'>
-       currentCharacter == $# ifTrue: [^self scanLiteral].
-       characterType == #alphabetic 
-           ifTrue: 
-               [| token value |
-               token := self scanSymbol.
-               value := token value.
-               value == #nil ifTrue: [token value: nil].
-               value == #true ifTrue: [token value: true].
-               value == #false ifTrue: [token value: false].
-               ^token].
-       (characterType == #digit 
-           or: [currentCharacter == $- and: [(self classify: stream peek) == 
#digit]]) 
-               ifTrue: [^self scanNumber].
-       characterType == #binary 
-           ifTrue: [^(self scanBinary: RBLiteralToken) stop: self 
previousStepPosition].
-       currentCharacter == $' ifTrue: [^self scanLiteralString].
-       currentCharacter == $$ ifTrue: [^self scanLiteralCharacter].
-       currentCharacter == $( ifTrue: [^self scanLiteralArray].
-       currentCharacter == $[ ifTrue: [^self scanByteArray].
-       ^self scannerError: 'Unknown character in literal array'
-    ]
-
     scanLiteralCharacter [
        <category: 'private-scanning'>
        | token value char tokenStop |
diff --git a/packages/stinst/parser/RBParserTests.st 
b/packages/stinst/parser/RBParserTests.st
index f569821..f0df0d1 100644
--- a/packages/stinst/parser/RBParserTests.st
+++ b/packages/stinst/parser/RBParserTests.st
@@ -58,14 +58,46 @@ TestCase subclass: TestParser [
     ]
 
     testLiteralArrayParsing [
-        | node |
+        | node nested |
 
         node := RBParser parseExpression: '#(-3 -2 -16r1)'.
-        self assert: node value first = -3.
-        self assert: node value second = -2.
-        self assert: node value third = -1.
+        self assert: node nodes first value = -3.
+        self assert: node nodes second value = -2.
+        self assert: node nodes third value = -1.
 
         node := RBParser parseExpression: '#(16r-1)'.
-        self assert: node value first = -1.
+        self assert: node nodes first value = -1.
+
+        node := RBParser parseExpression: '#(- 2)'.
+        self assert: node nodes first value = #-.
+        self assert: node nodes second value = 2.
+
+        node := RBParser parseExpression: '#(true false nil foo)'.
+        self assert: node nodes first value = true.
+        self assert: node nodes second value = false.
+        self assert: node nodes third value = nil.
+        self assert: node nodes fourth value = #foo.
+
+        node := RBParser parseExpression: '#(1 #[2 3] 4)'.
+        self assert: node nodes first value = 1.
+        self assert: node nodes second value = #[2 3].
+        self assert: node nodes third value = 4.
+
+        node := RBParser parseExpression: '#(1 [2 3] 4)'.
+        self assert: node nodes first value = 1.
+        self assert: node nodes second value = #[2 3].
+        self assert: node nodes third value = 4.
+
+        node := RBParser parseExpression: '#(1 (2 3) 4)'.
+        self assert: node nodes first value = 1.
+        nested := node nodes second.
+        self assert: nested nodes first value = 2.
+        self assert: nested nodes second value = 3.
+        self assert: node nodes third value = 4.
+
+        node := RBParser parseExpression: '#(1 ##(2/3) 4)'.
+        self assert: node nodes first value = 1.
+        self assert: node nodes second class == RBOptimizedNode.
+        self assert: node nodes third value = 4.
     ]
 ]
diff --git a/packages/stinst/parser/RBScannerTests.st 
b/packages/stinst/parser/RBScannerTests.st
index 41ecfd9..451e876 100644
--- a/packages/stinst/parser/RBScannerTests.st
+++ b/packages/stinst/parser/RBScannerTests.st
@@ -46,5 +46,58 @@ TestCase subclass: TestScanner [
         num := scanner next.
         self assert: num value = 3.
     ]
+
+    testEmbeddedCompiletimeConstant [
+        | scanner token value |
+        scanner := RBScanner on: '#(##(1))' readStream.
+
+        "Token is the literal"
+        token := scanner next.
+        self assert: token isLiteralArrayStart.
+
+        "Token is for optimized code"
+        token := scanner next.
+        self assert: token isOptimized.
+
+        "Token is the '1'"
+        token := scanner next.
+        self assert: token isLiteral.
+        self assert: token value equals: 1.
+
+        "Token is the ')'"
+        token := scanner next.
+        self assert: token isSpecial.
+        self assert: token value equals: $).
+
+        "Token is the ')'"
+        token := scanner next.
+        self assert: token isSpecial.
+        self assert: token value equals: $).
+
+        "And we are at the end"
+        self assert: scanner atEnd.
+    ]
+
+    testDirectCompiletimeConstant [
+        | scanner token |
+        scanner := RBScanner on: '##(1)' readStream.
+
+        "Token is for optimized code"
+        token := scanner next.
+        self assert: token isOptimized.
+
+        "Token is the '1'"
+        token := scanner next.
+        self assert: token isLiteral.
+        self assert: token value equals: 1.
+
+        "Token is the ')'"
+        token := scanner next.
+        self assert: token isSpecial.
+        self assert: token value equals: $).
+
+        "And we are at the end"
+        self assert: scanner atEnd.
+    ]
 ]
 
diff --git a/packages/stinst/parser/RBToken.st 
b/packages/stinst/parser/RBToken.st
index 399a6db..7c22c9c 100644
--- a/packages/stinst/parser/RBToken.st
+++ b/packages/stinst/parser/RBToken.st
@@ -95,6 +95,11 @@ Object subclass: RBToken [
        ^false
     ]
 
+    isLiteralArrayStart [
+       <category: 'testing'>
+       ^false
+    ]
+
     isOptimized [
        <category: 'testing'>
        ^false
@@ -391,6 +396,24 @@ RBValueToken subclass: RBKeywordToken [
 
 
 
+RBToken subclass: RBLiteralArrayStartToken [
+    
+    <category: 'Refactory-Scanner'>
+    <comment: nil>
+
+    isLiteralArrayStart [
+       <category: 'testing'>
+       ^true
+    ]
+
+    length [
+       <category: 'testing'>
+       ^2
+    ]
+]
+
+
+
 RBToken subclass: RBOptimizedToken [
     
     <category: 'Refactory-Scanner'>
diff --git a/packages/stinst/parser/RewriteTests.st 
b/packages/stinst/parser/RewriteTests.st
index 322ac38..05130a4 100644
--- a/packages/stinst/parser/RewriteTests.st
+++ b/packages/stinst/parser/RewriteTests.st
@@ -273,8 +273,6 @@ TestCase subclass: TestFormat [
     testArrayRewrite [
        | inp res |
        inp := RBParser parseExpression: '#(16r01 2r01 16rFF )'.
-       self assert: inp value = (Array with: 1 with: 1 with: 255).
-
        res := RBFormatter new formatAll: (Array with: inp).
        self assert: res = '#(16r01 2r01 16rFF)'.
     ]
-- 
1.8.4.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]