5

我正在尝试恢复我在 vs 2008 中使用的旧 f# 解析器项目以使用 vs 2013。它使用 FsLexYacc。

我通过使用预构建步骤使其构建正常,如下所示:

fslex --unicode "$(ProjectDir)XpathLexer.fsl"
fsyacc --module XpathParser "$(ProjectDir)XpathParser.fsy"

但这并不理想,因为无论输入是否发生变化,它都会执行。

然后我尝试使用旧的 MsBuild 操作:

<FsYacc Include="XpathParser.fsy">
<FsLex Include="XpathLexer.fsl">

但这些似乎在构建过程中被完全忽略了。那正确吗?这些构建任务是否以某种方式被删除了?

然后我在 vs C++ 下发现了一些我认为可能有用的东西:

<CustomBuild Include="XpathParser.fsy">
  <Message>Calling FsYacc</Message>
  <Command>fsyacc --module XpathParser "$(ProjectDir)XpathParser.fsy"</Command>
  <Outputs>$(ProjectDir)XpathParser.fs</Outputs>
</CustomBuild>

<PropertyGroup>
    <CustomBuildBeforeTargets>CoreCompile</CustomBuildBeforeTargets>
</PropertyGroup>

(我检查了 Microsoft.Fsharp.Targets 文件以提出“CoreCompile”目标。)

唉,还是没有雪茄。

是否有人能够阐明是否确实可以将 fslex/yacc 正确集成到 vs 2013 解决方案中,如果可以,如何?

4

3 回答 3

8

我不认为这些工具默认包含在随 Visual Studio 安装的 F# 编译器中,因此这些任务不存在。我对 Visual Studio 2012 项目进行了以下操作,但我希望它在 VS 2013 中会类似。以下是我必须遵循的步骤:

  1. 从 nuget 安装 FSharp.Powerpack。这有 fslex 和 fsyacc 工具以及构建任务和目标。
  2. 卸载项目并编辑 .fsproj 文件。
  3. 为 FSharp.Powerpack.target 文件添加导入语句。这将添加CallFsLexCallFsYacc构建目标。我在导入后添加了这个Microsoft.FSharp.targets
    <Import Project="$(ProjectDir)\..\packages\FSPowerPack.Community.3.0.0.0\Tools\FSharp.PowerPack.targets" />

  4. 将这三个属性添加到文件顶部的主 PropertyGroup: <FsYaccToolPath>..\packages\FSPowerPack.Community.3.0.0.0\Tools</FsYaccToolPath> <FsLexToolPath>..\packages\FSPowerPack.Community.3.0.0.0\Tools</FsLexToolPath> <FsLexUnicode>true</FsLexUnicode> 这告诉构建任务在哪里可以找到必要的工具,并为 fslex 设置 unicode 选项。

  5. 要使用我们导入的目标,您需要使用要使用的输入文件定义 FsLex 和 FsYacc 项目组。您还需要为输出的 .fs 文件添加编译项。您最终会在 ItemGroup 部分中得到类似的内容:
    <Compile Include="Sql.fs" />
    <FsYacc Include="SqlParser.fsp">
    <Module>SqlParser</Module>
    </FsYacc>
    <Compile Include="SqlParser.fsi" />
    <Compile Include="SqlParser.fs" />
    <FsLex Include="SqlLexer.fsl" />
    <Compile Include="SqlLexer.fs" />

您可以通过引用 FSharp.Powerpack.Build.Tasks.dll 直接使用 FsLex 和 FsYacc 构建任务,但对我来说这更容易上手。

于 2013-11-05T08:48:05.613 回答
1

