Ryan Riley avatar Ryan Riley committed 26fa22f Merge

Merge latest

Comments (0)

Files changed (31)

Build/VS10/Calculator.fsproj

       <Private>False</Private>
     </ProjectReference>
   </ItemGroup>
-  <Import Project="$(ProgramFiles)\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Build/VS10/FParsec.fsproj

       <Link>CharParsers.fs</Link>
     </Compile>
   </ItemGroup>
-  <Import Project="$(ProgramFiles)\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Build/VS10/InterpFParsec.fsproj

       <Private>False</Private>
     </ProjectReference>
   </ItemGroup>
-  <Import Project="$(ProgramFiles)\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Build/VS10/InterpLexYacc.fsproj

     <Reference Include="mscorlib" />
     <Reference Include="System" />
   </ItemGroup>
-  <Import Project="$(ProgramFiles)\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Build/VS10/JSON.fsproj

       <Private>False</Private>
     </ProjectReference>
   </ItemGroup>
-  <Import Project="$(ProgramFiles)\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Build/VS10/PEG.fsproj

       <Private>False</Private>
     </ProjectReference>
   </ItemGroup>
-  <Import Project="$(ProgramFiles)\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Build/VS10/Test.fsproj

       <Private>False</Private>
     </ProjectReference>
   </ItemGroup>
-  <Import Project="$(ProgramFiles)\Microsoft F#\v4.0\Microsoft.FSharp.Targets" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Build/VS10/Tutorial.fsproj

       <Private>False</Private>
     </ProjectReference>
   </ItemGroup>
-  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="!Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
-  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition=" Exists('$(MSBuildBinPath)\Microsoft.Build.Tasks.v4.0.dll')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets" Condition="Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')" />
+  <Import Project="$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets'))" />
+  <Import Project="$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets" Condition="(!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.5\Microsoft.FSharp.Targets')) And (!Exists('$(MSBuildExtensionsPath32)\..\Microsoft F#\v4.0\Microsoft.FSharp.Targets')) And (Exists('$(MSBuildExtensionsPath32)\FSharp\1.0\Microsoft.FSharp.Targets'))" />
   <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
 	     Other similar extension points exist, see Microsoft.Common.targets.
 	<Target Name="BeforeBuild">

Doc/html/about/changelog.html

            class="cm">.</span><span class="ci">Exception</span></code> to prevent an infinite loop
           </li>
           <li class="_9">
+           <code class="fsharp"><a href="../reference/charparsers.html#members.anyOf"><span class="ci">anyOf</span></a></code>, <code
+           class="fsharp"><a href="../reference/charparsers.html#members.noneOf"><span class="ci">noneOf</span></a></code>, <code class="fsharp"><a
+           href="../reference/charparsers.html#members.isAnyOf"><span class="ci">isAnyOf</span></a></code> and <code class="fsharp"><a
+           href="../reference/charparsers.html#members.isNoneOf"><span class="ci">isNoneOf</span></a></code> now use runtime code generation (except
+           in the <a href="../download-and-installation.html#low-trust-version">Low‐Trust version</a>). <em>If you run into performance issues after
+           upgrading to version 0.9</em>, make sure that you don’t unnecessarily recreate <code class="fsharp"><a
+           href="../reference/charparsers.html#members.anyOf"><span class="ci">anyOf</span></a></code> or <code class="fsharp"><a
+           href="../reference/charparsers.html#members.noneOf"><span class="ci">noneOf</span></a></code> parsers, see <a
+           href="../users-guide/performance-optimizations.html#performance-guidelines.construct-parsers-once">here</a> and <a
+           href="../users-guide/where-is-the-monad.html#why-the-monadic-syntax-is-slow">here</a>.
+          </li>
+          <li class="_0">
            <code class="fsharp"><a href="../reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a></code>, <code
            class="fsharp"><a href="../reference/charparsers.html#members.notFollowedByString"><span class="ci">notFollowedByString</span></a></code>
            and similar parsers now have optimized code paths for argument strings with only 1 char
           </li>
-          <li class="_0">
+          <li class="_1">
            the behaviour of <code class="fsharp"><a href="../reference/charparsers.html#members.manyChars"><span
            class="ci">manyChars</span></a></code> and <code class="fsharp"><a href="../reference/charparsers.html#members.manyCharsTill"><span
            class="ci">manyCharsTill</span></a></code> and their variants <a
            href="#v0_9.details-on-changes-to-manychars-manycharstill-and-their-variants">has slightly changed</a>
           </li>
