Ticket #31: implicitLineContInParens.patch

File implicitLineContInParens.patch, 10.0 kB (added by hopscc, 6 months ago)
  • Source/CobraParser.cobra

     
    100100        var _curCodePart as AbstractMethod? 
    101101 
    102102        var _spaceAgnosticIndentLevel as int 
     103        var _spaceAgnosticExprLevel as int 
    103104        var _isContractOnSameLine as bool 
    104105 
    105106        var _isTraceOn as bool 
     
    11891190                        hasIsNames = true 
    11901191                else 
    11911192                        .endOfLine 
    1192                 if not .optional('INDENT') 
    1193                         # with no indent there can be no additional specs like attributes, contracts or body 
     1193 
     1194                if _noMoreSpecs()   
     1195                        # No additional specs like attributes, contracts or body 
    11941196                        nothingMore = true 
    11951197                        if not hasIsNames 
    11961198                                isNames = List<of String>(_isNamesStack) 
     
    12391241                else 
    12401242                        return method 
    12411243 
     1244        def _noMoreSpecs as bool 
     1245                """ 
     1246                Return a bool indicating that there is no (correctly indented) additional specs  
     1247                like attributes, contracts or body following. 
     1248                """ 
     1249                noMoreSpecs = false 
     1250                if _spaceAgnosticIndentLevel == 0                       # paramdecls all on same line  
     1251                        noMoreSpecs = not .optional('INDENT')   # Anything else must be indented 
     1252                else 
     1253                        #print "[name] sail=[_spaceAgnosticIndentLevel] " 
     1254                        sail = _spaceAgnosticIndentLevel 
     1255                        if sail > 0 
     1256                                _spaceAgnosticIndentLevel -= 1  # for missing indent 
     1257                        _finishSpaceAgnostic 
     1258                        if sail >= 1 
     1259                                noMoreSpecs =  .optional('DEDENT') <> nil  
     1260                        else 
     1261                                noMoreSpecs = not .optional('INDENT') 
     1262 
     1263                #print "noMoreSpex=[noMoreSpecs]" 
     1264                return noMoreSpecs       
     1265                                 
     1266                                 
    12421267        def declareMethodSig as MethodSig 
    12431268                require _typeProvider 
    12441269                token = .expect('SIG') 
     
    15301555        ## 
    15311556 
    15321557        def paramDecls(skipParen as bool) as List<of Param> 
    1533                 return .paramDecls(skipParen, 'RPAREN') 
     1558                return .paramDecls(skipParen, 'RPAREN', true) 
    15341559 
    15351560        def paramDecls(skipParen as bool, rightParen as String) as List<of Param> 
     1561                return .paramDecls(skipParen, rightParen, false)  
     1562                 
     1563        def paramDecls(skipParen as bool, rightParen as String, isSpaceAgnostic as bool) as List<of Param> 
    15361564                if not skipParen 
    15371565                        .expect('LPAREN') 
    15381566                params = List<of Param>() 
    15391567                expectComma = false 
    15401568                while true 
     1569                        if isSpaceAgnostic 
     1570                                _spaceAgnostic 
    15411571                        if .peek.which==rightParen 
    15421572                                .grab 
    15431573                                break 
    15441574                        if expectComma 
    15451575                                .expect('COMMA') 
     1576                        if isSpaceAgnostic 
     1577                                _spaceAgnostic 
    15461578                        param = .paramDecl 
    15471579                        params.add(param) 
    15481580                        if params.count==1 and param.name=='self' and param.isMissingType 
     
    23632395                        _inExpression += 1 
    23642396                        try 
    23652397                                expr = .expression(0, nil) 
    2366                                 if expr.isParened 
     2398                                if expr.isParened and expr.token.lineNum == .last.lineNum 
    23672399                                        _warning(expr.token, 'Unnecessary parentheses around expression. You can remove them.') 
    23682400                                return expr 
    23692401                        finally 
     
    23982430                                if not PostCallExpr.isTargetAcceptable(left to !) 
    23992431                                        .throwError('Unexpected call.')  # example: t = x to List<of String>() 
    24002432                                token = .grab 
     2433                                #exprs = .commaSepExprs(['RPAREN'], true, false) 
    24012434                                exprs = .commaSepExprs('RPAREN') 
    24022435                                return .expression(precedence, PostCallExpr(token, left, exprs)) 
    24032436                        else 
     
    24442477                return left to ! 
    24452478 
    24462479        def expression2 as Expr 
     2480                if _spaceAgnosticExprLevel > 0 #and .peek.which in ['EOL','INDENT','DEDENT'] 
     2481                        _spaceAgnostic 
    24472482                peekToken = .peek 
    24482483                peek = peekToken.which 
    24492484                if _unaryOpPrec.containsKey(peek) 
     
    24602495                # TODO: make a branch statement 
    24612496                else if peek=='LPAREN' 
    24622497                        .grab 
     2498                        _spaceAgnosticExprLevel += 1 
    24632499                        node = .expression(0, nil) 
    24642500                        .expect('RPAREN') 
     2501                        _spaceAgnosticExprLevel -= 1 
    24652502                        node.isParened = true 
    24662503                        return node 
    24672504                else if peek=='DOT' 
     
    25442581                                return .typeExpr 
    25452582                        catch pe as ParserException 
    25462583                                if pe.message.contains('Unrecognized type') 
    2547                                         msg = 'Expecting an expression.' 
     2584                                        ofst = pe.message.indexOf('Unrecognized type') 
     2585                                        submsg = pe.message[ofst:] 
     2586                                        msg = '[submsg] Expecting an expression.' 
    25482587                                        if peekToken.isKeyword 
    25492588                                                msg += ' "[peekToken.text]" is a reserved keyword that is not expected here.' 
    25502589                                        .throwError(msg) 
     
    25622601                branch token.which 
    25632602                        on 'OPEN_CALL' 
    25642603                                assert not callName.endsWith('(') 
    2565                                 args = .commaSepExprs(['RPAREN'], false, true) 
     2604                                args = .commaSepExprs(['RPAREN'], true, true) # false, true) 
    25662605                                return CallExpr(token, callName, args) 
    25672606                        on 'OPEN_GENERIC' 
    25682607                                assert not callName.endsWith('<of') and not callName.endsWith('<') 
     
    25752614                                                on 'GT', isDone = true 
    25762615                                                else, .throwError('Unexpected token [.last] in type arguments.') 
    25772616                                .expect('LPAREN') 
    2578                                 args = .commaSepExprs(['RPAREN'], false, true) 
     2617                                args = .commaSepExprs(['RPAREN'], true, true) #false, true) 
    25792618                                return CallExpr(token, callName, typeArgs, args) 
    25802619                        else 
    25812620                                throw FallThroughException(token)                                
     
    31983237                                        _spaceAgnosticIndentLevel -= 1 
    31993238                                        continue 
    32003239                        break 
     3240                if _verbosity>=5 
     3241                        print '<> spaceAgnostic level=[_spaceAgnosticIndentLevel]' 
    32013242 
    32023243        def _finishSpaceAgnostic 
    32033244                """ 
  • Tests/110-basics-two/920-space-agnostic-expr.cobra

     
     1# Simple Test for implicit line continuation in paren delimited expressions 
     2 
     3namespace Test 
     4        class SpaceAgnostic 
     5         
     6                def main is shared 
     7                        i = (100 + 1 + 2 + 
     8                                3 + 4) 
     9                        #print i 
     10                        assert i == 110 
     11                        s = ('a very long line of text ' + 
     12                                'another long line') 
     13                        #print s 
     14                        assert s == 'a very long line of text another long line' 
     15                         
     16                        i = (100 + 1 + 2 + 
     17                                        3 + 4) 
     18                        assert i == 110 
     19                                         
     20                        # TODO add more 
  • Tests/110-basics-two/910-space-agnostic-method.cobra

     
     1# Simple Test for implicit line continuation in method call arglists  and  
     2# method param declarations 
     3# if this fails it probably wont compile 
     4namespace Test 
     5        class SpaceAgnostic 
     6         
     7                def main is shared 
     8                        CobraCore.tracer.isActive = false 
     9                        .foo('foo argument Number 1', 
     10                                'arg2', 
     11                                'areg3' ) 
     12                                 
     13                        .foo2('foo2 argument Number 1', 
     14                                        'argument Number 2', 
     15                                        'argument Number THree reg3' ) 
     16                                 
     17                        .foo3('foo3 argument Number 1', 
     18                                                'argument Number 2',  
     19                                                'argument Number THree reg3' ) 
     20 
     21                        .foo4('foo4 argument Number 1',  
     22                        'argument Number 2',  
     23                        'argument Number THree reg3' ) 
     24 
     25                        .foo5('foo5 argument Number 1',  
     26                'argument Number 2',  
     27                        'argument Number THree reg3' ) 
     28                         
     29                        .foo6('foo6 argument Number 1',  
     30                                        'argument Number 2',  
     31                                'argument Number THree reg3' ) 
     32                         
     33                        .foo7('foo7 argument Number 1',  
     34                                                'argument Number 2',  
     35                        'argument Number THree reg3' ) 
     36                        # thats it for calls 
     37                 
     38                def foo(arg1 as String, arg2 as String, arg3 as String) is shared 
     39                        assert arg1.length 
     40                        #print 'foo done' 
     41                         
     42                def foo2(arg1 as String,  
     43                                arg2 as String,  
     44                                arg3 as String  ) is shared 
     45                        assert arg1.length 
     46                        trace arg1 
     47                        assert arg1.length 
     48                        trace arg2 
     49                        assert arg2.length 
     50                        trace arg3 
     51                        assert arg3.length 
     52                        #print 'foo2 done' 
     53                 
     54                def foo2a(arg1 as String,  
     55                                        arg2 as String,  
     56                                        arg3 as String  ) is shared 
     57                        assert arg1.length 
     58                        trace arg1 
     59                        assert arg1.length 
     60                        trace arg2 
     61                        assert arg2.length 
     62                        trace arg3 
     63                        assert arg3.length 
     64                        #print 'foo2a done' 
     65                         
     66                def foo3(arg1 as String,  
     67                        arg2 as String,  
     68                        arg3 as String  ) is shared 
     69                        assert arg1.length 
     70                        trace arg1 
     71                        assert arg1.length 
     72                        trace arg2 
     73                        assert arg2.length 
     74                        trace arg3 
     75                        assert arg3.length 
     76                        #print 'foo3 done' 
     77                 
     78                # pathological (0) 
     79                def foo4(arg1 as String,  
     80                arg2 as String,  
     81                arg3 as String  ) is shared 
     82                        assert arg1.length 
     83                        #print "in foo4" 
     84                        trace arg1 
     85                        assert arg1.length 
     86                        trace arg2 
     87                        assert arg2.length 
     88                        trace arg3 
     89                        assert arg3.length 
     90                        #print 'foo4 done' 
     91                 
     92                # pathological (+1) 
     93                def foo5(arg1 as String,  
     94        arg2 as String,  
     95        arg3 as String  ) is shared 
     96                        #print "in foo5" 
     97                        trace arg1 
     98                        assert arg1.length 
     99                        trace arg2 
     100                        assert arg2.length 
     101                        trace arg3 
     102                        assert arg3.length 
     103                        #print 'foo5 done' 
     104                 
     105                # pathological (++1) 
     106                def foo6(arg1 as String,  
     107arg2 as String,  
     108arg3 as String  ) is shared 
     109                        trace arg1 
     110                        assert arg1.length 
     111                        trace arg2 
     112                        assert arg2.length 
     113                        trace arg3 
     114                        assert arg3.length 
     115                        #print 'foo6 done' 
     116                 
     117                def foo7(arg1 as String,  
     118                                                arg2 as String,  
     119                                                arg3 as String  ) is shared 
     120                        trace arg1 
     121                        assert arg1.length 
     122                        trace arg2 
     123                        assert arg2.length 
     124                        trace arg3 
     125                        assert arg3.length 
     126                        #print 'foo7 done' 
     127                         
     128        class AbX  
     129                is abstract      
     130 
     131                def aa(arg1 as String) is abstract 
     132                         
     133                def ab(arg1 as String,   
     134                                        arg2 as String) is abstract 
     135                def ac(arg1 as String, 
     136                        arg2 as String) is abstract 
     137                         
     138                def ad(arg1 as String, 
     139                arg2 as String) is abstract 
     140         
     141                def ad1(arg1 as String, 
     142        arg2 as String) is abstract 
     143                 
     144                def ae(arg1 as String, 
     145                        arg2 as String) is abstract 
  • Developer/IntermediateReleaseNotes.text

     
    11Post 0.8 
    22 
     3* Added support for implicit line continuation for items in parentheses. 
     4 i.e method call argument lists, method declaration parameters and  
     5     parenthesised expressions. 
     6 
    37* Added a new built-in doc tool accessible via "cobra -doc ...". The documentation is generated to local HTML files using your declarations, doc strings, contracts, etc. 
    48 
    59* Add support for specifying unsigned integers as Hex literals