Ticket #304: ticket-304-2.patch
File ticket-304-2.patch, 12.0 KB (added by hopscc, 12 years ago) |
---|
-
Source/CobraParser.cobra
114 114 115 115 var _spaceAgnosticIndentLevel as int 116 116 var _spaceAgnosticExprLevel as int 117 var _isContractOnSameLine as bool118 117 119 118 var _isTraceOn as bool 120 119 … … 1925 1924 <any statement 2> 1926 1925 <any statement N> 1927 1926 Example source 1927 require <cond 1> | 1928 1928 require 1929 1929 <cond 1> 1930 1930 <cond N> 1931 ensure <cond 1> | 1931 1932 ensure 1932 1933 <cond 1> 1933 1934 <cond N> 1934 test1935 [test 1935 1936 <any statement 1> 1936 1937 <any statement 2> 1937 <any statement N> 1938 <any statement N>] 1938 1939 [body 1939 1940 <any statement 1> 1940 1941 <any statement 2> … … 1943 1944 Nothing. 1944 1945 Errors 1945 1946 Already encountered "code" block. 1946 Already encountered "test" block.1947 Missing 'body' block 1947 1948 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' 1948 1951 The caller must check whether or not statements were found and issue an error when appropriate. 1949 1952 For example, interface members and abstract members cannot have any statements. 1950 1953 Other members must have at least one. … … 1956 1959 while .peek.which == 'EOL', .grab 1957 1960 if .peek.which.isOneOf('BODY.TEST.REQUIRE.ENSURE.OR.AND.') 1958 1961 # 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 1961 1965 if .peek.which.isOneOf('REQUIRE.OR.') 1966 haveContract, indentedContract = true, _isIndentedContract 1962 1967 .requireSection(codePart) 1963 1968 if .peek.which.isOneOf('ENSURE.AND.') 1969 haveContract, indentedContract = true, _isIndentedContract 1964 1970 .ensureSection(codePart) 1965 1971 while .peek.which == 'TEST' 1972 haveTest = true 1966 1973 .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' 1968 1980 .grab 1969 1981 .indent 1970 1982 _statementsFor(codePart) 1983 .dedent 1971 1984 else 1972 if _isContractOnSameLine 1985 if haveContract 1986 if indentedContract and bodyNeeded 1987 .throwError('Missing BODY keyword. Earlier indented contract clauses [detail]') 1973 1988 _statementsFor(codePart) 1974 1989 else 1975 1990 pass 1976 1991 # There is no body for abstract or interface members. Error checking is done elsewhere. 1977 1992 # .throwError('Expecting `body` section.') 1978 if not _isContractOnSameLine 1979 .dedent 1993 1980 1994 else 1981 1995 # non-sectional 1982 1996 _statementsFor(codePart) … … 1991 2005 # TODO: is the toplevel statement really useful? 1992 2006 _warning('More than 100 lines of code ([codePart.statements.count] toplevel statements) in method [fullName].') 1993 2007 #print '[fullName.padLeft(50)]\t[nLines]\t[codePart.statements.count]' 1994 2008 1995 2009 def _statementsFor(codePart as HasAddStmt) 1996 2010 """ 1997 2011 Utility method for .statementsFor. … … 2438 2452 expr = if(.peek.which == 'EOL', nil, .expression) 2439 2453 return ReturnStmt(token, expr) 2440 2454 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 2441 2462 def requireSection(codeMember as AbstractMethod) as ContractPart 2442 2463 return _requireOrEnsure(codeMember, 'OR', 'REQUIRE', RequirePart) 2443 2464 … … 2447 2468 def _requireOrEnsure(codeMember as AbstractMethod, connectWhich as String, mainWhich as String, theClass as Type) as ContractPart 2448 2469 connectToken = .optional(connectWhich) 2449 2470 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 2451 2472 .indent 2452 2473 exprs = List<of Expr>() 2453 2474 while true … … 2463 2484 # one expression, on the same line 2464 2485 exprs = [.expression] 2465 2486 .endOfLine 2466 _isContractOnSameLine = true2467 2487 return theClass(connectToken, mainToken, codeMember, exprs) to ContractPart 2468 2488 2469 2489 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 2 class 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 2 class 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 2 class 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 2 class 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 2 class 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 2 class 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 2 class 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 2 class 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'