Use FsLex and FsYacc to make a parser in F#

Update: The template I posted yesterday was for PowerPack 1.9.9.9 which is not the most recent version available. I have since updated the template to target PowerPack 2.0.0.0. If you installed the old template you may need to uninstall at Tools\Extension Manager...

-----------------------------

Jomo Fisher—F# is excellent for parsing text and creating new languages. The F# PowerPack contains two tools—FsLex.exe and FsYacc.exe—to create powerful lexers and parsers. However, it isn’t so easy to configure a Visual Studio project correctly to use these tools. To help with this, I made a project template that you can use to get started quickly. Just follow these quick steps:

1) Download the F# PowerPack from here.

2) In VS2010, go to File\New Project. Select ‘Online Templates’ and search for ‘F# Parsed’ (or my name).

LexYacc

The starter project implements a simple calculator language that you can grow into a more sophisticated Domain Specific Language or text processing application.

Credit goes to Matt Valerio and Brian McNamara for figuring out the details and to Don Syme for making the calculator language that this is based on. Bugs and omissions are probably my fault. Please let me know what you think, and whether you have any issues or spot any bugs that I should address.

This posting is provided "AS IS" with no warranties, and confers no rights.

Comments

  • Anonymous
    June 15, 2010
    I'd really like this, as I struggled to get Don's calculator sample from Chapter 16 of Expert F# running on VS2010. Unfortunately the template appears to be tied to version 1.9.9.9 of the PowerPack, so if you download the latest Powerpack as I did its probably not going to work...

  • Anonymous
    June 15, 2010
    Hi, The VS2010 template does not work for F# PowerPack 2.0.0.0. Is there a way to fix it? Thanks in advance.

  • Anonymous
    June 15, 2010
    Hi, The VS2010 template does not work for F# PowerPack 2.0.0.0. Is there a way to fix it? Thanks in advance.

  • Anonymous
    June 15, 2010
    Hi, The VS2010 template does not work for F# PowerPack 2.0.0.0. Is there a way to fix it? Thanks in advance.

  • Anonymous
    June 15, 2010
    Nice work. Although the extension seems to fail if one uses 2.0.0.0 of the power pack; it complains it can not find the 1.9.9.9 version.

  • Anonymous
    June 16, 2010
    The comment has been removed

  • Anonymous
    June 16, 2010
    Just noticed that you updated the template.  However, it appears that the version downloaded from within VS2010 is still the old version - even deleting the AppData directory did not help. When you fix this, would you mind also updating the .vstemplate to enable PromptForSaveOnCreation, so that the template works when "Save new projects on creation" is turned off? Finally, make sure you don't hard code the path to Program Files, since it won't work if the root drive is not C:, and won't work on an x64 install (since PowerPack is installed into "Program Files(x86)"... Relative off of $(MSBuildExtensionsPath32) worked just fine for me.

  • Anonymous
    July 13, 2010
    Thanks for the starter - I'll be using this to quickly get started building my parser. The sample code is over-complicated for what it does though. Exactly the same effect (including operator precedence) is achieved with a single expression discriminator. From Ast.fs: type Expr =    | Float of Double    | Integer of Int32    | Times of Expr * Expr    | Divide of Expr * Expr    | Plus of Expr * Expr    | Minus of Expr * Expr From parser.fsy: Expr:    | Expr PLUS Term { Plus($1, $3) }    | Expr MINUS Term { Minus($1, $3) }    | Term { $1 } Term:    | Term ASTER Factor { Times($1, $3) }    | Term SLASH Factor { Divide($1, $3) }    | Factor { $1 } Factor:    | FLOAT { Float($1) }    | INT32 { Integer($1) }    | LPAREN Expr RPAREN { $2 } From Program.fs: let rec evalExpr expr =    match expr with    | Float x   -> x    | Integer x -> float x    | Times (term, fact)  -> (evalExpr term) * (evalExpr fact)    | Divide (term, fact) -> (evalExpr term) / (evalExpr fact)    | Plus (expr, term)  -> (evalExpr expr) + (evalExpr term)    | Minus (expr, term) -> (evalExpr expr) - (evalExpr term)