Interpreter: support implicit multiplication (adjacency) and allow whitespace; update Coco/R frames path casing; add tests for implicit multiplication and function calls; fix project reference casing in tests.

This commit is contained in:
codex 2025-08-29 17:43:07 -05:00
commit 135af2cc49
6 changed files with 47 additions and 5 deletions

View file

@ -13,7 +13,7 @@
</PropertyGroup>
<Target Name="PreBuild" BeforeTargets="PreBuildEvent">
<Exec Command="dotnet tool run coco -namespace CSMic.Interpreter -frames $(ProjectDir)CocoR $(ProjectDir)CocoR/Interpreter.atg" />
<Exec Command="dotnet tool run coco -namespace CSMic.Interpreter -frames $(ProjectDir)cocor $(ProjectDir)cocor/Interpreter.atg" />
</Target>
<Import Project="NuGetPublish.targets" Condition="Exists('NuGetPublish.targets')" />

View file

@ -58,6 +58,19 @@ bool IsArrayCall()
return false;
}
// Implicit multiplication detection: the next token starts a Factor
bool IsImplicitMul()
{
// Allow whitespace between tokens; scanner already skips it
// A Factor/Value can start with: '(', identifier (incl. function/array), number, hex, or binary
if (la.kind == _LPAREN) return true;
if (la.kind == _identifier) return true;
if (la.kind == _number) return true;
if (la.kind == _hex) return true;
if (la.kind == _binary) return true;
return false;
}
/*
* Character sets and tokens
*/
@ -132,7 +145,8 @@ Term<out decimal r>
=
(. decimal r1 = 0; r = 0; .)
Factor<out r>
{ '*' Factor<out r1> (. r *= r1; .)
{ IF(IsImplicitMul()) Factor<out r1> (. r *= r1; .)
| '*' Factor<out r1> (. r *= r1; .)
| '/' Factor<out r1> (. r /= r1; .)
| '%' Term<out r1> (. r %= r1; .)
}

View file

@ -19,8 +19,8 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Core\CsMic.Core.csproj" />
<ProjectReference Include="..\StandardLibrary\CsMic.StandardLibrary.csproj" />
<ProjectReference Include="..\Core\CSMic.Core.csproj" />
<ProjectReference Include="..\StandardLibrary\CSMic.StandardLibrary.csproj" />
</ItemGroup>
<ItemGroup>

View file

@ -158,4 +158,25 @@ public class InputInterpreterTests
_interp.Interpret("3+3");
Assert.That(_interp.LastExecutionTime, Is.GreaterThanOrEqualTo(TimeSpan.Zero));
}
[Test]
public void ImplicitMultiplication_Basic()
{
AssertSuccess(_interp.Interpret("2(3+1)"), 8, _interp);
}
[Test]
public void ImplicitMultiplication_WithVariableAndParens()
{
AssertSuccess(_interp.Interpret("x :: 3"), 3, _interp);
AssertSuccess(_interp.Interpret("2x"), 6, _interp);
AssertSuccess(_interp.Interpret("(x+1)(x-1)"), 8, _interp);
}
[Test]
public void ImplicitMultiplication_ChainedParens()
{
AssertSuccess(_interp.Interpret("x :: 4"), 4, _interp);
AssertSuccess(_interp.Interpret("3(x)(2)"), 24, _interp);
}
}

View file

@ -63,6 +63,14 @@ public class TrigonometryFunctionsTests
AssertApprox(_interp.Interpret("atan(1)"), 0.7853981633974483m, 0.0000000000001m, _interp);
AssertApprox(_interp.Interpret("atan2(1, 0)"), 1.5707963267948966m, 0.0000000000001m, _interp);
}
[Test]
public void ImplicitMultiplication_WithFunctions()
{
AssertSuccess(_interp.Interpret("2sin(0)"), 0m, _interp);
AssertSuccess(_interp.Interpret("2 sin(0)"), 0m, _interp);
AssertApprox(_interp.Interpret("2sin(pi/2)"), 2m, 0.0000000000001m, _interp);
}
}
public class HyperbolicTrigFunctionsTests
@ -95,4 +103,3 @@ public class HyperbolicTrigFunctionsTests
AssertSuccess(_interp.Interpret("atanh(0)"), 0m, _interp);
}
}