Wiki

Ticket #304: ticket-304-2.patch

File ticket-304-2.patch, 12.0 KB (added by hopscc, 12 years ago)
  • Source/CobraParser.cobra

     
    114114 
    115115    var _spaceAgnosticIndentLevel as int 
    116116    var _spaceAgnosticExprLevel as int 
    117     var _isContractOnSameLine as bool 
    118117 
    119118    var _isTraceOn as bool 
    120119 
     
    19251924            <any statement 2> 
    19261925            <any statement N> 
    19271926        Example source 
     1927            require <cond 1> | 
    19281928            require 
    19291929                <cond 1> 
    19301930                <cond N> 
     1931            ensure <cond 1>  |   
    19311932            ensure 
    19321933                <cond 1> 
    19331934                <cond N> 
    1934             test 
     1935            [test 
    19351936                <any statement 1> 
    19361937                <any statement 2> 
    1937                 <any statement N> 
     1938                <any statement N>] 
    19381939            [body 
    19391940                <any statement 1> 
    19401941                <any statement 2> 
     
    19431944            Nothing. 
    19441945        Errors 
    19451946            Already encountered "code" block. 
    1946             Already encountered "test" block. 
     1947            Missing 'body' block 
    19471948        Notes 
     1949            If have 'test' blocks or indented 'ensure' or 'require' blocks must also have 'body' code block 
     1950            May (now) have multiple 'test' blocks' 
    19481951            The caller must check whether or not statements were found and issue an error when appropriate. 
    19491952            For example, interface members and abstract members cannot have any statements. 
    19501953            Other members must have at least one. 
     
    19561959            while .peek.which == 'EOL', .grab 
    19571960            if .peek.which.isOneOf('BODY.TEST.REQUIRE.ENSURE.OR.AND.') 
    19581961                # sectional 
    1959                 # not flexible. sequence is signature, contract, test, implementation 
    1960                 _isContractOnSameLine = false 
     1962                # not flexible. sequence is signature, contracts, tests, implementation body 
     1963                # if have indented contract or test blocks, must also have an explicit body block 
     1964                haveContract = haveTest = indentedContract = false 
    19611965                if .peek.which.isOneOf('REQUIRE.OR.') 
     1966                    haveContract, indentedContract = true, _isIndentedContract 
    19621967                    .requireSection(codePart) 
    19631968                if .peek.which.isOneOf('ENSURE.AND.') 
     1969                    haveContract, indentedContract = true, _isIndentedContract 
    19641970                    .ensureSection(codePart) 
    19651971                while .peek.which == 'TEST' 
     1972                    haveTest = true  
    19661973                    .testSection(codePartContainingTest to !) 
    1967                 if .peek.which=='BODY' 
     1974 
     1975                bodyNeeded = not codePart.bodyExclusion      
     1976                detail='mandate that the body code also be indented. You need the "body" keyword with indented code following it.'       
     1977                if haveTest and .peek.which <> 'BODY' 
     1978                    .throwError('Missing BODY keyword. Earlier (indented) "test" clauses [detail]')      
     1979                if .peek.which == 'BODY' 
    19681980                    .grab 
    19691981                    .indent 
    19701982                    _statementsFor(codePart) 
     1983                    .dedent 
    19711984                else 
    1972                     if _isContractOnSameLine 
     1985                    if haveContract  
     1986                        if indentedContract and bodyNeeded 
     1987                            .throwError('Missing BODY keyword. Earlier indented contract clauses [detail]') 
    19731988                        _statementsFor(codePart) 
    19741989                    else 
    19751990                        pass 
    19761991                        # There is no body for abstract or interface members. Error checking is done elsewhere. 
    19771992                        # .throwError('Expecting `body` section.') 
    1978                 if not _isContractOnSameLine 
    1979                     .dedent 
     1993 
    19801994            else 
    19811995                # non-sectional 
    19821996                _statementsFor(codePart) 
     
    19912005                    # TODO: is the toplevel statement really useful? 
    19922006                    _warning('More than 100 lines of code ([codePart.statements.count] toplevel statements) in method [fullName].')  
    19932007                #print '[fullName.padLeft(50)]\t[nLines]\t[codePart.statements.count]' 
    1994  
     2008                 
    19952009    def _statementsFor(codePart as HasAddStmt) 
    19962010        """ 
    19972011        Utility method for .statementsFor. 
     
    24382452        expr = if(.peek.which == 'EOL', nil, .expression) 
    24392453        return ReturnStmt(token, expr) 
    24402454 
     2455    def _isIndentedContract as bool 
     2456        require .peek.which.isOneOf('REQUIRE.ENSURE.OR.AND.') 
     2457        ofst=0 
     2458        if .peek(ofst).which.isOneOf('.OR.AND.'),        ofst +=1 
     2459        if .peek(ofst).which.isOneOf('REQUIRE.ENSURE.'), ofst += 1 
     2460        return .peek(ofst).which.isOneOf('EOL.COLON.')  # code must be indented 
     2461         
    24412462    def requireSection(codeMember as AbstractMethod) as ContractPart 
    24422463        return _requireOrEnsure(codeMember, 'OR', 'REQUIRE', RequirePart) 
    24432464 
     
    24472468    def _requireOrEnsure(codeMember as AbstractMethod, connectWhich as String, mainWhich as String, theClass as Type) as ContractPart 
    24482469        connectToken = .optional(connectWhich) 
    24492470        mainToken = .expect(mainWhich) 
    2450         if .peek.which.isOneOf('EOL.COLON.') 
     2471        if .peek.which.isOneOf('EOL.COLON.')  # TODO: COLON here should throw a not-needed-warning  
    24512472            .indent 
    24522473            exprs = List<of Expr>() 
    24532474            while true 
     
    24632484            # one expression, on the same line 
    24642485            exprs = [.expression] 
    24652486            .endOfLine 
    2466             _isContractOnSameLine = true 
    24672487        return theClass(connectToken, mainToken, codeMember, exprs) to ContractPart 
    24682488 
    24692489    def throwStmt as Stmt 
  • Tests/340-contracts/093-parse-tests-fail.cobra

     
     1# test the main the variants of contract layout - looking for parsing errors 
     2class ContractParsing 
     3             
     4    # we allow this - 1 line contract, non indented or keyworded body 
     5    def dedent1(x as int) as char 
     6        require x < 3 
     7        return c'z' 
     8         
     9             
     10    def dedent2c(x as int) as char 
     11        require  
     12            x < 3 
     13        #test 
     14        #   assert true 
     15        # indented clause after keyword no body keyword, no body code 
     16             
     17    def main is shared      # .error. missing BODY 
     18        c = ContractParsing() 
     19        assert c.dedent1(1) == c'z' 
     20        assert c.dedent2c(2) == c'z' 
  • Tests/340-contracts/095-parse-tests-fail.cobra

     
     1# test the main the variants of contract layout - looking for parsing errors 
     2class ContractParsing 
     3             
     4    # we allow this - 1 line contract, non indented or keyworded body 
     5    def dedent1(x as int) as char 
     6        require x < 3 
     7        return c'z' 
     8         
     9    def dedent4(x as int) as char 
     10        require x < 3 
     11        test 
     12            assert true 
     13        #No 'body' 
     14        return c'z' #.error. missing BODY 
     15         
     16             
     17    def main is shared 
     18        c = ContractParsing() 
     19        assert c.dedent1(1) == c'z' 
     20        assert c.dedent4(1) == c'z' 
  • Tests/340-contracts/097-parse-tests-fail.cobra

     
     1# test the main the variants of contract layout - looking for parsing errors 
     2class ContractParsing 
     3             
     4    # we allow this - 1 line contract, non indented or keyworded body 
     5    def dedent1(x as int) as char 
     6        require x < 3 
     7        return c'z' 
     8     
     9    def dedent5(x as int) as char 
     10        #require x < 3 
     11        test 
     12            assert true 
     13        #no body/indented body code 
     14        return c'z' # .error. missing BODY 
     15         
     16             
     17    def main is shared 
     18        c = ContractParsing() 
     19        assert c.dedent1(1) == c'z' 
     20        assert c.dedent5(1) == c'z' 
  • Tests/340-contracts/091-parse-tests-maybe.cobra

     
     1# test the main the variants of contract layout - looking for parsing errors 
     2class ContractParsing 
     3             
     4    # we allow this - 1 line contract, non indented or keyworded body 
     5    def dedent1(x as int) as char 
     6        require x < 3 
     7        return c'z' 
     8         
     9    #should we allow this even though body not necessary? 
     10    def dedent2a(x as int) as char 
     11        require x < 3 
     12        body    # optional body 
     13            return c'z' 
     14             
     15    def main is shared 
     16        c = ContractParsing() 
     17        assert c.dedent1(1) == c'z' 
     18        assert c.dedent2a(2) == c'z' 
  • Tests/340-contracts/092-parse-tests-fail.cobra

     
     1# test the main the variants of contract layout - looking for parsing errors 
     2class ContractParsing 
     3             
     4    # we allow this - 1 line contract, non indented or keyworded body 
     5    def dedent1(x as int) as char 
     6        require x < 3 
     7        c = c'z' 
     8        return c 
     9         
     10 
     11    def dedent2a(x as int) as char 
     12        require  
     13            x < 3 
     14        #test 
     15        #   assert true 
     16        # indented contract clause keyword, no body keyword  
     17        return c'z' #.error. Missing BODY 
     18         
     19             
     20    def main is shared 
     21        c = ContractParsing() 
     22        assert c.dedent1(1) == c'z' 
     23        assert c.dedent2a(2) == c'z' 
  • Tests/340-contracts/090-parse-test.cobra

     
     1# test the main variants of contract layout - these should be all OK 
     2class ContractParsing 
     3    # this was the failure case 
     4    def dedentError(x as int) as char 
     5        require x < 3 
     6        test 
     7            assert true 
     8        body 
     9            return c'z' 
     10    # to here 
     11         
     12    # contract and test clauses 
     13    def dedent1(x as int) as char 
     14        require  
     15            x < 3 
     16        test 
     17            assert true 
     18        body 
     19            return c'z' 
     20 
     21    # 1 stmt contract and unindented body only       
     22    def dedent2(x as int) as char 
     23        require x < 3 
     24        #test 
     25        #   assert true 
     26        return c'z' 
     27 
     28    #should we allow this even though body not necessary? 
     29    def dedent2a(x as int) as char 
     30        require x < 3 
     31        body   
     32            return c'z' 
     33             
     34    # no test clause 
     35    def dedent3(x as int) as char 
     36        require  
     37            x < 3 
     38        #test 
     39        #   assert true 
     40        # indented contract clause must also have keyword and indented body 
     41        body 
     42            return c'z' 
     43             
     44    def dedent3a(x as int) as char 
     45        require  
     46            x < 3 
     47        body 
     48            return c'z' 
     49 
     50         
     51    # no contract 
     52    def dedent4(x as int) as char 
     53        #require x < 3 
     54        test 
     55            assert true 
     56        body 
     57            return c'z' 
     58         
     59    def dedent4a(x as int) as char 
     60        test 
     61            assert true 
     62        body 
     63            return c'z' 
     64             
     65    # stmt(s) only - none of contract/test or body 
     66    def noDedent(x as int) as char 
     67        return c'z' 
     68         
     69    def main is shared 
     70        c = ContractParsing() 
     71        assert c.dedentError(1) == c'z' 
     72        assert c.dedent1(1)  == c'z' 
     73        assert c.dedent2(1)  == c'z' 
     74        assert c.dedent2a(1)  == c'z' 
     75        assert c.dedent3(2)  == c'z' 
     76        assert c.dedent3a(2) == c'z' 
     77        assert c.dedent4(1)  == c'z' 
     78        assert c.dedent4a(1) == c'z' 
     79        assert c.noDedent(1) == c'z' 
  • Tests/340-contracts/094-parse-tests-fail.cobra

     
     1# test the main the variants of contract layout - looking for parsing errors 
     2class ContractParsing 
     3             
     4    # we allow this - 1 line contract, non indented or keyworded body 
     5    def dedent1(x as int) as char 
     6        require x < 3 
     7        return c'z' 
     8         
     9         
     10    def dedent3a(x as int) as char 
     11        require  
     12            x < 3 
     13        test 
     14            assert true 
     15        #no 'body' 
     16        return c'z' #.error. missing BODY 
     17         
     18             
     19    def main is shared 
     20        c = ContractParsing() 
     21        assert c.dedent1(1) == c'z' 
     22        assert c.dedent3a(2) == c'z' 
  • Tests/340-contracts/096-parse-tests-fail.cobra

     
     1# test the main the variants of contract layout - looking for parsing errors 
     2class ContractParsing 
     3             
     4    # we allow this - 1 line contract, non indented or keyworded body 
     5    def dedent1(x as int) as char 
     6        require x < 3 
     7        return c'z' 
     8         
     9         
     10    def dedent4a(x as int) as char 
     11        require  
     12            x < 3 
     13        test 
     14            assert true 
     15        #no body 
     16        return c'z' #.error. missing BODY 
     17         
     18             
     19    def main is shared 
     20        c = ContractParsing() 
     21        assert c.dedent1(1) == c'z' 
     22        assert c.dedent4a(2) == c'z'