I keep thinking of that as I work on my source generator for my Visual FA project. It's a lot of work and I have a long way to go before I can write an article or anything.
Writing source generators for C# is difficult, especially in Visual Studio where your updated generation code doesn't always "take" until you exit and relaunch Visual Studio. I had to find that out the hard way, after hours of struggle.
I've also got to learn to make NuGet packages, and probably something more than just a simple DLL or something.
Here's what I have so far, and I'm quite happy with it.
So far you can declare a regex matcher (one FARule) or lexer (multiple FARules, possibly with symbol names and ids):
using VisualFA;
partial class TestSource
{
[FARule(@"\/\*",Symbol="commentBlock",BlockEnd=@"\*\/")]
[FARule(@"\/\/[^\n]*", Symbol = "lineComment")]
[FARule(@"[ \t\r\n]+", Symbol = "whiteSpace")]
[FARule(@"[A-Za-z_][A-Za-z0-9_]*",Symbol="identifier")]
[FARule(@"(0|([1-9][0-9]*))((\.[0-9]+[Ee]\-?[1-9][0-9]*)?|\.[0-9]+)",Symbol="number")]
[FARule(@"\+",Symbol = "plus")]
[FARule(@"\-", Symbol = "minus")]
[FARule(@"\*", Symbol = "multiply")]
[FARule(@"\/", Symbol = "divide")]
[FARule(@"%", Symbol = "modulo")]
internal static partial FATextReaderRunner Calc(TextReader text);
}
That causes the C# compiler, with the help of my source generator to generate all the code necessary such that you can do this with it:
var exp = "the 10 quick brown foxes jumped over 1.5 lazy dogs";
foreach (var match in TestSource.Calc(new StringReader(exp)))
{
Console.WriteLine(match);
}
Which nets you this:
[SymbolId: 3, Value: "the", Position: 0 (1, 1)]
[SymbolId: 2, Value: " ", Position: 3 (1, 4)]
[SymbolId: 4, Value: "10", Position: 4 (1, 5)]
[SymbolId: 2, Value: " ", Position: 6 (1, 7)]
[SymbolId: 3, Value: "quick", Position: 7 (1, 8)]
[SymbolId: 2, Value: " ", Position: 12 (1, 13)]
[SymbolId: 3, Value: "brown", Position: 13 (1, 14)]
[SymbolId: 2, Value: " ", Position: 18 (1, 19)]
[SymbolId: 3, Value: "foxes", Position: 19 (1, 20)]
[SymbolId: 2, Value: " ", Position: 24 (1, 25)]
[SymbolId: 3, Value: "jumped", Position: 25 (1, 26)]
[SymbolId: 2, Value: " ", Position: 31 (1, 32)]
[SymbolId: 3, Value: "over", Position: 32 (1, 33)]
[SymbolId: 2, Value: " ", Position: 36 (1, 37)]
[SymbolId: 4, Value: "1.5", Position: 37 (1, 38)]
[SymbolId: 2, Value: " ", Position: 40 (1, 41)]
[SymbolId: 3, Value: "lazy", Position: 41 (1, 42)]
[SymbolId: 2, Value: " ", Position: 45 (1, 46)]
[SymbolId: 3, Value: "dogs", Position: 46 (1, 47)]
Check out my IoT graphics library here:
https://honeythecodewitch.com/gfx
And my IoT UI/User Experience library here:
https://honeythecodewitch.com/uix
|