You can pass designtime Farkles to be used in the resulting production as they are, or strings or characters to be used as literals. We use the ProductionBuilder's constructor which accepts a variable amount of objects (or none, but this is essentially the empty one). S is of type, which implements only the untyped DesigntimeFarkle interface.įor C# we could use production builders without extending or finishing them like in F#, but there is another shorter way. > operator since none of its members are significant, and we don't finish the production builder in the end with => or =%. We use the familiar production builders syntax to do it but with some changes: we always chain the members of the production with the. > ")", empty )Ĭ#: var S = Nonterminal.CreateUntyped( "S") įor F# we use the nonterminalU function to define an untyped nonterminal, and after that we set its productions, just like the typed nonterminals. Let's see how we would write the nonterminal that recognizes the balanced parentheses:į#: let S = nonterminalU "S" S. The nonterminals use a slightly different approach. If you don't remember how to use an API from C#, this guide can help you. > X (or W.Extended().Append(X) in C#), but not W. This means it can be normally used from other grammars (even typed), but it cannot be the significant member of a production. In F#, we use the terminalU function (guess what the U stands for), and in C# we just omit the delegate (it would have otherwise appeared between the name and the regex).Īs you might have seen, the terminal is of type DesigntimeFarkle, without a generic parameter at the end. Let's first see how we would write our terminal:į#: let X = m圜omplexRegex |> terminalU "X"Ĭ#: DesigntimeFarkle X = Terminal.Create( "X", m圜omplexRegex) The parentheses-ridden delegate definition at the end would have to be repeated, for every terminal we would have to create.įor this reason, the untyped API was created, to minimize code duplication. We would have done something like this: let X = m圜omplexRegex |> terminal "X" ( T ( fun _ _ -> ( ) ) ) Also imagine if we had more complex terminals. On larger grammars however, this habit of adding =% () to the end of each production tends to be repetitive. In Farkle, one way to write this grammar, is to just write it, but return dummy types like units on every production: // In all our examples, we always open this namespace. Let's take a look at the following grammar which matches matching parentheses: :: = ( ) :: = There are times however that we do not want to do the latter thing: we just want Farkle to create a grammar. Usually, when we write our designtime Farkles, we do not only state how our grammar is structured, but also what should our parser do when he encounters a specific symbol. The first feature we are going to discuss is a different API for creating grammars, which is called the untyped API. So, are you ready? Let's do this! The untyped API In this guide, we will take a look at some of these features that truly push Farkle's capabilities to the fullest. Farkle has a couple of features that were not covered in other guides because they are less likely to be useful.
0 Comments
Leave a Reply. |