Ticket #108: modifier-sections.patch
File modifier-sections.patch, 14.3 KB (added by hopscc, 11 years ago) |
---|
-
Source/CobraParser.cobra
100 100 var _lowercaseLetters = 'abcdefghijklmnopqrstuvwxyz' 101 101 var _uppercaseLetters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 102 102 103 var _ isNamesStack as Stack<of String>?103 var _modifierNamesStack as Stack<of String>? 104 104 """ Stack for recording modifier for items in modifier sections (e.g.shared). """ 105 105 106 106 var _boxStack as Stack<of Box>? … … 231 231 tokVerbosity = _verbosity - 4 # in order words, tokenizer does not spew unless our verbosity is 5 or greater 232 232 if tokVerbosity < 0, tokVerbosity = 0 233 233 234 _ isNamesStack = Stack<of String>() # for `shared` for example234 _modifierNamesStack = Stack<of String>() # for `shared` for example 235 235 _leftStack = Stack<of Expr>() 236 236 _opStackStack = Stack<of Stack<of String>>() 237 237 .newOpStack … … 697 697 .throwError('Cannot nest a type underneath a [parentBox.englishName]') # TODO: needs a test case 698 698 699 699 _boxStack.push(theClass) 700 # . isNamesStack = Stack<of String>()700 # .modifierNamesStack = Stack<of String>() 701 701 .bodiedBoxMemberDecls(theClass) 702 702 _boxStack.pop 703 703 … … 780 780 781 781 def _isDeclNamesNoEOL(hasIsNames as out bool) as List<of String> 782 782 """ Parse for possible stream of isNames without terminating EOL. """ 783 names = List<of String>(_ isNamesStack)783 names = List<of String>(_modifierNamesStack) 784 784 hasIsNames = false 785 785 if .optional('IS') is nil 786 786 return names 787 787 hasIsNames = true 788 return _commaSepDeclNames(names) 789 790 def _commaSepDeclNames(names as List<of String>) as List<of String> 791 """ 792 Grab one or a comma separated sequence of declNames/isNames. 793 Verify that the modifier names are valid and internally consistant 794 Returns 795 A string list of the modifierNames/isNames 796 """ 788 797 while true 789 798 what = .grab.text 790 799 if what in .validIsNames … … 801 810 if .peek.text in .validIsNames 802 811 .throwError(.peek, 'Multiple access modifiers should be separated by commas such as "[what], [.peek.text]".') 803 812 break 804 # TODO: error on virtual and shared 813 # error on virtual and shared 814 if 'virtual' in names and 'shared' in names 815 .recordError(.last, 'Cannot specify both "virtual" and "shared".') 805 816 # to-do: move these to _bindInt 806 817 # error on non virtual and override 807 818 if 'nonvirtual' in names and 'override' in names 808 819 .recordError(.last, 'Cannot specify both "nonvirtual" and "override".') 809 # to-do: cannot specify 'new' and 'override' 820 # Cannot specify 'new' and 'override' 821 if 'new' in names and 'override' in names 822 .recordError(.last, 'Cannot specify both "new" and "override".') 810 823 # error if 2 or more of 'public', 'protected', 'private', 'internal' 811 824 accessModifierCount = 0 812 825 for vam in _validAccessModifiers … … 819 832 var _validAccessModifiers = ['public', 'protected', 'private', 'internal'] 820 833 821 834 get validIsNames as List<of String> 835 """ 836 All the valid isNames/DeclNames or modifiers. 837 Some of these are specific to clauses - i.e partial on Types/Class..., readonly on vars 838 """ 822 839 if _validIsNames is nil 823 840 _validIsNames = [ 824 841 'fake', 'extern', 'shared', 'virtual', 'nonvirtual', 'override', 'new', … … 897 914 898 915 # TODO when supporting nested classes, look at the _boxStack and set a back pointer here 899 916 _boxStack.push(theMixin) 900 # . isNamesStack = Stack<of String>()917 # .modifierNamesStack = Stack<of String>() 901 918 .bodiedBoxMemberDecls(theMixin) 902 919 _boxStack.pop 903 920 … … 936 953 theInterface = Interface(wordToken, idToken, name, .makeList<of IType>(genericParams), typeSpecs.isNames, typeSpecs.attributes, typeSpecs.inheritsProxies, docString) 937 954 938 955 _boxStack.push(theInterface) 939 # . isNamesStack = Stack<of String>()956 # .modifierNamesStack = Stack<of String>() 940 957 .bodiedBoxMemberDecls(theInterface) # TODO: this shouldn't be bodiedBoxMemberDecls, right? 941 958 _boxStack.pop 942 959 … … 974 991 .throwError('Cannot nest a type underneath a [parentBox.englishName]') # TODO: needs a test case 975 992 976 993 _boxStack.push(theStruct) 977 # . isNamesStack = Stack<of String>()994 # .modifierNamesStack = Stack<of String>() 978 995 .bodiedBoxMemberDecls(theStruct) 979 996 _boxStack.pop 980 997 … … 988 1005 handlerType = .typeId 989 1006 # ahem, duplicated from .boxVarDecl 990 1007 docString = '' to ? 991 isNames = List<of String>(_ isNamesStack)1008 isNames = List<of String>(_modifierNamesStack) 992 1009 if .peek.which=='IS' 993 1010 isNames = .isDeclNames 994 1011 attribs = .hasAttribs … … 1219 1236 breakLoop = false # cannot use 'break' to stop a 'while' loop in a branch statement. CC? 1220 1237 while not breakLoop 1221 1238 _isTraceOn = true 1222 branch .peek.which 1239 nextWhich = .peek.which 1240 if .peek.text in .validIsNames # shared, protected, etc - lower case not tokenNames 1241 .bodiedBoxMemberDeclNames(box) 1242 continue 1243 branch nextWhich 1223 1244 on 'PASS' 1224 1245 .classPass 1225 1246 breakLoop = true … … 1232 1253 on 'VAR', .addDecl(box, .boxFieldDecl(true)) 1233 1254 on 'CONST', .addDecl(box, .boxFieldDecl(false)) 1234 1255 on 'INVARIANT', .declareInvariant 1235 on 'EOL', .endOfLine1256 on 'EOL', .endOfLine 1236 1257 on 'ENUM', .addDecl(box, .enumDecl) 1237 on 'EVENT', .addDecl(box, .eventDecl) 1238 on 'SIG', .addDecl(box, .declareMethodSig) 1239 on 'SHARED', .bodiedBoxMemberDeclsShared(box) 1240 on 'TEST', .testSection(box) 1258 on 'EVENT',.addDecl(box, .eventDecl) 1259 on 'SIG', .addDecl(box, .declareMethodSig) 1260 on 'TEST', .testSection(box) 1241 1261 on 'CLASS', .addDecl(box, .classDecl) # nested types 1242 1262 on 'STRUCT', .addDecl(box, .structDecl) # nested types 1243 1263 else 1244 branch .peek.text 1264 branch .peek.text 1245 1265 on 'ensure', sugg = 'invariant' 1246 1266 on 'void', sugg = 'def' 1247 1267 else, sugg = '' 1248 if sugg <> '' 1249 sugg = ' Instead of "[.peek.text]", try "[sugg]".' 1268 if sugg <> '', sugg = ' Instead of "[.peek.text]", try "[sugg]".' 1250 1269 .throwError('Got [.peek] when expecting class, def, enum, get, invariant, pro, set, shared, sig, struct, test or var.[sugg]') 1251 1270 .dedent 1252 1271 … … 1258 1277 # TODO: Give another error with the line number of the other definition (and then change message above) 1259 1278 box.addDecl(member) 1260 1279 1261 def bodiedBoxMemberDeclsShared(box as Box) 1262 .expect('SHARED') 1280 def bodiedBoxMemberDeclNames(box as Box) 1281 """ Section for block of common decl/modifier isnames.""" 1282 declModifierNames = _commaSepDeclNames(List<of String>()) 1283 if 'fake' in declModifierNames or 'partial' in declModifierNames 1284 .recordError(.last, 'Cannot have "fake" or "partial" in a modifier block.') 1285 1286 for modName in declModifierNames 1287 _modifierNamesStack.push(modName) 1263 1288 .indent 1264 _isNamesStack.push('shared')1265 1289 try 1266 1290 .bodiedBoxMemberDecls(box) 1267 1291 finally 1268 _isNamesStack.pop 1269 1292 for modName in declModifierNames 1293 _modifierNamesStack.pop 1294 1270 1295 def classPass 1271 1296 if .curBox.declsInOrder.count 1272 1297 _warning('Encountered "pass" in a class that already has declared members.') # TODO: change to an error … … 1299 1324 if type is nil 1300 1325 type = .typeProvider.defaultType 1301 1326 docString = '' to ? 1302 isNames = List<of String>(_ isNamesStack)1327 isNames = List<of String>(_modifierNamesStack) 1303 1328 if .peek.which=='IS' 1304 1329 isNames = .isDeclNames 1305 1330 attribs = .hasAttribs … … 1370 1395 params = _methodParams(opener) 1371 1396 returnType = _methodReturnType 1372 1397 1373 isNames = List<of String>(_ isNamesStack)1398 isNames = List<of String>(_modifierNamesStack) 1374 1399 attribs = AttributeList() 1375 1400 implementsType = nil to ITypeProxy? 1376 1401 … … 1551 1576 if not .optional('INDENT') 1552 1577 # with no indent there can be no additional specs like attributes, contracts or body 1553 1578 if not hasIsNames 1554 isNames = List<of String>(_ isNamesStack)1579 isNames = List<of String>(_modifierNamesStack) 1555 1580 attribs = AttributeList() 1556 1581 docString = '' to ? 1557 1582 else … … 1625 1650 if not isAbstract and curBox.canHaveStatements 1626 1651 .throwError('Missing body for property.') 1627 1652 if not hasIsNames 1628 isNames = List<of String>(_ isNamesStack)1653 isNames = List<of String>(_modifierNamesStack) 1629 1654 attribs = AttributeList() 1630 1655 docString = '' 1631 1656 if params.count … … 1693 1718 docString = .docString 1694 1719 .dedent 1695 1720 else 1696 if not hasIsNames, isNames = List<of String>(_ isNamesStack)1721 if not hasIsNames, isNames = List<of String>(_modifierNamesStack) 1697 1722 attribs = AttributeList() 1698 1723 docString = '' 1699 1724 varDef = _genVarDef(declVarType, token, name, varName, initExpr) … … 1706 1731 possibleVarDef = .curBox.declForName(varName) 1707 1732 if not possibleVarDef 1708 1733 if initExpr or declVarType 1709 varDef = BoxVar(token, token, .curBox, varName, declVarType, List<of String>(_ isNamesStack), initExpr, nil, 'Automatic backing var for property "[name]".')1734 varDef = BoxVar(token, token, .curBox, varName, declVarType, List<of String>(_modifierNamesStack), initExpr, nil, 'Automatic backing var for property "[name]".') 1710 1735 .curBox.addDecl(varDef) 1711 1736 return varDef 1712 1737 if not varName.startsWith('_') or varName.startsWith('__') … … 1782 1807 if not isAbstract and curBox.canHaveStatements 1783 1808 .throwError('Missing body for property.') 1784 1809 if not hasIsNames 1785 isNames = List<of String>(_ isNamesStack)1810 isNames = List<of String>(_modifierNamesStack) 1786 1811 attribs = AttributeList() 1787 1812 docString = '' 1788 1813 if params.count -
Tests/120-classes/450-isnames/502-bad-combo-new-override.cobra
1 class Test 2 def xyzzy is new, override #.error. Cannot specify both 3 pass 4 5 def xyzzy is override, new #.error. Cannot specify both 6 pass 7 8 def main is shared 9 Test().xyzzy -
Tests/120-classes/450-isnames/100-isnames.cobra
1 class Base 2 def foo is shared 3 pass 4 5 def bar is shared 6 .foo 7 8 class Derived inherits Base 9 def main is shared 10 .bar 11 .foo -
Tests/120-classes/450-isnames/500-bad-combo-shared-virtual.cobra
1 class Test 2 def xyzzy is virtual, shared #.error. Cannot specify both 3 pass 4 5 def xyzzy is shared, virtual #.error. Cannot specify both 6 pass 7 8 def main is shared 9 Test().xyzzy -
Tests/120-classes/450-isnames/200-modifier-section.cobra
1 class Base 2 shared 3 def foo 4 pass 5 6 def bar 7 .foo 8 9 class Derived inherits Base 10 def main is shared 11 .bar 12 .foo -
Tests/120-classes/450-isnames/202-modifier-section.cobra
1 class Base 2 private 3 def foo 4 pass 5 6 shared 7 def bar 8 .foo #.error. cannot access instance member "foo" 9 10 class Derived inherits Base 11 def main is shared 12 .bar 13 .foo # .error. Cannot access private "foo" 14 -
Tests/120-classes/450-isnames/204-modifier-section.cobra
1 class Base 2 private, shared 3 def foo 4 pass 5 6 shared 7 def bar 8 .foo 9 10 class Derived inherits Base 11 def main is shared 12 .bar 13 .foo # .error. Cannot access private "foo" 14 -
Tests/120-classes/450-isnames/206-modifier-section.cobra
1 class Base is abstract 2 private, shared 3 def foo 4 pass 5 6 shared 7 def bar 8 .foo 9 10 abstract, protected 11 def brazil 12 13 class Derived inherits Base 14 15 def brazil is override, protected 16 pass 17 18 def main is shared 19 .bar 20 21 d = Derived() 22 d.brazil -
Tests/120-classes/450-isnames/504-bad-combo-access-modifiers.cobra
1 class Test 2 def xyzzy is private, protected #.error. Can only specify one of 3 pass 4 5 def xyzzy1 is private, public #.error. Can only specify one of 6 pass 7 8 def xyzzy2 is protected, public #.error. Can only specify one of 9 pass 10 11 def xyzzy3 is protected, private #.error. Can only specify one of 12 pass 13 14 def xyzzy4 is public, internal #.error. Can only specify one of 15 pass 16 17 def xyzzy5 is private, internal #.error. Can only specify one of 18 pass 19 20 def xyzzy6 is protected, internal #.error. Can only specify one of 21 pass 22 23 def xyzzyAll is internal, protected, private #.error. Can only specify one of 24 pass 25 def xyzzyAll is private, protected, public, internal #.error. Can only specify one of 26 pass 27 28 29 def main is shared 30 Test().xyzzy