-          <li class="_1">
+          <li class="_2">
            the skip variants of <code class="fsharp"><a href="../reference/charparsers.html#members.manyChars"><span
            class="ci">manyChars</span></a></code> and <code class="fsharp"><a href="../reference/charparsers.html#members.manyCharsTill"><span
            class="ci">manyCharsTill</span></a></code> <a href="#v0_9.removed-skip-variants-of-manyChars">have been removed</a>
           </li>
-          <li class="_2">
+          <li class="_3">
            <p>Some renamings and function signature changes:</p>
            <div id="v0_9.renamings" class="table">
             <table cellspacing="0">

Doc/html/download-and-installation.html

         <div class="para _2">
          <p>
           This is an optimization for 32‐bit runtimes. You can find more information about the state tag in <a
-          href="users-guide/applying-parsers-in-sequence.html#the-statetag"></a>.
+          href="users-guide/applying-parsers-in-sequence.html#the-statetag">section 5.4.3</a> of the user’s guide.
          </p>
         </div>
        </dd>

Doc/html/tutorial.html

       class="fsharp"><a href="reference/primitives.html#members.tuple2"><span class="ci">tuple2</span></a> <span class="ci">p1</span> <span
       class="ci">p2</span></code>. In the following example we parse a pair of comma separated numbers with this operator:
      </p>
