Prexonite, a .NET hosted scripting language with a focus on meta-programming and embedded DSLs
0

Configure Feed

Select the types of activity you want to include in your feed.

PRX-32 add detection for ::-instead-of-. in namepsaces

It raises a hard error, but the parser tries its best to recover from the situation.

Christian Klauser (Apr 28, 2021, 12:06 AM +0200) 5e7bcf90 a48de581

+93 -4
+23 -3
Prexonite/Compiler/Grammar/Parser.GlobalScope.atg
··· 932 932 . 933 933 934 934 NsTransferSource<out bool hasWildcard, out QualifiedId qualifiedId> 935 - (. hasWildcard = false; .) 935 + (. hasWildcard = false; 936 + var qualIdPos = GetPosition(); 937 + qualifiedId = new("unknown"); 938 + .) 936 939 = 937 940 NsQualifiedIdImpl<true, out qualifiedId, out hasWildcard> 941 + | GlobalQualifiedId<out var gid> (. // This alternative covers a common but hard to spot mistake (`.` vs `::`) 942 + // It tries to recover, but it's considered a hard error. 943 + Loader.ReportMessage(Message.Error( 944 + Resources.Parser_DoubleColonInNamespaceName, 945 + qualIdPos, MessageClasses.UnexpectedDoubleColonInNamespaceName)); 946 + hasWildcard = false; 947 + qualifiedId = new(gid.Split('.')); 948 + .) 938 949 . 939 950 940 951 NsQualifiedIdImpl<bool allowWildcard, out QualifiedId qualifiedId, out bool hasWildcard> ··· 1091 1102 .) 1092 1103 . 1093 1104 1094 - NamespaceDeclaration (. QualifiedId fullNsId; 1105 + NamespaceDeclaration (. QualifiedId? fullNsId = null; 1095 1106 DeclarationScope scope = null; 1096 1107 ISourcePosition qualIdPos,exportPos; 1097 1108 List<SymbolTransferDirective> directives; ··· 1100 1111 .) 1101 1112 = (. .) 1102 1113 namespace (. qualIdPos = GetPosition(); .) 1103 - NsQualifiedId<out fullNsId> (. var declBuilder = _prepareDeclScope(fullNsId, qualIdPos); .) 1114 + ( NsQualifiedId<out var outNsId> (. fullNsId = outNsId; .) 1115 + | GlobalQualifiedId<out var qid> (. // This alternative captures a common and hard to spot mistake (. vs ::) 1116 + // It tries to recover, but it's considered a hard error. 1117 + Loader.ReportMessage(Message.Error( 1118 + Resources.Parser_DoubleColonInNamespaceName, 1119 + qualIdPos, MessageClasses.UnexpectedDoubleColonInNamespaceName)); 1120 + // Best-effort recovery based on invalid namespace name 1121 + fullNsId = new QualifiedId(qid.Split('.')); 1122 + .) 1123 + ) (. var declBuilder = _prepareDeclScope(fullNsId ?? new QualifiedId("unknown"), qualIdPos); .) 1104 1124 [ (. ISourcePosition importKeywordPosition; 1105 1125 _pushLexerState(Lexer.Transfer); 1106 1126 .)
+1
Prexonite/Compiler/MessageClasses.cs
··· 62 62 public const string UnexpectedWildcard = "P.UnexpectedWildcard"; 63 63 public const string QualifiedIdPartsAfterWildcard = "P.QualifiedIdPartsAfterWildcard"; 64 64 public const string NonTopLevelNamespaceImport = "P.NonTopLevelNamespaceImport"; 65 + public const string UnexpectedDoubleColonInNamespaceName = "P.UnexpectedDoubleColonInNamespaceName"; 65 66 66 67 #endregion 67 68
+3
Prexonite/Properties/Resources.resx
··· 436 436 <data name="MetaEntry_EntryTypeUnknownToString" xml:space="preserve"> 437 437 <value>MetaEntry type {0} does not have a string representation.</value> 438 438 </data> 439 + <data name="Parser_DoubleColonInNamespaceName" xml:space="preserve"> 440 + <value>Double colon (`::`) not allowed in namespace name.</value> 441 + </data> 439 442 </root>
+66 -1
PrexoniteTests/Tests/Translation.cs
··· 1406 1406 name psr.pattern:test/2.0; 1407 1407 "); 1408 1408 } 1409 - 1409 + 1410 + [Test] 1411 + public void ErrorDoubleColonInNamespaceDecl() 1412 + { 1413 + var ldr = CompileInvalid(@" 1414 + namespace a::b { 1415 + function should_be_illegal = null; 1416 + } 1417 + "); 1418 + 1419 + Assert.That(ldr.Errors.Where(m => m.MessageClass == MessageClasses.UnexpectedDoubleColonInNamespaceName), Is.Not.Empty); 1420 + Assert.That(ldr.ErrorCount, Is.EqualTo(1), "Error count"); 1421 + } 1422 + 1423 + [Test] 1424 + public void ErrorDoubleColonInNamespaceImport() 1425 + { 1426 + var ldr = CompileInvalid(@" 1427 + namespace a.b 1428 + { 1429 + function f = null; 1430 + } 1431 + namespace a.c 1432 + import a::b::f 1433 + { 1434 + function should_be_illegal = null; 1435 + } 1436 + "); 1437 + 1438 + Assert.That(ldr.Errors.Where(m => m.MessageClass == MessageClasses.UnexpectedDoubleColonInNamespaceName), Is.Not.Empty); 1439 + Assert.That(ldr.ErrorCount, Is.EqualTo(1), "Error count"); 1440 + } 1441 + 1442 + [Test] 1443 + public void ErrorDoubleColonInGlobalNamespaceImport() 1444 + { 1445 + var ldr = CompileInvalid(@" 1446 + namespace a.b 1447 + { 1448 + function f = null; 1449 + } 1450 + namespace import a::b::f; 1451 + function should_be_illegal = null; 1452 + "); 1453 + 1454 + Assert.That(ldr.Errors.Where(m => m.MessageClass == MessageClasses.UnexpectedDoubleColonInNamespaceName), Is.Not.Empty); 1455 + Assert.That(ldr.ErrorCount, Is.EqualTo(1), "Error count"); 1456 + } 1457 + 1458 + [Test] 1459 + public void ErrorDoubleColonInNamespaceExport() 1460 + { 1461 + var ldr = CompileInvalid(@" 1462 + namespace b.c.d { 1463 + function f = null; 1464 + } 1465 + namespace a 1466 + { 1467 + 1468 + } export b::c; 1469 + "); 1470 + 1471 + Assert.That(ldr.Errors.Where(m => m.MessageClass == MessageClasses.UnexpectedDoubleColonInNamespaceName), Is.Not.Empty); 1472 + Assert.That(ldr.ErrorCount, Is.EqualTo(1), "Error count"); 1473 + } 1474 + 1410 1475 [ContractAnnotation("value:null=>halt")] 1411 1476 private static void _assumeNotNull(object value) 1412 1477 {