1 // 2 // Copyright (c) 2010-2023 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using System; 8 using System.Linq; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.PlatformDescription; 11 using Antmicro.Renode.PlatformDescription.Syntax; 12 using NUnit.Framework; 13 using Sprache; 14 using System.Text; 15 16 namespace Antmicro.Renode.UnitTests.PlatformDescription 17 { 18 [TestFixture] 19 public class ParserTests 20 { 21 [Test] ShouldParseEmptyFile()22 public void ShouldParseEmptyFile() 23 { 24 var source = string.Empty; 25 26 var result = Grammar.Description(GetInputFromString(source)); 27 Assert.IsTrue(result.WasSuccessful, result.ToString()); 28 } 29 30 [Test] ShouldParseUsingEntry()31 public void ShouldParseUsingEntry() 32 { 33 var source = @" 34 using ""file.pl8"" 35 using ""other_file.pl8"""; 36 37 var input = GetInputFromString(source); 38 var result = Grammar.Description(input); 39 Assert.IsTrue(result.WasSuccessful, result.ToString()); 40 41 var usingEntries = result.Value.Usings.Select(x => x.Path.Value); 42 CollectionAssert.AreEquivalent(new[] { "file.pl8", "other_file.pl8" }, usingEntries); 43 } 44 45 [Test] ShouldParseSimpleEntry()46 public void ShouldParseSimpleEntry() 47 { 48 var source = @" 49 uart: UART"; 50 var result = Grammar.Description(GetInputFromString(source)); 51 Assert.IsTrue(result.WasSuccessful, result.ToString()); 52 53 var entry = result.Value.Entries.Single(); 54 Assert.AreEqual("uart", entry.VariableName); 55 Assert.AreEqual("UART", (string)entry.Type); 56 } 57 58 [Test] ShouldParseEntryWithSimpleRegistrationInfo()59 public void ShouldParseEntryWithSimpleRegistrationInfo() 60 { 61 var source = @" 62 uart: @ sysbus"; 63 var result = Grammar.Description(GetInputFromString(source)); 64 Assert.IsTrue(result.WasSuccessful, result.ToString()); 65 66 var entry = result.Value.Entries.Single(); 67 Assert.AreEqual("uart", entry.VariableName); 68 Assert.IsNull(entry.Type); 69 Assert.AreEqual("sysbus", entry.RegistrationInfos.Single().Register.Value); 70 Assert.IsNull(entry.RegistrationInfos.Single().RegistrationPoint); 71 } 72 73 [Test] ShouldParseEntryWithRangeRegistrationPoint()74 public void ShouldParseEntryWithRangeRegistrationPoint() 75 { 76 var source = @" 77 uart: @ sysbus <0x2000A000, +0x1000>"; 78 var result = Grammar.Description(GetInputFromString(source)); 79 Assert.IsTrue(result.WasSuccessful, result.ToString()); 80 81 var entry = result.Value.Entries.Single(); 82 Assert.AreEqual("uart", entry.VariableName); 83 Assert.IsNull(entry.Type); 84 Assert.AreEqual("sysbus", entry.RegistrationInfos.Single().Register.Value); 85 Assert.AreEqual(0x2000A000.By(0x1000), ((RangeValue)entry.RegistrationInfos.Single().RegistrationPoint).ToRange()); 86 } 87 88 [Test] ShouldParseEntryWithStringRegistrationPoint()89 public void ShouldParseEntryWithStringRegistrationPoint() 90 { 91 var source = @" 92 uart: @ sysbus ""something"""; 93 var result = Grammar.Description(GetInputFromString(source)); 94 Assert.IsTrue(result.WasSuccessful, result.ToString()); 95 96 var entry = result.Value.Entries.Single(); 97 Assert.AreEqual("uart", entry.VariableName); 98 Assert.IsNull(entry.Type); 99 Assert.AreEqual("sysbus", entry.RegistrationInfos.Single().Register.Value); 100 Assert.AreEqual("something", ((StringValue)entry.RegistrationInfos.Single().RegistrationPoint).Value); 101 } 102 103 [Test] ShouldParseEntryWithManyRegistrationPoints()104 public void ShouldParseEntryWithManyRegistrationPoints() 105 { 106 var source = @" 107 uart: @{ sysbus 0x100; 108 sysbus 0x200}"; 109 var result = Grammar.Description(GetInputFromString(source)); 110 Assert.IsTrue(result.WasSuccessful, result.ToString()); 111 112 var entry = result.Value.Entries.Single(); 113 Assert.AreEqual("uart", entry.VariableName); 114 Assert.IsNull(entry.Type); 115 var registrationInfos = entry.RegistrationInfos.ToArray(); 116 Assert.AreEqual("sysbus", registrationInfos[0].Register.Value); 117 Assert.AreEqual("0x100", ((NumericalValue)registrationInfos[0].RegistrationPoint).Value); 118 119 Assert.AreEqual("sysbus", registrationInfos[1].Register.Value); 120 Assert.AreEqual("0x200", ((NumericalValue)registrationInfos[1].RegistrationPoint).Value); 121 } 122 123 [Test] ShouldParseEntryWithOneAttribute()124 public void ShouldParseEntryWithOneAttribute() 125 { 126 var source = @" 127 uart: 128 baudRate: BaudRate.B9600 129 "; 130 var result = Grammar.Description(GetInputFromString(source)); 131 Assert.IsTrue(result.WasSuccessful, result.ToString()); 132 133 var entry = result.Value.Entries.Single(); 134 Assert.AreEqual("uart", entry.VariableName); 135 Assert.IsNull(entry.Type); 136 137 var attribute = (ConstructorOrPropertyAttribute)entry.Attributes.Single(); 138 Assert.AreEqual("baudRate", attribute.Name); 139 Assert.AreEqual("B9600", ((EnumValue)attribute.Value).Value); 140 } 141 142 [Test] ShouldParseEntryWithTwoAttributes()143 public void ShouldParseEntryWithTwoAttributes() 144 { 145 var source = @" 146 uart: 147 friendlyName: ""some name"" 148 size: 0x1000 149 "; 150 151 var result = Grammar.Description(GetInputFromString(source)); 152 Assert.IsTrue(result.WasSuccessful, result.ToString()); 153 154 var entry = result.Value.Entries.Single(); 155 var attributes = entry.Attributes; 156 Assert.AreEqual(2, attributes.Count()); 157 } 158 159 [Test] ShouldParseEntryWithAllAttributes()160 public void ShouldParseEntryWithAllAttributes() 161 { 162 var source = @" 163 uart: 164 model: ""ABC666"" 165 numberOfBits: 32 166 sleepTime: 0.01 167 friendUart: otherUart 168 range: <0x1000, +0x100> 169 "; 170 var result = Grammar.Description(GetInputFromString(source)); 171 Assert.IsTrue(result.WasSuccessful, result.ToString()); 172 173 var entry = result.Value.Entries.Single(); 174 var attributes = entry.Attributes.Cast<ConstructorOrPropertyAttribute>().ToDictionary(x => x.Name, x => x.Value); 175 Assert.AreEqual(5, attributes.Count); 176 Assert.AreEqual("ABC666", ((StringValue)attributes["model"]).Value); 177 Assert.AreEqual("32", ((NumericalValue)attributes["numberOfBits"]).Value); 178 Assert.AreEqual("0.01", ((NumericalValue)attributes["sleepTime"]).Value); 179 Assert.AreEqual("otherUart", ((ReferenceValue)attributes["friendUart"]).Value); 180 Assert.AreEqual(0x1000.By(0x100), ((RangeValue)attributes["range"]).ToRange()); 181 } 182 183 [Test] ShouldParseEntryWithSimpleIrqEntries()184 public void ShouldParseEntryWithSimpleIrqEntries() 185 { 186 var source = @" 187 uart: 188 1 -> pic@2 189 IRQ -> pic@3 190 -> pic@4"; 191 192 var result = Grammar.Description(GetInputFromString(source)); 193 Assert.IsTrue(result.WasSuccessful, result.ToString()); 194 195 var entry = result.Value.Entries.Single(); 196 var attributes = entry.Attributes.Cast<IrqAttribute>().ToArray(); 197 Assert.AreEqual(1, attributes[0].Sources.Single().Ends.Single().Number); 198 Assert.AreEqual("pic", attributes[0].Destinations.ElementAt(0).DestinationPeripheral.Reference.Value); 199 Assert.AreEqual(2, attributes[0].Destinations.ElementAt(0).Destinations.Single().Ends.Single().Number); 200 Assert.AreEqual("IRQ", attributes[1].Sources.Single().Ends.Single().PropertyName); 201 Assert.IsNull(attributes[2].Sources); 202 } 203 204 [Test] ShouldParseEntryWithSimpleMultiplexedIrqEntries()205 public void ShouldParseEntryWithSimpleMultiplexedIrqEntries() 206 { 207 var source = @" 208 uart: 209 1 -> pic@2 | pic1@3 210 -> pic2@4 | pic3@5 211 IRQ -> pic4@6 | pic5@7 | pic6@8 | pic7@9"; 212 213 var result = Grammar.Description(GetInputFromString(source)); 214 Assert.IsTrue(result.WasSuccessful, result.ToString()); 215 216 var entry = result.Value.Entries.Single(); 217 var attributes = entry.Attributes.Cast<IrqAttribute>().ToArray(); 218 219 Assert.AreEqual(1, attributes[0].Sources.Single().Ends.Single().Number); 220 Assert.AreEqual(2, attributes[0].Destinations.ElementAt(0).Destinations.ElementAt(0).Ends.ElementAt(0).Number); 221 Assert.AreEqual("pic", attributes[0].Destinations.ElementAt(0).DestinationPeripheral.Reference.Value); 222 Assert.AreEqual(3, attributes[0].Destinations.ElementAt(1).Destinations.ElementAt(0).Ends.ElementAt(0).Number); 223 Assert.AreEqual("pic1", attributes[0].Destinations.ElementAt(1).DestinationPeripheral.Reference.Value); 224 225 Assert.IsNull(attributes[1].Sources); 226 Assert.AreEqual(4, attributes[1].Destinations.ElementAt(0).Destinations.ElementAt(0).Ends.ElementAt(0).Number); 227 Assert.AreEqual("pic2", attributes[1].Destinations.ElementAt(0).DestinationPeripheral.Reference.Value); 228 Assert.AreEqual(5, attributes[1].Destinations.ElementAt(1).Destinations.ElementAt(0).Ends.ElementAt(0).Number); 229 Assert.AreEqual("pic3", attributes[1].Destinations.ElementAt(1).DestinationPeripheral.Reference.Value); 230 231 Assert.AreEqual("IRQ", attributes[2].Sources.ElementAt(0).Ends.ElementAt(0).PropertyName); 232 Assert.AreEqual(4, attributes[2].Destinations.Count()); 233 } 234 235 [Test] ShouldParseEntryWithMultiplexedMultiIrqEntries()236 public void ShouldParseEntryWithMultiplexedMultiIrqEntries() 237 { 238 var source = @" 239 uart: 240 [1-2, IRQ] -> pic0@[4-6] | pic1@[7-8, 9] | pic2@[10, 11, 12]"; 241 242 var result = Grammar.Description(GetInputFromString(source)); 243 Assert.IsTrue(result.WasSuccessful, result.ToString()); 244 245 var entry = result.Value.Entries.Single(); 246 var attribute = entry.Attributes.Cast<IrqAttribute>().Single(); 247 248 var flattenedSources = attribute.Sources.SelectMany(x => x.Ends).ToArray(); 249 Assert.AreEqual(1, flattenedSources[0].Number); 250 Assert.AreEqual(2, flattenedSources[1].Number); 251 Assert.AreEqual("IRQ", flattenedSources[2].PropertyName); 252 Assert.AreEqual(3, flattenedSources.Count()); 253 254 Assert.AreEqual("pic0", attribute.Destinations.ElementAt(0).DestinationPeripheral.Reference.Value); 255 Assert.AreEqual(flattenedSources.Count(), attribute.Destinations.ElementAt(0).Destinations.SelectMany(x => x.Ends).Count()); 256 Assert.AreEqual(4, attribute.Destinations.ElementAt(0).Destinations.ElementAt(0).Ends.ElementAt(0).Number); 257 Assert.AreEqual(5, attribute.Destinations.ElementAt(0).Destinations.ElementAt(0).Ends.ElementAt(1).Number); 258 Assert.AreEqual(6, attribute.Destinations.ElementAt(0).Destinations.ElementAt(0).Ends.ElementAt(2).Number); 259 260 Assert.AreEqual("pic1", attribute.Destinations.ElementAt(1).DestinationPeripheral.Reference.Value); 261 Assert.AreEqual(flattenedSources.Count(), attribute.Destinations.ElementAt(1).Destinations.SelectMany(x => x.Ends).Count()); 262 Assert.AreEqual(7, attribute.Destinations.ElementAt(1).Destinations.ElementAt(0).Ends.ElementAt(0).Number); 263 Assert.AreEqual(8, attribute.Destinations.ElementAt(1).Destinations.ElementAt(0).Ends.ElementAt(1).Number); 264 Assert.AreEqual(9, attribute.Destinations.ElementAt(1).Destinations.ElementAt(1).Ends.ElementAt(0).Number); 265 266 Assert.AreEqual("pic2", attribute.Destinations.ElementAt(2).DestinationPeripheral.Reference.Value); 267 Assert.AreEqual(flattenedSources.Count(), attribute.Destinations.ElementAt(2).Destinations.SelectMany(x => x.Ends).Count()); 268 Assert.AreEqual(10, attribute.Destinations.ElementAt(2).Destinations.ElementAt(0).Ends.ElementAt(0).Number); 269 Assert.AreEqual(11, attribute.Destinations.ElementAt(2).Destinations.ElementAt(1).Ends.ElementAt(0).Number); 270 Assert.AreEqual(12, attribute.Destinations.ElementAt(2).Destinations.ElementAt(2).Ends.ElementAt(0).Number); 271 } 272 273 [Test] ShouldParseEntryWithMultiIrqEntries()274 public void ShouldParseEntryWithMultiIrqEntries() 275 { 276 var source = @" 277 uart: 278 [1-3, IRQ] -> pic @ [2-5]"; 279 280 var result = Grammar.Description(GetInputFromString(source)); 281 Assert.IsTrue(result.WasSuccessful, result.ToString()); 282 283 var entry = result.Value.Entries.Single(); 284 var attribute = entry.Attributes.Cast<IrqAttribute>().Single(); 285 var flattenedSources = attribute.Sources.SelectMany(x => x.Ends).ToArray(); 286 var flattenedDestinations = attribute.Destinations.ElementAt(0).Destinations.SelectMany(x => x.Ends).ToArray(); 287 Assert.AreEqual(1, flattenedSources[0].Number); 288 Assert.AreEqual(2, flattenedSources[1].Number); 289 Assert.AreEqual(3, flattenedSources[2].Number); 290 Assert.AreEqual("IRQ", flattenedSources[3].PropertyName); 291 292 Assert.AreEqual(2, flattenedDestinations[0].Number); 293 Assert.AreEqual(3, flattenedDestinations[1].Number); 294 Assert.AreEqual(4, flattenedDestinations[2].Number); 295 Assert.AreEqual(5, flattenedDestinations[3].Number); 296 } 297 298 [Test] ShouldParseEntryWithLocalIrqReceiver()299 public void ShouldParseEntryWithLocalIrqReceiver() 300 { 301 var source = @" 302 uart: 303 1 -> something#3@2"; 304 305 var result = Grammar.Description(GetInputFromString(source)); 306 Assert.IsTrue(result.WasSuccessful, result.ToString()); 307 308 var entry = result.Value.Entries.Single(); 309 var attribute = entry.Attributes.OfType<IrqAttribute>().Single(); 310 Assert.AreEqual(1, attribute.Sources.Single().Ends.Single().Number); 311 Assert.AreEqual("something", attribute.Destinations.ElementAt(0).DestinationPeripheral.Reference.Value); 312 Assert.AreEqual(3, attribute.Destinations.ElementAt(0).DestinationPeripheral.LocalIndex); 313 Assert.AreEqual(2, attribute.Destinations.ElementAt(0).Destinations.Single().Ends.Single().Number); 314 } 315 316 [Test] ShouldParseInitAttributeWithOneLine()317 public void ShouldParseInitAttributeWithOneLine() 318 { 319 var source = @" 320 uart: 321 init: 322 DoSomething 3 323 "; 324 var result = Grammar.Description(GetInputFromString(source)); 325 Assert.IsTrue(result.WasSuccessful, result.ToString()); 326 327 var onlyLine = ((InitAttribute)result.Value.Entries.Single().Attributes.Single()).Lines.Single(); 328 Assert.AreEqual("DoSomething 3", onlyLine); 329 } 330 331 [Test] ShouldParseInitAttributeWithMoreLines()332 public void ShouldParseInitAttributeWithMoreLines() 333 { 334 var source = @" 335 uart: 336 init: 337 Method1 a b 338 Method2 true 339 Method3"; 340 341 var result = Grammar.Description(GetInputFromString(source)); 342 Assert.IsTrue(result.WasSuccessful, result.ToString()); 343 344 var lines = ((InitAttribute)result.Value.Entries.Single().Attributes.Single()).Lines.ToArray(); 345 Assert.AreEqual("Method1 a b", lines[0]); 346 Assert.AreEqual("Method2 true", lines[1]); 347 Assert.AreEqual("Method3", lines[2]); 348 } 349 350 [Test] ShouldParseInitAttributeWithSemicolonInQuotes()351 public void ShouldParseInitAttributeWithSemicolonInQuotes() 352 { 353 var source = @" 354 uart: 355 init: 356 CallMethod ""string ; with semicolon"" 357 "; 358 var result = Grammar.Description(GetInputFromString(source)); 359 Assert.IsTrue(result.WasSuccessful, result.ToString()); 360 361 var lines = ((InitAttribute)result.Value.Entries.Single().Attributes.Single()).Lines.ToArray(); 362 Assert.AreEqual("CallMethod \"string ; with semicolon\"", lines.Single()); 363 } 364 365 [Test] ShouldParseObjectValue()366 public void ShouldParseObjectValue() 367 { 368 var source = @" 369 display: Display 370 resolution: new Point 371 x: 640 372 y: 480 373 "; 374 375 var result = Grammar.Description(GetInputFromString(source)); 376 Assert.IsTrue(result.WasSuccessful, result.ToString()); 377 378 var objectValue = ((ObjectValue)((ConstructorOrPropertyAttribute)result.Value.Entries.Single().Attributes.Single()).Value); 379 Assert.AreEqual("Point", (string)objectValue.TypeName); 380 var attributes = objectValue.Attributes.Cast<ConstructorOrPropertyAttribute>().ToDictionary(x => x.Name, x => x.Value); 381 Assert.AreEqual(2, attributes.Count); 382 Assert.AreEqual("640", ((NumericalValue)attributes["x"]).Value); 383 Assert.AreEqual("480", ((NumericalValue)attributes["y"]).Value); 384 } 385 386 [Test] ShouldParseTwoEntries()387 public void ShouldParseTwoEntries() 388 { 389 var source = @" 390 uart1: UART @ sysbus <0x1000, +0x100> 391 someProperty: someValue 392 393 uart2: UART @ sysbus <0x2000, +0x100> 394 otherProperty: ""otherValue"" 395 "; 396 var result = Grammar.Description(GetInputFromString(source)); 397 Assert.IsTrue(result.WasSuccessful, result.ToString()); 398 399 Assert.AreEqual(2, result.Value.Entries.Count()); 400 } 401 402 [Test] ShouldParseLocalAndNonLocalEntry()403 public void ShouldParseLocalAndNonLocalEntry() 404 { 405 var source = @" 406 peripheral: SomeHub 407 local other: Other"; 408 409 var result = Grammar.Description(GetInputFromString(source)); 410 Assert.IsTrue(result.WasSuccessful, result.ToString()); 411 412 var entries = result.Value.Entries.ToArray(); 413 Assert.IsFalse(entries[0].IsLocal); 414 Assert.IsTrue(entries[1].IsLocal); 415 } 416 417 [Test] ShouldHandlePrefixedUsing()418 public void ShouldHandlePrefixedUsing() 419 { 420 var source = @" 421 using ""file1"" 422 using ""file2"" prefixed ""prefix_"""; 423 424 var result = Grammar.Description(GetInputFromString(source)); 425 Assert.IsTrue(result.WasSuccessful, result.ToString()); 426 427 var usings = result.Value.Usings.ToArray(); 428 Assert.AreEqual("file1", usings[0].Path.Value); 429 Assert.AreEqual("file2", usings[1].Path.Value); 430 Assert.IsNull(usings[0].Prefix); 431 Assert.AreEqual("prefix_", usings[1].Prefix); 432 } 433 434 [Test] ShouldParseExample()435 public void ShouldParseExample() 436 { 437 var source = @" 438 screen: Display@graphicsCard1 439 resolution: new Point { x: 5; y: 6 } 440 refreshMode: Automatic 441 model: ""SuperDisplay"" 442 -> ic@3 443 init: 444 DrawCircle 20 20 445 DrawCircle 30 40 446 447 screen: 448 init: 449 DrawRect 40 50 1 450 451 screen: 452 init: 453 base init 454 DrawRect 40 50 1 455 456 other: Display @ sysbus <0x0, +0x100> { refreshMode: Automatic; -> ic@3 } 457 "; 458 459 var result = Grammar.Description(GetInputFromString(source)); 460 Assert.IsTrue(result.WasSuccessful, result.ToString()); 461 } 462 463 [Test] ShouldParseTwoShortEntries()464 public void ShouldParseTwoShortEntries() 465 { 466 var source = @" 467 uart: UART 468 469 uart: @sysbus <0x100, +0x100> 470 "; 471 472 var result = Grammar.Description(GetInputFromString(source)); 473 Assert.IsTrue(result.WasSuccessful, result.ToString()); 474 475 Assert.AreEqual(2, result.Value.Entries.Count()); 476 } 477 478 [Test] ShouldParseUsingAndEntry()479 public void ShouldParseUsingAndEntry() 480 { 481 var source = @" 482 using ""other_file"" 483 484 device: SomeDevice"; 485 486 var result = Grammar.Description(GetInputFromString(source)); 487 Assert.IsTrue(result.WasSuccessful, result.ToString()); 488 489 var usingEntry = result.Value.Usings.First(); 490 Assert.AreEqual("other_file", usingEntry.Path.Value); 491 var entry = result.Value.Entries.First(); 492 Assert.AreEqual("device", entry.VariableName); 493 Assert.AreEqual("SomeDevice", entry.Type.Value); 494 } 495 496 [Test] ShouldParseBool()497 public void ShouldParseBool() 498 { 499 var source = @" 500 device: Something @ somewhere 501 BoolProp: true 502 BoolProp2: false 503 "; 504 505 var result = Grammar.Description(GetInputFromString(source)); 506 Assert.IsTrue(result.WasSuccessful, result.ToString()); 507 508 var values = result.Value.Entries.Single().Attributes.OfType<ConstructorOrPropertyAttribute>() 509 .Select(x => x.Value).OfType<BoolValue>().ToArray(); 510 Assert.AreEqual(2, values.Length); 511 Assert.AreEqual(true, values[0].Value); 512 Assert.AreEqual(false, values[1].Value); 513 } 514 515 [Test] ShouldParseWithMixedLineEndings()516 public void ShouldParseWithMixedLineEndings() 517 { 518 var source = new StringBuilder(); 519 source.Append("peripheral: SomeHub"); 520 source.Append("\n"); 521 source.Append("local first_other: Other"); 522 source.Append("\r\n"); 523 source.Append("local second_other: Other"); 524 source.Append("\r\n"); 525 526 var result = Grammar.Description(GetInputFromString(source.ToString())); 527 Assert.IsTrue(result.WasSuccessful, result.ToString()); 528 } 529 530 [Test] ShouldParseStringWithEscapedBackslashes()531 public void ShouldParseStringWithEscapedBackslashes() 532 { 533 var source = @" 534 uart: 535 string: ""\\escaped backslash: \\, two in a row: \\\\, before quote: \\\"", and one at the end: \\"" 536 "; 537 var result = Grammar.Description(GetInputFromString(source)); 538 Assert.IsTrue(result.WasSuccessful, result.ToString()); 539 540 var entry = result.Value.Entries.Single(); 541 Assert.AreEqual("uart", entry.VariableName); 542 Assert.IsNull(entry.Type); 543 544 var attribute = (ConstructorOrPropertyAttribute)entry.Attributes.Single(); 545 Assert.AreEqual("string", attribute.Name); 546 Assert.AreEqual(@"\escaped backslash: \, two in a row: \\, before quote: \"", and one at the end: \", ((StringValue)attribute.Value).Value); 547 } 548 549 private static IInput GetInputFromString(string source) 550 { 551 var result = PreLexer.Process(source); 552 if(!result.Any()) 553 { 554 return new Input(string.Empty); 555 } 556 var output = result.Aggregate((x, y) => x + Environment.NewLine + y); 557 return new Input(output); 558 } 559 } 560 } 561