-<pre class="code fsharp"><span class="cmd"><span class="cmdp">&gt;</span> <span class="ci">test</span> <span class="cp">(</span><span class="ci">float_ws</span> <a href="reference/primitives.html#members...:62::62:.."><span class="co">.&gt;&gt;.</span></a> <span class="cp">(</span><span class="ci">ch</span> <span class="cc"><span class="cld">'</span>,<span class="crd">'</span></span> <a href="reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <span class="ci">float_ws</span><span class="cp">)</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>123, 456<span class="crd">"</span></span><span class="cp">;;</span></span>
+<pre class="code fsharp"><span class="cmd"><span class="cmdp">&gt;</span> <span class="ci">test</span> <span class="cp">(</span><span class="ci">float_ws</span> <a href="reference/primitives.html#members...:62::62:.."><span class="co">.&gt;&gt;.</span></a> <span class="cp">(</span><span class="ci">str_ws</span> <span class="cs"><span class="cld">"</span>,<span class="crd">"</span></span> <a href="reference/primitives.html#members.:62::62:.."><span class="co">&gt;&gt;.</span></a> <span class="ci">float_ws</span><span class="cp">)</span><span class="cp">)</span> <span class="cs"><span class="cld">"</span>123, 456<span class="crd">"</span></span><span class="cp">;;</span></span>
 <span class="cout">Success: (123.0, 456.0)
 </span></pre>
     </div>
     </div>
     <div class="para _3 lcinp">
      <p>F#’s value restriction is the reason that the following code snippet does not compile</p>
-<pre class="code fsharp"><span class="ck">open</span> <a href="reference/charparsers.html"><span class="ci">FParsec</span><span class="cm">.</span><span class="ci">CharParsers</span></a>
+<pre class="code fsharp"><span class="ck">open</span> <span class="ci">FParsec</span>
 <span class="ck">let</span> <span class="ci">p</span> <span class="cp">=</span> <a href="reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>test<span class="crd">"</span></span>
 </pre>
      <p>
       even though the following snippet compiles without a problem<sup class="fn-mark"><a id="fs-value-restriction.:FN:2:B:"
       href="#fs-value-restriction.:FN:2">[2]</a></sup>:
      </p>
-<pre class="code fsharp"><span class="ck">open</span> <a href="reference/charparsers.html"><span class="ci">FParsec</span><span class="cm">.</span><span class="ci">CharParsers</span></a>
+<pre class="code fsharp"><span class="ck">open</span> <span class="ci">FParsec</span>
 <span class="ck">let</span> <span class="ci">p</span> <span class="cp">=</span> <a href="reference/charparsers.html#members.pstring"><span class="ci">pstring</span></a> <span class="cs"><span class="cld">"</span>test<span class="crd">"</span></span>
 <a href="reference/charparsers.html#members.run"><span class="ci">run</span></a> <span class="ci">p</span> <span class="cs"><span class="cld">"</span>input<span class="crd">"</span></span>
 </pre>

Doc/html/users-guide/performance-optimizations.html

          </ul>
         </div>
        </dd>
-       <dt class="_3">Construct parsers once</dt>
+       <dt class="_3"><span class="a" id="performance-guidelines.construct-parsers-once">Construct parsers once</span></dt>
        <dd class="_3">
         <div class="para _1">
          <p>
 <pre class="code fsharp"><span class="ck">let</span> <a href="../reference/charparsers.html#members.identifier"><span class="ci">identifier</span></a> <span class="cp">=</span>
     <a href="../reference/primitives.html#members.attempt"><span class="ci">attempt</span></a> <span class="cp">(</span><span class="ci">identifierString</span>
              <a href="../reference/primitives.html#members.:62::62::61:"><span class="co">&gt;&gt;=</span></a> <span class="ck">fun</span> <span class="ci">str</span> <span class="cr">-&gt;</span>
-                     <span class="ck">if</span> <span class="ci">isIdentifier</span> <span class="ci">str</span> <span class="ck">then</span> <a href="../reference/primitives.html#members.preturn"><span class="ci">preturn</span></a> <span class="ci">str</span>
+                     <span class="ck">if</span> <span class="ci">not</span> <span class="cp">(</span><span class="ci">isKeyword</span> <span class="ci">str</span><span class="cp">)</span> <span class="ck">then</span> <a href="../reference/primitives.html#members.preturn"><span class="ci">preturn</span></a> <span class="ci">str</span>
                      <span class="ck">else</span> <a href="../reference/primitives.html#members.pzero"><span class="ci">pzero</span></a><span class="cp">)</span> <a href="../reference/primitives.html#members.:60::63::62:"><span class="co">&lt;?&gt;</span></a> <span class="cs"><span class="cld">"</span>identifier<span class="crd">"</span></span>
 
 </pre>

Doc/src/changelog.txt

 - the `...FoldApply` inline variants of `many`, `sepBy`, `sepEndBy` and `manyTill`
   have been consolidated in the `[^reference.Primitives.members.Inline FParsec.Primitives.Inline]` helper class
 - sequence parsers now throw a `System.InvalidOperationException` instead of a `System.Exception` to prevent an infinite loop
+- `anyOf`, `noneOf`, `isAnyOf` and `isNoneOf` now use runtime code generation (except in the [^low-trust-version Low-Trust version]). *If you run into performance issues after upgrading to version 0.9*, make sure that you don't unnecessarily recreate `anyOf` or `noneOf` parsers, see [^construct-parsers-once here] and [^why-the-monadic-syntax-is-slow here].
 - `pstring`, `notFollowedByString` and similar parsers now have optimized code paths
   for argument strings with only 1 char
 - the behaviour of `manyChars` and `manyCharsTill` and their variants [^details-on-changes-to-manychars-manycharstill-and-their-variants has slightly changed]

Doc/src/download-and-installation.txt

 [
 Use a 32-bit `StateTag` in the `CharStream` class instead of the default 64-bit one.
 
-This is an optimization for 32-bit runtimes. You can find more information about the state tag in [^the-statetag].
+This is an optimization for 32-bit runtimes. You can find more information about the state tag in [^ users-guide.applying-parsers-in-sequence.the-statetag] of the user's guide.
 ]
 
 [`#UNALIGNED_READS#`]

Doc/src/tutorial.txt

 
 The `tuple2` parser is also available under the operator name `.>>.`, so that you can write `p1 .>>. p2` instead of `tuple2 p1 p2`. In the following example we parse a pair of comma separated numbers with this operator:
 ``{fsi}
-> test (float_ws .>>. (ch ',' >>. float_ws)) "123, 456";;
+> test (float_ws .>>. (str_ws "," >>. float_ws)) "123, 456";;
 Success: (123.0, 456.0)
 ``
 
 
 F#'s value restriction is the reason that the following code snippet does not compile
 ``
-open FParsec.CharParsers
+open FParsec
 let p = pstring "test"
 ``
 even though the following snippet compiles without a problem[fn  Assuming you referenced the two FParsec DLLs.]:
 ``
-open FParsec.CharParsers
+open FParsec
 let p = pstring "test"
 run p "input"
 ``

Doc/src/users-guide.txt

 - Consider parsing unicode identifiers with the `identifier` parser.
 ]
 
-[Construct parsers once]
+[[# Construct parsers once]]
 [
 Constructing a parser can be relatively expensive in comparison to a single invocation of the parser. Hence, if you repeatedly apply the same parser, you should make sure that you construct the parser only once, either by preconstructing it at the beginning or by lazily constructing the parser and then caching it.
 
 let identifier =
     attempt (identifierString
              >>= fun str ->
-                     if isIdentifier str then preturn str
+                     if not (isKeyword str) then preturn str
                      else pzero) <?> "identifier"
 
 ``

FParsec/AssemblyInfo.fs

-namespace FParsec
+namespace FParsec
 
 open System.Reflection
 open System.Runtime.CompilerServices

FParsecCS/Buffer.cs

-// Copyright (c) Stephan Tolksdorf 2007-2010
+// Copyright (c) Stephan Tolksdorf 2007-2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/CharSet.cs

-// Copyright (c) Stephan Tolksdorf 2008-2010
+// Copyright (c) Stephan Tolksdorf 2008-2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/CharStream.cs

         public int LastBlock;
 
         public Stream Stream;
-        // we keep a seperate record of the Stream.Position, so that we don't need to require Stream.CanSeek
+        // we keep a separate record of the Stream.Position, so that we don't need to require Stream.CanSeek
         public long StreamPosition;
+        // we use StreamLength to avoid calling Read() again on a non-seekable stream after it returned 0 once (see ticket #23)
+        public long StreamLength;
         public bool LeaveOpen;
 
         public int MaxCharCountForOneByte;
     {
         if (byteBufferLength < MinimumByteBufferLength) byteBufferLength = MinimumByteBufferLength;
 
-        int bytesInStream = -1;
+        int remainingBytesCount = -1;
         long streamPosition;
+        long streamLength;
         if (stream.CanSeek) {
             streamPosition = stream.Position;
-            long streamLength = stream.Length - streamPosition;
-            if (streamLength <= Int32.MaxValue) {
-                bytesInStream = (int)streamLength;
-                if (bytesInStream < byteBufferLength) byteBufferLength = bytesInStream;
+            streamLength = stream.Length;
+            long remainingBytesCount64 = streamLength - streamPosition;
+            if (remainingBytesCount64 <= Int32.MaxValue) {
+                remainingBytesCount = (int)remainingBytesCount64;
+                if (remainingBytesCount < byteBufferLength) byteBufferLength = remainingBytesCount;
             }
         } else {
             streamPosition = 0;
+            streamLength = Int64.MaxValue;
         }
 
         byte[] byteBuffer = new byte[byteBufferLength];
         do {
             int n = stream.Read(byteBuffer, byteBufferCount, byteBufferLength - byteBufferCount);
             if (n == 0) {
-                bytesInStream = byteBufferCount;
+                remainingBytesCount = byteBufferCount;
+                Debug.Assert(!stream.CanSeek || streamPosition + byteBufferCount == streamLength);
+                streamLength = streamPosition + byteBufferCount;
                 break;
             }
             byteBufferCount += n;
         streamPosition += byteBufferCount;
 
         int preambleLength = Text.DetectPreamble(byteBuffer, byteBufferCount, ref encoding, detectEncodingFromByteOrderMarks);
-        bytesInStream -= preambleLength;
+        remainingBytesCount -= preambleLength;
 
         _Line = 1;
         Encoding = encoding;
         if (blockSize < 8) blockSize = DefaultBlockSize;
 
         bool allCharsFitIntoOneBlock = false;
-        if (bytesInStream >= 0 && bytesInStream/4 <= blockSize) {
-            if (bytesInStream != 0) {
+        if (remainingBytesCount >= 0 && remainingBytesCount/4 <= blockSize) {
+            if (remainingBytesCount != 0) {
                 try {
-                    int maxCharCount = Encoding.GetMaxCharCount(bytesInStream); // may throw ArgumentOutOfRangeException
+                    int maxCharCount = Encoding.GetMaxCharCount(remainingBytesCount); // may throw ArgumentOutOfRangeException
                     if (blockSize >= maxCharCount) {
                         allCharsFitIntoOneBlock = true;
                         blockSize = maxCharCount;
             if (allCharsFitIntoOneBlock) {
                 int bufferCount = preambleLength == byteBufferCount
                                   ? 0
-                                  : Text.ReadAllRemainingCharsFromStream(bufferBegin, buffer.Length, byteBuffer, preambleLength, byteBufferCount, stream, streamPosition, decoder);
+                                  : Text.ReadAllRemainingCharsFromStream(bufferBegin, buffer.Length, byteBuffer, preambleLength, byteBufferCount, stream, streamPosition, decoder, streamPosition == streamLength);
                 if (!leaveOpen) stream.Close();
                 if (bufferCount != 0) {
                     BufferBegin = bufferBegin;
                 d.CharStream = this;
                 d.Stream = stream;
                 d.StreamPosition = streamPosition;
+                d.StreamLength = streamLength;
                 d.LeaveOpen = leaveOpen;
                 d.Decoder = decoder;
                 d.DecoderIsSerializable = decoder.GetType().IsSerializable;
             // iteration anyway (or two at the end of the stream).
             int i = byteBufferIndex;
             int m = ByteBuffer.Length - byteBufferIndex;
-            while (m != 0) {
+            while (m != 0 && StreamPosition != StreamLength) { // we check the StreamPosition to avoid calling Read after it returned 0 at the end of the stream (see ticket #23)
                 int c = Stream.Read(ByteBuffer, i, m);
-                if (c == 0) break;
-                i += c;
-                m -= c;
+                if (c != 0) {
+                    i += c;
+                    m -= c;
+                    StreamPosition += c;
+                } else {
+                    Debug.Assert(!Stream.CanSeek || StreamPosition == StreamLength);
+                    StreamLength = StreamPosition;
+                    break;
+                }
             }
             int n = i - byteBufferIndex;
             ByteBufferIndex = byteBufferIndex;
             ByteBufferCount = byteBufferIndex + n;
-            StreamPosition += n;
             return n;
         }
 

FParsecCS/CharStreamLT.cs

         // the ByteBuffer must be larger than the longest detectable preamble
         if (byteBufferLength < MinimumByteBufferLength) byteBufferLength = MinimumByteBufferLength;
 
-        int bytesInStream = -1;
+        int remainingBytesCount = -1;
         long streamPosition;
         if (stream.CanSeek) {
             streamPosition = stream.Position;
-            long streamLength = stream.Length - streamPosition;
-            if (streamLength <= Int32.MaxValue) {
-                bytesInStream = (int) streamLength;
-                if (bytesInStream < byteBufferLength) byteBufferLength = bytesInStream;
+            long remainingBytesCount64 = stream.Length - streamPosition;
+            if (remainingBytesCount64 <= Int32.MaxValue) {
+                remainingBytesCount = (int)remainingBytesCount64;
+                if (remainingBytesCount < byteBufferLength) byteBufferLength = remainingBytesCount;
             }
         } else {
             streamPosition = 0;
         }
 
+        // byteBufferLength should be larger than the longest detectable preamble
         byte[] byteBuffer = new byte[byteBufferLength];
         int byteBufferCount = 0;
-        // byteBufferLength should be larger than the longest detectable preamble
+        bool flush = false;
         do {
             int n = stream.Read(byteBuffer, byteBufferCount, byteBuffer.Length - byteBufferCount);
             if (n == 0) {
-                bytesInStream = byteBufferCount;
+                remainingBytesCount = byteBufferCount;
+                flush = true;
                 break;
             }
             byteBufferCount += n;
         streamPosition += byteBufferCount;
 
         int preambleLength = Text.DetectPreamble(byteBuffer, byteBufferCount, ref encoding, detectEncodingFromByteOrderMarks);
-        bytesInStream -= preambleLength;
+        remainingBytesCount -= preambleLength;
         Encoding = encoding;
         _Line = 1;
-        if (bytesInStream != 0) {
+        if (remainingBytesCount != 0) {
             int charBufferLength = encoding.GetMaxCharCount(byteBufferLength); // might throw
             char[] charBuffer = new char[charBufferLength];
             int stringBufferCapacity = 2*charBufferLength;
-            if (bytesInStream > 0) {
+            if (remainingBytesCount > 0) {
                 try {
-                    stringBufferCapacity = encoding.GetMaxCharCount(bytesInStream); // might throw
+                    stringBufferCapacity = encoding.GetMaxCharCount(remainingBytesCount); // might throw
                 } catch (ArgumentOutOfRangeException) { }
             }
             var sb = new StringBuilder(stringBufferCapacity);
             var decoder = encoding.GetDecoder();
             Debug.Assert(preambleLength < byteBufferCount);
             int byteBufferIndex = preambleLength;
-            bool flush = false;
             for (;;) {
                 try {
                     int charBufferCount = decoder.GetChars(byteBuffer, byteBufferIndex, byteBufferCount - byteBufferIndex, charBuffer, 0, flush);

FParsecCS/ErrorMessage.cs

-// Copyright (c) Stephan Tolksdorf 2010
+// Copyright (c) Stephan Tolksdorf 2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/ErrorMessageList.cs

-// Copyright (c) Stephan Tolksdorf 2010
+// Copyright (c) Stephan Tolksdorf 2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/Errors.cs

-// Copyright (c) Stephan Tolksdorf 2010-2011
+// Copyright (c) Stephan Tolksdorf 2010-2011
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/FastGenericEqualityERComparer.cs

-// Copyright (c) Stephan Tolksdorf 2010
+// Copyright (c) Stephan Tolksdorf 2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/IdentifierValidator.cs

-// Copyright (c) Stephan Tolksdorf 2010
+// Copyright (c) Stephan Tolksdorf 2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/OperatorPrecedenceParser.cs

-// Copyright (c) Stephan Tolksdorf 2008-2011
+// Copyright (c) Stephan Tolksdorf 2008-2011
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/Reply.cs

-// Copyright (c) Stephan Tolksdorf 2008-2010
+// Copyright (c) Stephan Tolksdorf 2008-2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;

FParsecCS/Strings.cs

-// Copyright (c) Stephan Tolksdorf 2010-2011
+// Copyright (c) Stephan Tolksdorf 2010-2011
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;
 
     public static string AnyCharIn(string chars) {
         //return Quote(Strings.AnyCharIn1, chars, Strings.AnyCharIn2);
-        return Strings.AnyCharIn1 + "�" + chars + "�" + Strings.AnyCharIn2;
+        return Strings.AnyCharIn1 + "‘" + chars + "’" + Strings.AnyCharIn2; // Review: Should we use different quotes if the string contains ‘ or ’ chars?
     }
 
     public static string AnyCharNotIn(string chars) {
         //return Quote(Strings.AnyCharNotIn1, chars, Strings.AnyCharNotIn2);
-        return Strings.AnyCharNotIn1 + "" + chars + "" + Strings.AnyCharNotIn2;
+        return Strings.AnyCharNotIn1 + "" + chars + "" + Strings.AnyCharNotIn2;
     }
 
     public static string StringMatchingRegex(string regexPattern) {

FParsecCS/Text.cs

-// Copyright (c) Stephan Tolksdorf 2009-2010
+// Copyright (c) Stephan Tolksdorf 2009-2010
 // License: Simplified BSD License. See accompanying documentation.
 
 using System;
 #if !LOW_TRUST
 /// <summary>Reads all remaining chars into the given buffer. If the remaining stream
 /// content holds more than the given maximum number of chars, an exception will be thrown.</summary>
-internal unsafe static int ReadAllRemainingCharsFromStream(char* buffer, int maxCount, byte[] byteBuffer, int byteBufferIndex, int byteBufferCount, System.IO.Stream stream, long streamPosition, Decoder decoder) {
+internal unsafe static int ReadAllRemainingCharsFromStream(char* buffer, int maxCount, byte[] byteBuffer, int byteBufferIndex, int byteBufferCount, System.IO.Stream stream, long streamPosition, Decoder decoder, bool flush) {
     Debug.Assert(maxCount > 0 && byteBufferIndex >= 0 && byteBufferIndex < byteBufferCount);
     fixed (byte* pByteBuffer = byteBuffer) {
-        bool flush = false;
         int bufferCount = 0;
         for (;;) {
             try {

FParsecCS/UnmanagedMemoryPool.cs

-// Copyright (c) Stephan Tolksdorf 2010
+// Copyright (c) Stephan Tolksdorf 2010
 // License: Simplified BSD License. See accompanying documentation.
 
 #if !LOW_TRUST
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.