这对我有用(Windows 7 x64,Visual Studio 2013 Ultimate RTM):

  1. 从 CodePlex ( https://fsharppowerpack.codeplex.com/downloads/get/625449 )获取并安装“PowerPack for FSharp 3.0 + .NET 4.x + VS2012”

  2. 创建以下注册表项:(HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework\AssemblyFolders\FSharp.PowerPack-1.9.9.9对于 x64 版本的 Windows,省略Wow6432Node32 位版本)并将其(Default)值设置为 F# PowerPack 的安装目录(例如“C:\Program Files (x86)\FSharpPowerPack-4.0.0.0\bin ”)。[这与一个长期存在的/回归错误有关,src/FSharp.PowerPack/CompilerLocationUtils.fs其中基本上破坏了工具发现。]

  3. 在 *.fsproj 文件中导入 PowerPack 目标(在导入 F# 目标之后):<Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\FSharp.PowerPack.targets" />

  4. 将您的节点更新ItemGroup为这样的内容(相应地使用 FsYacc):

    <ItemGroup>
      <None Include="App.config" />
      <FsLex Include="Lexer.fsl" />
      <Compile Include="Lexer.fs">
        <Visible>False</Visible>
      </Compile>
      <Compile Include="Program.fs" />
    </ItemGroup>
    
  5. 包括对FSharp.PowerPack.dll和构建的引用。

您最终应该得到一个类似于此的 *.fsproj 文件:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>8c565f99-d6bc-43a9-ace9-eadfe429c0f7</ProjectGuid>
    <OutputType>Exe</OutputType>
    <RootNamespace>FsYaccTest</RootNamespace>
    <AssemblyName>FsYaccTest</AssemblyName>
    <TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
    <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
    <TargetFSharpCoreVersion>4.3.1.0</TargetFSharpCoreVersion>
    <Name>FsYaccTest</Name>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
  <!-- Snip -->
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="FSharp.PowerPack">
      <HintPath>C:\Program Files (x86)\FSharpPowerPack-4.0.0.0\bin\FSharp.PowerPack.dll</HintPath>
    </Reference>
    <Reference Include="mscorlib" />
    <Reference Include="FSharp.Core, Version=$(TargetFSharpCoreVersion), Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
      <Private>True</Private>
    </Reference>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Numerics" />
  </ItemGroup>
  <PropertyGroup>
    <MinimumVisualStudioVersion Condition="'$(MinimumVisualStudioVersion)' == ''">11</MinimumVisualStudioVersion>
  </PropertyGroup>
  <Choose>
    <When Condition="'$(VisualStudioVersion)' == '11.0'">
      <PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets')">
        <FSharpTargetsPath>$(MSBuildExtensionsPath32)\..\Microsoft SDKs\F#\3.0\Framework\v4.0\Microsoft.FSharp.Targets</FSharpTargetsPath>
      </PropertyGroup>
    </When>
    <Otherwise>
      <PropertyGroup Condition="Exists('$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets')">
        <FSharpTargetsPath>$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\FSharp\Microsoft.FSharp.Targets</FSharpTargetsPath>
      </PropertyGroup>
    </Otherwise>
  </Choose>
  <Import Project="$(FSharpTargetsPath)" />  
  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\FSharp.PowerPack.targets" />  
  <PropertyGroup>
    <FsLexUnicode>true</FsLexUnicode>
  </PropertyGroup>
  <ItemGroup>
    <None Include="App.config" />
    <FsLex Include="Lexer.fsl" />
    <Compile Include="Lexer.fs">
      <Visible>False</Visible>
    </Compile>
    <Compile Include="Program.fs" />
  </ItemGroup>
</Project>

注意:如果您FsYaccToolPath按照 mike z 的回答中所述提供正确的,您可能可以省略创建注册表项。

于 2013-11-11T11:59:17.507 回答
1

这看起来可行 - 至少,根据我的经验,如果您使用此处详述的单独 FsLexYacc nuget 包,然后将以下内容放入您的 fsproj 文件(从 gi​​thub示例中提取):

在所有其他进口旁边:

<Import Project="..\packages\FsLexYacc.6.0.4\bin\FsLexYacc.targets" />

等等等等

然后对于源文件:

<FsYacc Include="Parser.fsp">
  <OtherFlags>--module SqlParser</OtherFlags>
</FsYacc>
<FsLex Include="Lexer.fsl">
  <OtherFlags>--unicode</OtherFlags>
</FsLex>

除了编辑 fsproj 文件并安装 nuget 包之外,无需执行任何操作。

于 2015-02-16T11:06:30.320 回答