mirror of
https://github.com/wagesj45/cs-mic.git
synced 2024-12-22 09:42:43 -06:00
Migrating from Sourceforge to Codeplex. Initial checkin starting with version 1.1.5.0 source code.
This commit is contained in:
parent
f7165325f7
commit
c41167bfc4
44 changed files with 7608 additions and 0 deletions
136
CS-MIC/csmic/CSMICTests/AuthoringTests.txt
Normal file
136
CS-MIC/csmic/CSMICTests/AuthoringTests.txt
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
==========================================================================
|
||||||
|
Visual Studio Team System: Overview of Authoring and Running Tests
|
||||||
|
==========================================================================
|
||||||
|
|
||||||
|
This overview describes the features for authoring and running tests in
|
||||||
|
Visual Studio Team System and Visual Studio Team Edition for Software Testers.
|
||||||
|
|
||||||
|
Opening Tests
|
||||||
|
-------------
|
||||||
|
To open a test, open a test project or a test metadata file (a file with
|
||||||
|
extension .vsmdi) that contains the definition of the test. You can find
|
||||||
|
test projects and metadata files in Solution Explorer.
|
||||||
|
|
||||||
|
Viewing Tests
|
||||||
|
-------------
|
||||||
|
To see which tests are available to you, open the Test View window. Or,
|
||||||
|
if you have installed Team Edition for Software Testers, you can also open
|
||||||
|
the Test List Editor window to view tests.
|
||||||
|
|
||||||
|
To open the Test View window, click the Test menu, point to Windows, and
|
||||||
|
then click Test View. To open the Test List Editor window (if you have
|
||||||
|
installed Team Edition for Software Testers), click Test, point to Windows,
|
||||||
|
and then click Test List Editor.
|
||||||
|
|
||||||
|
Running Tests
|
||||||
|
-------------
|
||||||
|
You can run tests from the Test View window and the Test List Editor window.
|
||||||
|
See Viewing Tests to learn how to open these windows. To run one or more
|
||||||
|
tests displayed in the Test View window, first select the tests in that
|
||||||
|
window; to select multiple tests, hold either the Shift or CTRL key while
|
||||||
|
clicking tests. Then click the Run Tests button in the Test View window
|
||||||
|
toolbar.
|
||||||
|
|
||||||
|
If you have installed Visual Studio Team Edition for Software Testers, you can
|
||||||
|
also use the Test List Editor window to run tests. To run tests in Test List Editor,
|
||||||
|
select the check box next to each test that you want to run. Then click the
|
||||||
|
Run Tests button in the Test List Editor window toolbar.
|
||||||
|
|
||||||
|
Viewing Test Results
|
||||||
|
--------------------
|
||||||
|
When you run a test or a series of tests, the results of the test run will be
|
||||||
|
shown in the Test Results window. Each individual test in the run is shown on
|
||||||
|
a separate line so that you can see its status. The window contains an
|
||||||
|
embedded status bar in the top half of the window that provides you with
|
||||||
|
summary details of the complete test run.
|
||||||
|
|
||||||
|
To see more detailed results for a particular test result, double-click it in
|
||||||
|
the Test Results window. This opens a window that provides more information
|
||||||
|
about the particular test result, such as any specific error messages returned
|
||||||
|
by the test.
|
||||||
|
|
||||||
|
Changing the way that tests are run
|
||||||
|
-----------------------------------
|
||||||
|
Each time you run one or more tests, a collection of settings is used to
|
||||||
|
determine how those tests are run. These settings are contained in a “test
|
||||||
|
run configuration” file.
|
||||||
|
|
||||||
|
Here is a partial list of the changes you can make with a test run
|
||||||
|
configuration file:
|
||||||
|
|
||||||
|
- Change the naming scheme for each test run.
|
||||||
|
- Change the test controller that the tests are run on so that you can run
|
||||||
|
tests remotely.
|
||||||
|
- Gather code coverage data for the code being tested so that you can see
|
||||||
|
which lines of code are covered by your tests.
|
||||||
|
- Enable and disable test deployment.
|
||||||
|
- Specify additional files to deploy before tests are run.
|
||||||
|
- Select a different host, ASP.NET, for running ASP.NET unit tests.
|
||||||
|
- Select a different host, the smart device test host, for running smart device unit tests.
|
||||||
|
- Set various properties for the test agents that run your tests.
|
||||||
|
- Run custom scripts at the start and end of each test run so that you can
|
||||||
|
set up the test environment exactly as required each time tests are run.
|
||||||
|
- Set time limits for tests and test runs.
|
||||||
|
- Set the browser mix and the number of times to repeat Web tests in the
|
||||||
|
test run.
|
||||||
|
|
||||||
|
By default, a test run configuration file is created whenever you create a
|
||||||
|
new test project. You make changes to this file by double-clicking it in
|
||||||
|
Solution Explorer and then changing its settings. (Test run configuration
|
||||||
|
files have the extension .testrunconfig.)
|
||||||
|
|
||||||
|
A solution can contain multiple test run configuration files. Only one of
|
||||||
|
those files, known as the “Active” test run configuration file, is used to
|
||||||
|
determine the settings that are currently used for test runs. You select
|
||||||
|
the active test run configuration by clicking Select Active Test Run
|
||||||
|
Configuration on the Test menu.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Test Types
|
||||||
|
----------
|
||||||
|
Using Visual Studio Team Edition for Software Testers, you can create a number
|
||||||
|
of different test types:
|
||||||
|
|
||||||
|
Unit test: Use a unit test to create a programmatic test in C++, Visual C# or
|
||||||
|
Visual Basic that exercises source code. A unit test calls the methods of a
|
||||||
|
class, passing suitable parameters, and verifies that the returned value is
|
||||||
|
what you expect.
|
||||||
|
There are three specialized variants of unit tests:
|
||||||
|
- Data-driven unit tests are created when you configure a unit test to be
|
||||||
|
called repeatedly for each row of a data source. The data from each row
|
||||||
|
is used by the unit test as input data.
|
||||||
|
- ASP.NET unit tests are unit tests that exercise code in an ASP.NET Web
|
||||||
|
application.
|
||||||
|
- Smart device unit tests are unit tests that are deployed to a smart device
|
||||||
|
or emulator and then executed by the smart device test host.
|
||||||
|
|
||||||
|
Web Test: Web tests consist of an ordered series of HTTP requests that you
|
||||||
|
record in a browser session using Microsoft Internet Explorer. You can have
|
||||||
|
the test report specific details about the pages or sites it requests, such
|
||||||
|
as whether a particular page contains a specified string.
|
||||||
|
|
||||||
|
Load Test: You use a load test to encapsulate non-manual tests, such as
|
||||||
|
unit, Web, and generic tests, and then run them simultaneously by using
|
||||||
|
virtual users. Running these tests under load generates test results,
|
||||||
|
including performance and other counters, in tables and in graphs.
|
||||||
|
|
||||||
|
Generic test: A generic test is an existing program wrapped to function as a
|
||||||
|
test in Visual Studio. The following are examples of tests or programs that
|
||||||
|
you can turn into generic tests:
|
||||||
|
- An existing test that uses process exit codes to communicate whether the
|
||||||
|
test passed or failed. 0 indicates passing and any other value indicates
|
||||||
|
a failure.
|
||||||
|
- A general program to obtain specific functionality during a test scenario.
|
||||||
|
- A test or program that uses a special XML file (called a “summary results
|
||||||
|
file”), to communicate detailed results.
|
||||||
|
|
||||||
|
Manual test: The manual test type is used when the test tasks are to be
|
||||||
|
completed by a test engineer as opposed to an automated script.
|
||||||
|
|
||||||
|
Ordered test: Use an ordered test to execute a set of tests in an order you
|
||||||
|
specify.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
120
CS-MIC/csmic/CSMICTests/CSMICTests.csproj
Normal file
120
CS-MIC/csmic/CSMICTests/CSMICTests.csproj
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{C03AD9DF-630F-4C88-A9D4-8B4B450CCB54}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>CSMICTests</RootNamespace>
|
||||||
|
<AssemblyName>CSMICTests</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<OldToolsVersion>3.5</OldToolsVersion>
|
||||||
|
<UpgradeBackupLocation />
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
<SccProjectName>SAK</SccProjectName>
|
||||||
|
<SccLocalPath>SAK</SccLocalPath>
|
||||||
|
<SccAuxPath>SAK</SccAuxPath>
|
||||||
|
<SccProvider>SAK</SccProvider>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Data" />
|
||||||
|
<Reference Include="System.Data.DataSetExtensions">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
<Reference Include="System.Xml" />
|
||||||
|
<Reference Include="System.Xml.Linq">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="InputInterpreterTest.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Content Include="AuthoringTests.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\csmic\csmic.csproj">
|
||||||
|
<Project>{7BBA4BA2-E885-4D89-8710-F1A609616B7D}</Project>
|
||||||
|
<Name>csmic</Name>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Shadow Include="Test References\csmic.accessor" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Microsoft .NET Framework 4 %28x86 and x64%29</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Windows Installer 3.1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.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">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
</Project>
|
10
CS-MIC/csmic/CSMICTests/CSMICTests.csproj.vspscc
Normal file
10
CS-MIC/csmic/CSMICTests/CSMICTests.csproj.vspscc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
""
|
||||||
|
{
|
||||||
|
"FILE_VERSION" = "9237"
|
||||||
|
"ENLISTMENT_CHOICE" = "NEVER"
|
||||||
|
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||||
|
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||||
|
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||||
|
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||||
|
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
||||||
|
}
|
216
CS-MIC/csmic/CSMICTests/InputInterpreterTest.cs
Normal file
216
CS-MIC/csmic/CSMICTests/InputInterpreterTest.cs
Normal file
|
@ -0,0 +1,216 @@
|
||||||
|
using csmic;
|
||||||
|
using csmic.Extensions;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||||
|
namespace CSMICTests
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///This is a test class for InputInterpreterTest and is intended
|
||||||
|
///to contain all InputInterpreterTest Unit Tests
|
||||||
|
///</summary>
|
||||||
|
[TestClass()]
|
||||||
|
public class InputInterpreterTest
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
private TestContext testContextInstance;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///Gets or sets the test context which provides
|
||||||
|
///information about and functionality for the current test run.
|
||||||
|
///</summary>
|
||||||
|
public TestContext TestContext
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return testContextInstance;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
testContextInstance = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Additional test attributes
|
||||||
|
//
|
||||||
|
//You can use the following additional attributes as you write your tests:
|
||||||
|
//
|
||||||
|
//Use ClassInitialize to run code before running the first test in the class
|
||||||
|
//[ClassInitialize()]
|
||||||
|
//public static void MyClassInitialize(TestContext testContext)
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//Use ClassCleanup to run code after all tests in a class have run
|
||||||
|
//[ClassCleanup()]
|
||||||
|
//public static void MyClassCleanup()
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//Use TestInitialize to run code before running each test
|
||||||
|
//[TestInitialize()]
|
||||||
|
//public void MyTestInitialize()
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
//Use TestCleanup to run code after each test has run
|
||||||
|
//[TestCleanup()]
|
||||||
|
//public void MyTestCleanup()
|
||||||
|
//{
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///A test for Interpret
|
||||||
|
///</summary>
|
||||||
|
[TestMethod()]
|
||||||
|
public void InterpretTest()
|
||||||
|
{
|
||||||
|
InputInterpreter target = new InputInterpreter();
|
||||||
|
target.CodedFunctions.Add(CodedFunctionFactory.Create("addfive", 1, rf => rf[0] + 5));
|
||||||
|
|
||||||
|
//HighLoadTest(target, "+1");
|
||||||
|
//HighLoadTest(target, "+sin(1)");
|
||||||
|
//HighLoadTest(target, "+precision(0.123456789, 7)");
|
||||||
|
//HighLoadTest(target, "+2*(2 + 5)/tan(sin(4))");
|
||||||
|
//HighLoadTest(target, "+2*2/3-1.23456");
|
||||||
|
|
||||||
|
ExpressionDecimalTest(target, "2+2", 4);
|
||||||
|
ExpressionDecimalTest(target, "1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10", 55);
|
||||||
|
ExpressionDecimalTest(target, "4 + 2 / 1 - 3 * 2", 0);
|
||||||
|
ExpressionDecimalTest(target, "16*2 - 2*3", 26);
|
||||||
|
ExpressionDecimalTest(target, "7-6+3*2", 7);
|
||||||
|
ExpressionDecimalTest(target, "1/-2*-1", 0.5M);
|
||||||
|
ExpressionDecimalTest(target, "12 + 26 / -2 + 3", 2);
|
||||||
|
ExpressionDecimalTest(target, "0.02395/1000", 0.00002395M);
|
||||||
|
ExpressionDecimalTest(target, "0100010101b", 277);
|
||||||
|
ExpressionDecimalTest(target, "0xabcdef", 11259375);
|
||||||
|
ExpressionDecimalTest(target, "11111111b + 0xFF", 510);
|
||||||
|
ExpressionDecimalTest(target, "10011001b * 0x01bAc", 1083852);
|
||||||
|
|
||||||
|
ExpressionDecimalTest(target, "log(sin(((25*200) - 5000)^1943),2)", decimal.MinValue);
|
||||||
|
ExpressionDecimalTest(target, "log(cos(((25*200) - 5000)^1943),2)", 0);
|
||||||
|
ExpressionDecimalTest(target, "cos(2^3)", -0.145500033808614M);
|
||||||
|
ExpressionDecimalTest(target, "addfive(30)", 35);
|
||||||
|
ExpressionDecimalTest(target, "precision(1.23456789, 4)", 1.2346M);
|
||||||
|
ExpressionDecimalTest(target, "3000 * (log(1 + 3162, 2))", 34881.2335215522M);
|
||||||
|
ExpressionDecimalTest(target, "(((12)))", 12);
|
||||||
|
|
||||||
|
ExpressionOutputTest(target, "z := (3*x) - (2*y)", "(3*x)-(2*y)");
|
||||||
|
ExpressionOutputTest(target, "x :: 3", "3");
|
||||||
|
ExpressionOutputTest(target, "y :: 2", "2");
|
||||||
|
ExpressionOutputTest(target, "x", "3");
|
||||||
|
ExpressionOutputTest(target, "y", "2");
|
||||||
|
ExpressionOutputTest(target, "z", "5");
|
||||||
|
ExpressionOutputTest(target, "z + 2", "7");
|
||||||
|
ExpressionOutputTest(target, "y :: 3", "3");
|
||||||
|
ExpressionOutputTest(target, "z", "3");
|
||||||
|
ExpressionOutputTest(target, "arr -> [3,6,9,12]", "3,6,9,12");
|
||||||
|
ExpressionOutputTest(target, "arr[1]", "6");
|
||||||
|
ExpressionOutputTest(target, "arr[1+1]", "9");
|
||||||
|
ExpressionOutputTest(target, "arr[2+44]", "0");
|
||||||
|
|
||||||
|
ExpressionOutputTest(target, "log(sin(((25*200) - 5000)^1943),2)", "log(sin(((25*200) - 5000)^1943),2)".Interpret());
|
||||||
|
ExpressionOutputTest(target, "log(cos(((25*200) - 5000)^1943),2)", "log(cos(((25*200) - 5000)^1943),2)".Interpret());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void AsyncTest()
|
||||||
|
{
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
interpreter.InterpretAsync("2 + 2", i =>
|
||||||
|
{
|
||||||
|
Assert.IsTrue(i.Output == "4");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[TestMethod]
|
||||||
|
public void ComputableTest()
|
||||||
|
{
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
|
||||||
|
interpreter.Interpret("1");
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.Add(5)).Resolve().Decimal == 6);
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.Subtract(5)).Resolve().Decimal == 1);
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.Multiply(5)).Resolve().Decimal == 5);
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.Divide(1)).Resolve().Decimal == 5);
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.Mod(1)).Resolve().Decimal == 0);
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.RaiseToPower(5)).Resolve().Decimal == 0);
|
||||||
|
|
||||||
|
interpreter.Interpret("1");
|
||||||
|
Assert.IsTrue(interpreter.ToComputable().Add(5).Resolve().Decimal == 6);
|
||||||
|
Assert.IsTrue(interpreter.ToComputable().Subtract(5).Resolve().Decimal == 1);
|
||||||
|
Assert.IsTrue(interpreter.ToComputable().Multiply(5).Resolve().Decimal == 5);
|
||||||
|
Assert.IsTrue(interpreter.ToComputable().Divide(1).Resolve().Decimal == 5);
|
||||||
|
Assert.IsTrue(interpreter.ToComputable().Mod(1).Resolve().Decimal == 0);
|
||||||
|
Assert.IsTrue(interpreter.ToComputable().RaiseToPower(5).Resolve().Decimal == 0);
|
||||||
|
|
||||||
|
interpreter.Interpret("1");
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.Add(5)).ResolveTo(i => i.Decimal) == 6);
|
||||||
|
Assert.IsTrue(interpreter.AsComputable(c => c.Subtract(5)).ResolveTo(i => i.Int) == 1);
|
||||||
|
|
||||||
|
interpreter.Interpret("5");
|
||||||
|
int[] ia = new int[] { 1,2,3 };
|
||||||
|
var test = interpreter.AsComputable(computable => computable.ForAll(ia, sub => sub.RaiseToPower)).Resolve();
|
||||||
|
Assert.IsTrue(test.Output == "15625");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests a value repeated 10,000 times and checks for an execution time less than 200 milliseconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">The input interpreter.</param>
|
||||||
|
/// <param name="value">The value to repeat and test.</param>
|
||||||
|
public void HighLoadTest(InputInterpreter target, string value)
|
||||||
|
{
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
string input = string.Empty;
|
||||||
|
System.TimeSpan baseTime = new System.TimeSpan();
|
||||||
|
for (int i = 0; i < 1000; i++)
|
||||||
|
{
|
||||||
|
builder.Append(value);
|
||||||
|
}
|
||||||
|
input = builder.ToString();
|
||||||
|
target.Interpret(input);
|
||||||
|
baseTime = target.LastExecutionTime;
|
||||||
|
|
||||||
|
builder = new StringBuilder();
|
||||||
|
for (int i = 0; i < 100000; i++)
|
||||||
|
{
|
||||||
|
builder.Append(value);
|
||||||
|
}
|
||||||
|
input = builder.ToString();
|
||||||
|
target.Interpret(input);
|
||||||
|
|
||||||
|
Assert.IsTrue(target.LastExecutionTime <= System.TimeSpan.FromTicks((baseTime.Ticks + 1 * 100) + 100), string.Format("{0} failed the high load test.", value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests a given expression for a decimal result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">The input interpreter.</param>
|
||||||
|
/// <param name="input">The input to execute.</param>
|
||||||
|
/// <param name="expected">The expected value.</param>
|
||||||
|
public void ExpressionDecimalTest(InputInterpreter target, string input, decimal expected)
|
||||||
|
{
|
||||||
|
target.Interpret(input);
|
||||||
|
Assert.AreEqual(expected, target.Decimal, string.Format("{0} returned {1} but {2} was expected.", input, target.Decimal, expected));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tests a given expression for a string result.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="target">The input interpreter.</param>
|
||||||
|
/// <param name="input">The input to execute.</param>
|
||||||
|
/// <param name="expected">The expected value.</param>
|
||||||
|
public void ExpressionOutputTest(InputInterpreter target, string input, string expected)
|
||||||
|
{
|
||||||
|
target.Interpret(input);
|
||||||
|
Assert.AreEqual(expected, target.Output, string.Format("{0} returned {1} but {2} was expected.", input, target.Decimal, expected));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
35
CS-MIC/csmic/CSMICTests/Properties/AssemblyInfo.cs
Normal file
35
CS-MIC/csmic/CSMICTests/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("CSMICTests")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("CSMICTests")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2010")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM componenets. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("8e6bded0-27ba-4d6b-a785-988958ca4b10")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
[assembly: AssemblyVersion("1.0.0.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
2
CS-MIC/csmic/CSMICTests/Test References/csmic.accessor
Normal file
2
CS-MIC/csmic/CSMICTests/Test References/csmic.accessor
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
csmic.dll
|
||||||
|
Desktop
|
87
CS-MIC/csmic/HelpFile/HelpFile.shfbproj
Normal file
87
CS-MIC/csmic/HelpFile/HelpFile.shfbproj
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
|
||||||
|
<PropertyGroup>
|
||||||
|
<!-- The configuration and platform will be used to determine which
|
||||||
|
assemblies to include from solution and project documentation
|
||||||
|
sources -->
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{b60970b9-771a-4ebb-9978-89f55163888f}</ProjectGuid>
|
||||||
|
<SHFBSchemaVersion>1.9.5.0</SHFBSchemaVersion>
|
||||||
|
<!-- AssemblyName, Name, and RootNamespace are not used by SHFB but Visual
|
||||||
|
Studio adds them anyway -->
|
||||||
|
<AssemblyName>HelpFile</AssemblyName>
|
||||||
|
<RootNamespace>HelpFile</RootNamespace>
|
||||||
|
<Name>HelpFile</Name>
|
||||||
|
<!-- SHFB properties -->
|
||||||
|
<OutputPath>.\Help\</OutputPath>
|
||||||
|
<HtmlHelpName>csmic_help</HtmlHelpName>
|
||||||
|
<Language>en-US</Language>
|
||||||
|
<HelpFileFormat>HtmlHelp1, Website</HelpFileFormat>
|
||||||
|
<IndentHtml>False</IndentHtml>
|
||||||
|
<FrameworkVersion>.NET Framework 4.0</FrameworkVersion>
|
||||||
|
<KeepLogFile>True</KeepLogFile>
|
||||||
|
<DisableCodeBlockComponent>False</DisableCodeBlockComponent>
|
||||||
|
<CppCommentsFixup>False</CppCommentsFixup>
|
||||||
|
<CleanIntermediates>True</CleanIntermediates>
|
||||||
|
<SyntaxFilters>Standard</SyntaxFilters>
|
||||||
|
<SdkLinkTarget>Blank</SdkLinkTarget>
|
||||||
|
<RootNamespaceTitle>csmic</RootNamespaceTitle>
|
||||||
|
<RootNamespaceContainer>True</RootNamespaceContainer>
|
||||||
|
<PresentationStyle>VS2010</PresentationStyle>
|
||||||
|
<Preliminary>False</Preliminary>
|
||||||
|
<NamingMethod>Guid</NamingMethod>
|
||||||
|
<HelpTitle>CS-MIC - C Sharp Math Input Control</HelpTitle>
|
||||||
|
<FooterText>Please visit the &lt%3ba href=&quot%3bhttp://cs-mic.com&quot%3b&gt%3bofficial site&lt%3b/a&gt%3b for more information.</FooterText>
|
||||||
|
<FeedbackEMailLinkText>Please feel free to provide feedback!</FeedbackEMailLinkText>
|
||||||
|
<FeedbackEMailAddress>jordan%40jordanwages.com</FeedbackEMailAddress>
|
||||||
|
<CopyrightText>Copyright 2012</CopyrightText>
|
||||||
|
<ContentPlacement>AboveNamespaces</ContentPlacement>
|
||||||
|
<WebsiteSdkLinkType>Msdn</WebsiteSdkLinkType>
|
||||||
|
<HtmlSdkLinkType>Msdn</HtmlSdkLinkType>
|
||||||
|
<IncludeFavorites>True</IncludeFavorites>
|
||||||
|
<BinaryTOC>True</BinaryTOC>
|
||||||
|
<ProjectSummary>CS-MIC is a .NET library written in C# designed to give developers easy access to expression parsing. For many developers, there is no need to involve complicated settings and formats. With few exposed methods and objects, CS-MIC makes basic expression solving as simple as possible with as little logic required from developers as possible. In fact, one can pull a value with only one line of code.</ProjectSummary>
|
||||||
|
<VisibleItems>Attributes, ExplicitInterfaceImplementations, InheritedMembers, InheritedFrameworkMembers, Internals, Protected, SealedProtected</VisibleItems>
|
||||||
|
<DocumentationSources>
|
||||||
|
<DocumentationSource sourceFile="..\csmic\bin\Release\csmic.dll" />
|
||||||
|
<DocumentationSource sourceFile="..\csmic\bin\Release\csmic.xml" />
|
||||||
|
</DocumentationSources>
|
||||||
|
<ApiFilter />
|
||||||
|
<ComponentConfigurations />
|
||||||
|
<HelpAttributes />
|
||||||
|
<NamespaceSummaries />
|
||||||
|
<PlugInConfigurations />
|
||||||
|
<BuildLogFile />
|
||||||
|
<HtmlHelp1xCompilerPath />
|
||||||
|
<HtmlHelp2xCompilerPath />
|
||||||
|
<SandcastlePath />
|
||||||
|
<WorkingPath />
|
||||||
|
<SccProjectName>SAK</SccProjectName>
|
||||||
|
<SccProvider>SAK</SccProvider>
|
||||||
|
<SccAuxPath>SAK</SccAuxPath>
|
||||||
|
<SccLocalPath>SAK</SccLocalPath>
|
||||||
|
</PropertyGroup>
|
||||||
|
<!-- There are no properties for these groups. AnyCPU needs to appear in
|
||||||
|
order for Visual Studio to perform the build. The others are optional
|
||||||
|
common platform types that may appear. -->
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x64' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x64' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|Win32' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|Win32' ">
|
||||||
|
</PropertyGroup>
|
||||||
|
<!-- Import the SHFB build targets -->
|
||||||
|
<Import Project="$(SHFBROOT)\SandcastleHelpFileBuilder.targets" />
|
||||||
|
</Project>
|
10
CS-MIC/csmic/HelpFile/HelpFile.shfbproj.vspscc
Normal file
10
CS-MIC/csmic/HelpFile/HelpFile.shfbproj.vspscc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
""
|
||||||
|
{
|
||||||
|
"FILE_VERSION" = "9237"
|
||||||
|
"ENLISTMENT_CHOICE" = "NEVER"
|
||||||
|
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||||
|
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||||
|
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||||
|
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||||
|
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
||||||
|
}
|
54
CS-MIC/csmic/csmic.sln
Normal file
54
CS-MIC/csmic/csmic.sln
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
|
||||||
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
|
# Visual Studio 2012
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "csmic", "csmic\csmic.csproj", "{7BBA4BA2-E885-4D89-8710-F1A609616B7D}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CSMICTests", "CSMICTests\CSMICTests.csproj", "{C03AD9DF-630F-4C88-A9D4-8B4B450CCB54}"
|
||||||
|
EndProject
|
||||||
|
Project("{7CF6DF6D-3B04-46F8-A40B-537D21BCA0B4}") = "HelpFile", "HelpFile\HelpFile.shfbproj", "{B60970B9-771A-4EBB-9978-89F55163888F}"
|
||||||
|
EndProject
|
||||||
|
Global
|
||||||
|
GlobalSection(TeamFoundationVersionControl) = preSolution
|
||||||
|
SccNumberOfProjects = 4
|
||||||
|
SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C}
|
||||||
|
SccTeamFoundationServer = https://tfs.codeplex.com/tfs/tfs35
|
||||||
|
SccLocalPath0 = .
|
||||||
|
SccProjectUniqueName1 = csmic\\csmic.csproj
|
||||||
|
SccProjectName1 = csmic
|
||||||
|
SccLocalPath1 = csmic
|
||||||
|
SccProjectUniqueName2 = CSMICTests\\CSMICTests.csproj
|
||||||
|
SccProjectName2 = CSMICTests
|
||||||
|
SccLocalPath2 = CSMICTests
|
||||||
|
SccProjectUniqueName3 = HelpFile\\HelpFile.shfbproj
|
||||||
|
SccProjectName3 = HelpFile
|
||||||
|
SccLocalPath3 = HelpFile
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(TestCaseManagementSettings) = postSolution
|
||||||
|
CategoryFile = csmic8.vsmdi
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
Debug|Any CPU = Debug|Any CPU
|
||||||
|
Release|Any CPU = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
|
{7BBA4BA2-E885-4D89-8710-F1A609616B7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{7BBA4BA2-E885-4D89-8710-F1A609616B7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{7BBA4BA2-E885-4D89-8710-F1A609616B7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{7BBA4BA2-E885-4D89-8710-F1A609616B7D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{C03AD9DF-630F-4C88-A9D4-8B4B450CCB54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{C03AD9DF-630F-4C88-A9D4-8B4B450CCB54}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{C03AD9DF-630F-4C88-A9D4-8B4B450CCB54}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{C03AD9DF-630F-4C88-A9D4-8B4B450CCB54}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{B60970B9-771A-4EBB-9978-89F55163888F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{B60970B9-771A-4EBB-9978-89F55163888F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{B60970B9-771A-4EBB-9978-89F55163888F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{B60970B9-771A-4EBB-9978-89F55163888F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
|
HideSolutionNode = FALSE
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SubversionScc) = preSolution
|
||||||
|
Svn-Managed = True
|
||||||
|
Manager = AnkhSVN - Subversion Support for Visual Studio
|
||||||
|
EndGlobalSection
|
||||||
|
EndGlobal
|
10
CS-MIC/csmic/csmic.vssscc
Normal file
10
CS-MIC/csmic/csmic.vssscc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
""
|
||||||
|
{
|
||||||
|
"FILE_VERSION" = "9237"
|
||||||
|
"ENLISTMENT_CHOICE" = "NEVER"
|
||||||
|
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||||
|
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||||
|
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||||
|
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||||
|
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT"
|
||||||
|
}
|
24
CS-MIC/csmic/csmic/CodedFunctionFactory.cs
Normal file
24
CS-MIC/csmic/csmic/CodedFunctionFactory.cs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary> Coded function factory. </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This class generates new coded functions dynamically.
|
||||||
|
/// </remarks>
|
||||||
|
public static class CodedFunctionFactory
|
||||||
|
{
|
||||||
|
/// <summary> Creates a new ICodedFunction interface object that implements the dynamic method described. </summary>
|
||||||
|
/// <param name="functionName"> Name of the function. </param>
|
||||||
|
/// <param name="numExpectedArguments"> Number of expected arguments. </param>
|
||||||
|
/// <param name="methodBody"> The method body. </param>
|
||||||
|
/// <returns> An ICodedFunction interface object. </returns>
|
||||||
|
public static ICodedFunction Create(string functionName, int numExpectedArguments, Func<decimal[], decimal> methodBody)
|
||||||
|
{
|
||||||
|
return new GenericCodedFunction(functionName, numExpectedArguments, methodBody);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Abs.cs
Normal file
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Abs.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of the absolute value function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Abs : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 1 argument.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "abs"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The absolute value of the argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
output = Math.Abs(input);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Cos.cs
Normal file
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Cos.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of the cosine function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Cos : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 1 argument.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "cos"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The cosine of the argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
output = (decimal)Math.Cos((double)input);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Exp.cs
Normal file
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Exp.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of the exponential function based on the constant e.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Exp : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 1 argument.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "exp"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The constant e raised to the power of the argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
output = (decimal)Math.Exp((double)input);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
57
CS-MIC/csmic/csmic/CodedFunctions/CF_Log.cs
Normal file
57
CS-MIC/csmic/csmic/CodedFunctions/CF_Log.cs
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of the log function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Log : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 2 arguments.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 2; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "log"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The log of the first argument to the base of the second argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
decimal logBase = args[1];
|
||||||
|
try
|
||||||
|
{
|
||||||
|
output = (decimal)Math.Log((double)input, (double)logBase);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
output = decimal.MinValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
50
CS-MIC/csmic/csmic/CodedFunctions/CF_Precision.cs
Normal file
50
CS-MIC/csmic/csmic/CodedFunctions/CF_Precision.cs
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of a precision function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Precision : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 2 arguments.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 2; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "precision"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The first argument to the precision of the argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
decimal precision = args[1];
|
||||||
|
output = (decimal)Math.Round(input, (int)precision);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Round.cs
Normal file
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Round.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of a rounded function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Round : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 1 argument.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "round"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The rounded argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
output = Math.Round(input);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Sin.cs
Normal file
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Sin.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of the sine function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Sin : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 1 argument.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "sin"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The sine of the argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
output = (decimal)Math.Sin((double)input);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Sqrt.cs
Normal file
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Sqrt.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of the squre root function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Sqrt : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 1 argument.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "sqrt"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The square root of the argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
output = (decimal)Math.Sqrt((double)input);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Tan.cs
Normal file
49
CS-MIC/csmic/csmic/CodedFunctions/CF_Tan.cs
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.CodedFunctions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A coded implementation of the tangent function.
|
||||||
|
/// </summary>
|
||||||
|
class CF_Tan : ICodedFunction
|
||||||
|
{
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Expects 1 argument.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get { return 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get { return "tan"; }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used in the code block.</param>
|
||||||
|
/// <returns>The tangent of the argument.</returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
decimal output = 0;
|
||||||
|
if (args.Length == this.NumExpectedArguments)
|
||||||
|
{
|
||||||
|
decimal input = args[0];
|
||||||
|
output = (decimal)Math.Tan((double)input);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
182
CS-MIC/csmic/csmic/Computable/Computable.cs
Normal file
182
CS-MIC/csmic/csmic/Computable/Computable.cs
Normal file
|
@ -0,0 +1,182 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.ComputableEngine
|
||||||
|
{
|
||||||
|
/// <summary> Computable class. </summary>
|
||||||
|
public sealed class Computable
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary> The expression to be built.</summary>
|
||||||
|
private string expression;
|
||||||
|
/// <summary> The interpreter to act as a base.</summary>
|
||||||
|
private InputInterpreter interpreter;
|
||||||
|
|
||||||
|
#region Constants
|
||||||
|
|
||||||
|
/// <summary> The add symbol.</summary>
|
||||||
|
private const string ADD = "+";
|
||||||
|
/// <summary> The substract symbol.</summary>
|
||||||
|
private const string SUBSTRACT = "-";
|
||||||
|
/// <summary> The divide symbol.</summary>
|
||||||
|
private const string DIVIDE = "/";
|
||||||
|
/// <summary> The multiply symbol.</summary>
|
||||||
|
private const string MULTIPLY = "*";
|
||||||
|
/// <summary> The modifier symbol.</summary>
|
||||||
|
private const string MOD = "%";
|
||||||
|
/// <summary> The power symbol.</summary>
|
||||||
|
private const string POWER = "^";
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary> Gets the expression. </summary>
|
||||||
|
/// <value> The expression. </value>
|
||||||
|
internal string Expression
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.expression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary> Creates a Computable instance. </summary>
|
||||||
|
/// <param name="expression"> The expression. </param>
|
||||||
|
/// <param name="interpreter"> The interpreter. </param>
|
||||||
|
internal Computable(string expression, InputInterpreter interpreter)
|
||||||
|
{
|
||||||
|
this.expression = expression;
|
||||||
|
this.interpreter = interpreter;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary> Resolves the computable as an input interpreter having calculated the input. </summary>
|
||||||
|
/// <returns> The computable as an input interpreter. </returns>
|
||||||
|
public InputInterpreter Resolve()
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(this.Expression);
|
||||||
|
return this.interpreter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Resolve the computer to a type <typeparamref name="T"/>. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <param name="selector"> The selector function. </param>
|
||||||
|
/// <returns> . </returns>
|
||||||
|
public T ResolveTo<T>(Func<InputInterpreter, T> selector)
|
||||||
|
{
|
||||||
|
return selector(this.Resolve());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Form the operation given the operation constant and an argument. </summary>
|
||||||
|
/// <param name="operation"> The operation constant. </param>
|
||||||
|
/// <param name="argument"> The argument. </param>
|
||||||
|
/// <returns> A string with the given operation appended. </returns>
|
||||||
|
private string FormOperation(string operation, object argument)
|
||||||
|
{
|
||||||
|
return string.Format("({0} {1} {2})", this.Expression, operation, argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Form the function <paramref name="name"/> with the current expression as the first argument, followed by <paramref name="arguments"/>. </summary>
|
||||||
|
/// <param name="name"> The name of the function. </param>
|
||||||
|
/// <param name="arguments"> The arguments. </param>
|
||||||
|
/// <returns> . </returns>
|
||||||
|
private string FormFunction(string name, object[] arguments)
|
||||||
|
{
|
||||||
|
return string.Format("{0}({1})", name, string.Join(",", this.Expression, arguments));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Adds addend. </summary>
|
||||||
|
/// <param name="addend"> The decimal to add. </param>
|
||||||
|
/// <returns> A computable class after the addition. </returns>
|
||||||
|
public Computable Add(decimal addend)
|
||||||
|
{
|
||||||
|
this.expression = FormOperation(ADD, addend);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Subtracts the subtrahend. </summary>
|
||||||
|
/// <param name="subtrahend"> The subtrahend. </param>
|
||||||
|
/// <returns> A computable class after the subtraction. </returns>
|
||||||
|
public Computable Subtract(decimal subtrahend)
|
||||||
|
{
|
||||||
|
this.expression = FormOperation(SUBSTRACT, subtrahend);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Multiplies the multiplicand. </summary>
|
||||||
|
/// <param name="multiplicand"> The multiplicand. </param>
|
||||||
|
/// <returns> A computable class after the mulitplication. </returns>
|
||||||
|
public Computable Multiply(decimal multiplicand)
|
||||||
|
{
|
||||||
|
this.expression = FormOperation(MULTIPLY, multiplicand);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Divides the divisor. </summary>
|
||||||
|
/// <param name="divisor"> The divisor. </param>
|
||||||
|
/// <returns> A computable class after the divison. </returns>
|
||||||
|
public Computable Divide(decimal divisor)
|
||||||
|
{
|
||||||
|
this.expression = FormOperation(DIVIDE, divisor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Mods using a given divisor. </summary>
|
||||||
|
/// <param name="divisor"> The divisor. </param>
|
||||||
|
/// <returns> A computable class after the mod. </returns>
|
||||||
|
public Computable Mod(decimal divisor)
|
||||||
|
{
|
||||||
|
this.expression = FormOperation(MOD, divisor);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Raises to power of the given integer value. </summary>
|
||||||
|
/// <param name="power"> The power. </param>
|
||||||
|
/// <returns> A computable class after the power operation. </returns>
|
||||||
|
public Computable RaiseToPower(int power)
|
||||||
|
{
|
||||||
|
this.expression = FormOperation(POWER, power);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Applies the function <paramref name="name"/> with the current expression as the first argument, followed by <paramref name="arguments"/>. </summary>
|
||||||
|
/// <param name="name"> The name of the function. </param>
|
||||||
|
/// <param name="arguments"> The arguments. </param>
|
||||||
|
/// <returns> A computable class after the function is applied. </returns>
|
||||||
|
public Computable ApplyFunction(string name, object[] arguments)
|
||||||
|
{
|
||||||
|
this.expression = FormFunction(name, arguments);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Executes a command for all items in a collection. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <param name="items"> The items of type <typeparamref name="T"/>. </param>
|
||||||
|
/// <param name="action"> The action belonging to type <see cref="Computable"/>. </param>
|
||||||
|
/// <returns> . </returns>
|
||||||
|
public Computable ForAll<T>(ICollection<T> items, Func<Computable, Func<T, Computable>> action)
|
||||||
|
{
|
||||||
|
foreach (T item in items)
|
||||||
|
{
|
||||||
|
action(this)(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
178
CS-MIC/csmic/csmic/Extensions/CSMICExtension.cs
Normal file
178
CS-MIC/csmic/csmic/Extensions/CSMICExtension.cs
Normal file
|
@ -0,0 +1,178 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic.Extensions
|
||||||
|
{
|
||||||
|
/// <summary> CS-MIC extension methods. </summary>
|
||||||
|
public static class CSMICExtension
|
||||||
|
{
|
||||||
|
#region String
|
||||||
|
|
||||||
|
/// <summary> A string extension method that interprets as input the string that calls it. </summary>
|
||||||
|
/// <param name="input"> The input to act on. </param>
|
||||||
|
/// <returns> The output from the interpretation of the string. </returns>
|
||||||
|
public static string Interpret(this string input)
|
||||||
|
{
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
interpreter.Interpret(input);
|
||||||
|
return interpreter.Output;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> A string extension method that executes as macro operation. </summary>
|
||||||
|
/// <param name="script"> The script to act on. </param>
|
||||||
|
/// <returns> The final output of the script. </returns>
|
||||||
|
public static string RunAsMacro(this string script)
|
||||||
|
{
|
||||||
|
MacroBuilder macro = new MacroBuilder(script, new InputInterpreter());
|
||||||
|
return macro.FinalOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable<string>
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A string extension method that interprets as input the string that calls it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="collection"> The collection to act on. </param>
|
||||||
|
/// <returns> The output from the interpretation of the string. </returns>
|
||||||
|
public static IEnumerable<string> Interpret(this IEnumerable<string> collection)
|
||||||
|
{
|
||||||
|
List<string> computed = new List<string>();
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
|
||||||
|
foreach (string input in collection)
|
||||||
|
{
|
||||||
|
interpreter.Interpret(input);
|
||||||
|
computed.Add(interpreter.Output);
|
||||||
|
}
|
||||||
|
|
||||||
|
return computed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A string extension method that interprets as input the string that calls it.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="collection"> The collection to act on. </param>
|
||||||
|
/// <param name="action"> The action. </param>
|
||||||
|
/// <returns> The output from the interpretation of the string. </returns>
|
||||||
|
public static IEnumerable<string> Interpret(this IEnumerable<string> collection, Action<InputInterpreter> action)
|
||||||
|
{
|
||||||
|
List<string> computed = new List<string>();
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
|
||||||
|
foreach (string input in collection)
|
||||||
|
{
|
||||||
|
interpreter.Interpret(input);
|
||||||
|
computed.Add(interpreter.Output);
|
||||||
|
action(interpreter);
|
||||||
|
}
|
||||||
|
|
||||||
|
return computed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Enumerates input in this collection, returning a selection on the interpreter. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <param name="collection"> The collection to act on. </param>
|
||||||
|
/// <param name="selection"> The selection. </param>
|
||||||
|
/// <returns>
|
||||||
|
/// An enumerator that allows foreach to be used to process interpret< t> in this
|
||||||
|
/// collection.
|
||||||
|
/// </returns>
|
||||||
|
public static IEnumerable<T> Interpret<T>(this IEnumerable<string> collection, Func<InputInterpreter, T> selection)
|
||||||
|
{
|
||||||
|
List<T> computed = new List<T>();
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
|
||||||
|
foreach (string input in collection)
|
||||||
|
{
|
||||||
|
interpreter.Interpret(input);
|
||||||
|
computed.Add(selection(interpreter));
|
||||||
|
}
|
||||||
|
|
||||||
|
return computed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> A string extension method that executes as macro operation. </summary>
|
||||||
|
/// <param name="collection"> The collection to act on. </param>
|
||||||
|
/// <returns> The final output of the script. </returns>
|
||||||
|
public static MacroBuilder RunAsMacro(this IEnumerable<string> collection)
|
||||||
|
{
|
||||||
|
return new MacroBuilder(string.Join(Environment.NewLine, collection.ToArray()), new InputInterpreter());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable<string> In Parallel
|
||||||
|
|
||||||
|
/// <summary> Enumerates input in parallel in this collection. </summary>
|
||||||
|
/// <param name="collection"> The collection to act on. </param>
|
||||||
|
/// <returns>
|
||||||
|
/// An enumerator that allows foreach to be used to process interpret in parallel in this
|
||||||
|
/// collection.
|
||||||
|
/// </returns>
|
||||||
|
public static IEnumerable<InputInterpreter> InterpretInParallel(this IEnumerable<string> collection)
|
||||||
|
{
|
||||||
|
ConcurrentBag<InputInterpreter> bag = new ConcurrentBag<InputInterpreter>();
|
||||||
|
|
||||||
|
collection.AsParallel().ForAll(input =>
|
||||||
|
{
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
interpreter.Interpret(input);
|
||||||
|
bag.Add(interpreter);
|
||||||
|
});
|
||||||
|
|
||||||
|
return bag;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Enumerates input in parallel this collection, returning a selection on the interpreter. </summary>
|
||||||
|
/// <typeparam name="T"> Generic type parameter. </typeparam>
|
||||||
|
/// <param name="collection"> The collection to act on. </param>
|
||||||
|
/// <param name="selection"> The selection. </param>
|
||||||
|
/// <returns>
|
||||||
|
/// An enumerator that allows foreach to be used to process interpret in parallel< t> in
|
||||||
|
/// this collection.
|
||||||
|
/// </returns>
|
||||||
|
public static IEnumerable<T> InterpretInParallel<T>(this IEnumerable<string> collection, Func<InputInterpreter, T> selection)
|
||||||
|
{
|
||||||
|
ConcurrentBag<T> bag = new ConcurrentBag<T>();
|
||||||
|
|
||||||
|
collection.AsParallel().ForAll(input =>
|
||||||
|
{
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
interpreter.Interpret(input);
|
||||||
|
bag.Add(selection(interpreter));
|
||||||
|
});
|
||||||
|
|
||||||
|
return bag;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ParallelQuery<string>
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A string extension method that interprets as input the strings that calls it in parallel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="collection"> The collection to act on. </param>
|
||||||
|
/// <returns> The output from the interpretation of the string. </returns>
|
||||||
|
public static IEnumerable<InputInterpreter> Interpret(this ParallelQuery<string> collection)
|
||||||
|
{
|
||||||
|
ConcurrentBag<InputInterpreter> bag = new ConcurrentBag<InputInterpreter>();
|
||||||
|
|
||||||
|
collection.ForAll(input =>
|
||||||
|
{
|
||||||
|
InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
interpreter.Interpret(input);
|
||||||
|
bag.Add(interpreter);
|
||||||
|
});
|
||||||
|
|
||||||
|
return bag;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
76
CS-MIC/csmic/csmic/GenericCodedFunction.cs
Normal file
76
CS-MIC/csmic/csmic/GenericCodedFunction.cs
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A generically coded implementation of the ICodedFunction interface.
|
||||||
|
/// </summary>
|
||||||
|
internal class GenericCodedFunction : ICodedFunction
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary> Number of expected arguments. </summary>
|
||||||
|
private int numExpectedArguments;
|
||||||
|
/// <summary> Name of the function. </summary>
|
||||||
|
private string functionName;
|
||||||
|
/// <summary> The method body. </summary>
|
||||||
|
private Func<decimal[], decimal> methodBody;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary> Constructor. </summary>
|
||||||
|
/// <param name="functionName"> Name of the function. </param>
|
||||||
|
/// <param name="NumExpectedArguments"> Number of expected arguments. </param>
|
||||||
|
/// <param name="methodBody"> The method body. </param>
|
||||||
|
internal GenericCodedFunction(string functionName, int numExpectedArguments, Func<decimal[], decimal> methodBody)
|
||||||
|
{
|
||||||
|
this.functionName = functionName;
|
||||||
|
this.numExpectedArguments = numExpectedArguments;
|
||||||
|
this.methodBody = methodBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region ICodedFunction Members
|
||||||
|
|
||||||
|
/// <summary> Gets the number of expected arguments. </summary>
|
||||||
|
/// <value> The total number of expected arguments. </value>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.numExpectedArguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets the name of the function. </summary>
|
||||||
|
/// <value> The name of the function. </value>
|
||||||
|
public string FunctionName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.functionName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Executes a code block that computes the value of the function. </summary>
|
||||||
|
/// <param name="args"> A variable-length parameters list containing arguments. </param>
|
||||||
|
/// <returns> The decimal value computed by the function. </returns>
|
||||||
|
public decimal Execute(params decimal[] args)
|
||||||
|
{
|
||||||
|
if (this.methodBody != null)
|
||||||
|
{
|
||||||
|
return this.methodBody(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new MissingMethodException(this.GetType().Name, this.functionName);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
73
CS-MIC/csmic/csmic/ICodedFunction.cs
Normal file
73
CS-MIC/csmic/csmic/ICodedFunction.cs
Normal file
|
@ -0,0 +1,73 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Implements a function that is coded in the .Net environment.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>This interface is required to implement a method or function
|
||||||
|
/// that can be used by the CS-MIC inputInterpreter. It is worth noting that the
|
||||||
|
/// function's name will be the text that is used in the inputInterpreter as the
|
||||||
|
/// executable text.</remarks>
|
||||||
|
public interface ICodedFunction
|
||||||
|
{
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of expected arguments.
|
||||||
|
/// </summary>
|
||||||
|
int NumExpectedArguments { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the function.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The input inputInterpreter will use this function name as
|
||||||
|
/// executable text, expecting an opening and closing parenthesis following
|
||||||
|
/// it.</remarks>
|
||||||
|
string FunctionName { get; }
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a code block that computes the value of the function.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">An array of arguments passed to the function.</param>
|
||||||
|
/// <returns>The decimal value computed by the function.</returns>
|
||||||
|
/// <remarks>Any code block is valid. Error handling must be done by the
|
||||||
|
/// developer, as the inputInterpreter cannot determine if there is an error.</remarks>
|
||||||
|
/// <example>
|
||||||
|
/// This example shows how to implement the sine function through the interface's
|
||||||
|
/// Execute() function.
|
||||||
|
/// <code>
|
||||||
|
/// public decimal Execute(params decimal[] args)
|
||||||
|
///{
|
||||||
|
/// //Set up an output variable.
|
||||||
|
/// decimal output = 0;
|
||||||
|
///
|
||||||
|
/// //Check to see if the number or arguments recieved
|
||||||
|
/// //is equal to the number of arguments expected.
|
||||||
|
/// if (args.Length == this.NumExpectedArguments)
|
||||||
|
/// {
|
||||||
|
/// //Grab the argument and set a local variable for clarity.
|
||||||
|
/// decimal input = args[0];
|
||||||
|
///
|
||||||
|
/// //Set the output as a sine of the input.
|
||||||
|
/// output = (decimal)Math.Sin((double)input);
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// //Return the output. The function will return the sine if the arguments
|
||||||
|
/// //matched what was expected, and will return 0 otherwise. Returning 0 on
|
||||||
|
/// //errors is the standard in CS-MIC.
|
||||||
|
/// return output;
|
||||||
|
///}
|
||||||
|
///</code>
|
||||||
|
///</example>
|
||||||
|
decimal Execute(params decimal[] args);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
502
CS-MIC/csmic/csmic/InputInterpreter.cs
Normal file
502
CS-MIC/csmic/csmic/InputInterpreter.cs
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using csmic.CodedFunctions;
|
||||||
|
using csmic.Interpreter;
|
||||||
|
using csmic.ComputableEngine;
|
||||||
|
using System.Runtime.Remoting.Messaging;
|
||||||
|
|
||||||
|
// namespace: csmic
|
||||||
|
//
|
||||||
|
// summary: .
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An interpreter object that reads user input and evaluates the code.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>The interpreter does not support exceptions by design. Instead, invalid
|
||||||
|
/// calculations, parameters, etc. will result in a result of zero.
|
||||||
|
/// <code>
|
||||||
|
/// InputInterpreter interpreter = new InputInterpreter();
|
||||||
|
/// interpreter.Interpret("1/0"); // The result will be 0, not an exception.
|
||||||
|
/// </code>
|
||||||
|
/// </remarks>
|
||||||
|
public class InputInterpreter
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The output generated.
|
||||||
|
/// </summary>
|
||||||
|
private string output;
|
||||||
|
/// <summary>
|
||||||
|
/// The variables assigned.
|
||||||
|
/// </summary>
|
||||||
|
internal Dictionary<string, Variable> variables;
|
||||||
|
/// <summary>
|
||||||
|
/// The time for execution.
|
||||||
|
/// </summary>
|
||||||
|
private TimeSpan executionTime;
|
||||||
|
/// <summary>
|
||||||
|
/// The verbose message of the calculation.
|
||||||
|
/// </summary>
|
||||||
|
private string message;
|
||||||
|
/// <summary>
|
||||||
|
/// The list of coded functions that can be executed.
|
||||||
|
/// </summary>
|
||||||
|
private List<ICodedFunction> codedFunctions;
|
||||||
|
/// <summary>
|
||||||
|
/// The list of user defined functions that can be executed.
|
||||||
|
/// </summary>
|
||||||
|
private List<InterpretedFunction> interpretedFunctions;
|
||||||
|
/// <summary>
|
||||||
|
/// The private calculated value.
|
||||||
|
/// </summary>
|
||||||
|
private decimal calculatedValue;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new InputInterpreter.
|
||||||
|
/// </summary>
|
||||||
|
public InputInterpreter()
|
||||||
|
{
|
||||||
|
this.output = string.Empty;
|
||||||
|
this.variables = new Dictionary<string, Variable>();
|
||||||
|
this.executionTime = new TimeSpan();
|
||||||
|
this.codedFunctions = new List<ICodedFunction>();
|
||||||
|
this.interpretedFunctions = new List<InterpretedFunction>();
|
||||||
|
LoadDefaultCodedFunctions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new InputInterpreter from an original.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="original">The orginal input interpreter to copy.</param>
|
||||||
|
public InputInterpreter(InputInterpreter original)
|
||||||
|
{
|
||||||
|
this.output = original.output;
|
||||||
|
this.variables = original.variables;
|
||||||
|
this.executionTime = original.executionTime;
|
||||||
|
this.codedFunctions = original.codedFunctions;
|
||||||
|
this.interpretedFunctions = original.interpretedFunctions;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the message that represents the InputInterpreters output.
|
||||||
|
/// </summary>
|
||||||
|
public string Output
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the verbose message that is generated with a calculation.
|
||||||
|
/// </summary>
|
||||||
|
public string Message
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the output as a decimal.
|
||||||
|
/// </summary>
|
||||||
|
public decimal Decimal
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.calculatedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the output cast as an int.
|
||||||
|
/// </summary>
|
||||||
|
public int Int
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (int)decimal.Round(this.calculatedValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the output cast as a float.
|
||||||
|
/// </summary>
|
||||||
|
public float Float
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (float)this.calculatedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the output cast as a double.
|
||||||
|
/// </summary>
|
||||||
|
public double Double
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (double)this.calculatedValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value (cast as a long) converted to its binary equivalent.
|
||||||
|
/// </summary>
|
||||||
|
public string Binary
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Convert.ToString((long)this.calculatedValue, 2).PadLeft(64, '0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the execution time of the last calculation.
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan LastExecutionTime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.executionTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a list of coded functions that the interpreter supports.
|
||||||
|
/// </summary>
|
||||||
|
public List<ICodedFunction> CodedFunctions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.codedFunctions;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.codedFunctions = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets a list of user generated interpreted functions that the interpreter supports.
|
||||||
|
/// </summary>
|
||||||
|
/// <value> The interpreted functions. </value>
|
||||||
|
public List<InterpretedFunction> InterpretedFunctions
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.interpretedFunctions;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.interpretedFunctions = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Gets the variables. </summary>
|
||||||
|
/// <value> The variables. </value>
|
||||||
|
public Dictionary<string, Variable> Variables
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.variables;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.variables = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Interprets and executes given input.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="input">The input to interpret and execute.</param>
|
||||||
|
public void Interpret(string input)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(input))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime timeStart = DateTime.Now;
|
||||||
|
this.message = string.Empty;
|
||||||
|
|
||||||
|
UTF8Encoding encoder = new UTF8Encoding();
|
||||||
|
Parser p = new Parser(new Scanner(new MemoryStream(encoder.GetBytes(input))));
|
||||||
|
p.Interpreter = this;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
p.Parse();
|
||||||
|
this.calculatedValue = p.CalculatedValue;
|
||||||
|
if (p.errors.count > 0)
|
||||||
|
{
|
||||||
|
ProduceOutput(this.calculatedValue, p.errors.builder.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
this.calculatedValue = 0;
|
||||||
|
ProduceOutput(this.calculatedValue, e.Message);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime timeEnd = DateTime.Now;
|
||||||
|
this.executionTime = timeEnd - timeStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes an expression and returns the result as a decimal.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="expression">The expression to be calculated.</param>
|
||||||
|
/// <returns>The value that was computed.</returns>
|
||||||
|
public decimal ComputeExpression(string expression)
|
||||||
|
{
|
||||||
|
this.Interpret(expression);
|
||||||
|
return this.calculatedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assigns a decimal value to a variable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the variable.</param>
|
||||||
|
/// <param name="value">The value of the variable.</param>
|
||||||
|
/// <returns>True if the variable was set, false otherwise.</returns>
|
||||||
|
internal bool Assign(string name, decimal value)
|
||||||
|
{
|
||||||
|
Variable v = new Variable();
|
||||||
|
v.Type = VariableType.Decimal;
|
||||||
|
v.Value = value;
|
||||||
|
|
||||||
|
if (!this.variables.ContainsKey(name))
|
||||||
|
{
|
||||||
|
this.variables.Add(name, v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.variables[name] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assigns a decimal value to a variable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the variable.</param>
|
||||||
|
/// <param name="expression">The expression of the variable.</param>
|
||||||
|
/// <returns>True if the variable was set, false otherwise.</returns>
|
||||||
|
internal bool Assign(string name, string expression)
|
||||||
|
{
|
||||||
|
Variable v = new Variable();
|
||||||
|
v.Type = VariableType.Equation;
|
||||||
|
v.Value = expression;
|
||||||
|
|
||||||
|
if (!this.variables.ContainsKey(name))
|
||||||
|
{
|
||||||
|
this.variables.Add(name, v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.variables[name] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Assigns a decimal value to a variable.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the variable.</param>
|
||||||
|
/// <param name="values">The values of the variable.</param>
|
||||||
|
/// <returns>True if the variable was set, false otherwise.</returns>
|
||||||
|
internal bool Assign(string name, decimal[] values)
|
||||||
|
{
|
||||||
|
Variable v = new Variable();
|
||||||
|
v.Type = VariableType.Array;
|
||||||
|
v.Value = values;
|
||||||
|
|
||||||
|
if (!this.variables.ContainsKey(name))
|
||||||
|
{
|
||||||
|
this.variables.Add(name, v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.variables[name] = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a function stored in the interpreter.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the function to execute.</param>
|
||||||
|
/// <param name="args">The arguments to pass to the function.</param>
|
||||||
|
/// <returns>The value computed from the function execution.</returns>
|
||||||
|
internal decimal ExecuteFunction(string name, decimal[] args)
|
||||||
|
{
|
||||||
|
foreach (ICodedFunction codedFunction in this.codedFunctions)
|
||||||
|
{
|
||||||
|
if (codedFunction.FunctionName == name)
|
||||||
|
{
|
||||||
|
return codedFunction.Execute(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (InterpretedFunction interpretedFunction in this.interpretedFunctions)
|
||||||
|
{
|
||||||
|
if (interpretedFunction.Name == name)
|
||||||
|
{
|
||||||
|
string answer = interpretedFunction.Compute(args);
|
||||||
|
decimal parsed = 0;
|
||||||
|
if (decimal.TryParse(answer, out parsed))
|
||||||
|
{
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loads the default coded functions supported by the interpreter.
|
||||||
|
/// </summary>
|
||||||
|
private void LoadDefaultCodedFunctions()
|
||||||
|
{
|
||||||
|
this.codedFunctions.Add(new CF_Sin());
|
||||||
|
this.codedFunctions.Add(new CF_Cos());
|
||||||
|
this.codedFunctions.Add(new CF_Tan());
|
||||||
|
this.codedFunctions.Add(new CF_Round());
|
||||||
|
this.codedFunctions.Add(new CF_Sqrt());
|
||||||
|
this.codedFunctions.Add(new CF_Abs());
|
||||||
|
this.codedFunctions.Add(new CF_Exp());
|
||||||
|
this.codedFunctions.Add(new CF_Log());
|
||||||
|
this.codedFunctions.Add(new CF_Precision());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Produces output given a single object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="output">The object representing the output.</param>
|
||||||
|
internal void ProduceOutput(object output)
|
||||||
|
{
|
||||||
|
if (output is bool)
|
||||||
|
{
|
||||||
|
bool o = (bool)output;
|
||||||
|
if (o)
|
||||||
|
{
|
||||||
|
this.calculatedValue = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.calculatedValue = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.output = string.Format("{0}", output);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Produces output given an object and a message.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="output">The object representing the output.</param>
|
||||||
|
/// <param name="message">The message to be displayed with the output.</param>
|
||||||
|
private void ProduceOutput(object output, string message)
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(message))
|
||||||
|
{
|
||||||
|
this.output = string.Format("{0}", output);
|
||||||
|
this.message = message;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ProduceOutput(output);
|
||||||
|
this.message = string.Empty;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Asynchronous
|
||||||
|
|
||||||
|
/// <summary> Interpret an input asynchronously. </summary>
|
||||||
|
/// <param name="input"> The input to interpret and execute. </param>
|
||||||
|
/// <param name="callback"> The callback. </param>
|
||||||
|
public void InterpretAsync(string input, Action<InputInterpreter> callback)
|
||||||
|
{
|
||||||
|
InterpretAsyncDelegate del = new InterpretAsyncDelegate(InterpretAsyncThreadingWork);
|
||||||
|
del.BeginInvoke(input, (result) =>
|
||||||
|
{
|
||||||
|
AsyncResult returned = result as AsyncResult;
|
||||||
|
if (returned != null)
|
||||||
|
{
|
||||||
|
InterpretAsyncDelegate end = returned.AsyncDelegate as InterpretAsyncDelegate;
|
||||||
|
if (end != null)
|
||||||
|
{
|
||||||
|
InputInterpreter returnValue = end.EndInvoke(result);
|
||||||
|
callback(returnValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Interpret asynchronous threading work. </summary>
|
||||||
|
/// <param name="input"> The input to interpret and execute. </param>
|
||||||
|
private InputInterpreter InterpretAsyncThreadingWork(string input)
|
||||||
|
{
|
||||||
|
Interpret(input);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Interpret asynchronous delegate. </summary>
|
||||||
|
/// <param name="input"> The input. </param>
|
||||||
|
/// <returns> . </returns>
|
||||||
|
private delegate InputInterpreter InterpretAsyncDelegate(string input);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Computable
|
||||||
|
|
||||||
|
/// <summary> Converts this object to a computable. </summary>
|
||||||
|
/// <returns> This object as a Computable. </returns>
|
||||||
|
public Computable ToComputable()
|
||||||
|
{
|
||||||
|
return new Computable(this.Decimal.ToString(), this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Treats the current object as a computable and performs an action in that context. </summary>
|
||||||
|
/// <param name="action"> The action to execute as a computable object. </param>
|
||||||
|
/// <returns> This object as a Computable, after the given action. </returns>
|
||||||
|
public Computable AsComputable(Func<Computable, Computable> action)
|
||||||
|
{
|
||||||
|
return action(this.ToComputable());
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
151
CS-MIC/csmic/csmic/InterpretedFunction.cs
Normal file
151
CS-MIC/csmic/csmic/InterpretedFunction.cs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a user defined function that can be executed by the interpreter.
|
||||||
|
/// </summary>
|
||||||
|
public class InterpretedFunction
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the function.
|
||||||
|
/// </summary>
|
||||||
|
private string name;
|
||||||
|
/// <summary>
|
||||||
|
/// The number of expected arguments.
|
||||||
|
/// </summary>
|
||||||
|
private int numExpectedArguments;
|
||||||
|
/// <summary>
|
||||||
|
/// The set of instructions to be passed to the internal inputInterpreter.
|
||||||
|
/// </summary>
|
||||||
|
private MacroOperation script;
|
||||||
|
/// <summary>
|
||||||
|
/// A set of arguments used in computation of the function.
|
||||||
|
/// </summary>
|
||||||
|
private InterpretedFunctionArgument[] arguments;
|
||||||
|
/// <summary>
|
||||||
|
/// The internal macro builder used for computation.
|
||||||
|
/// </summary>
|
||||||
|
private MacroBuilder macroFunction;
|
||||||
|
/// <summary>
|
||||||
|
/// The internal input inputInterpreter that macro builder will use for computation.
|
||||||
|
/// </summary>
|
||||||
|
private InputInterpreter interpreter;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new interpreted function.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the fuction.</param>
|
||||||
|
/// <param name="script">The node to be used in computation.</param>
|
||||||
|
/// <param name="args">A set of argument names to be used in computation.</param>
|
||||||
|
internal InterpretedFunction(string name, MacroOperation script, params string[] args)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.script = script;
|
||||||
|
this.macroFunction = null;
|
||||||
|
this.arguments = new InterpretedFunctionArgument[args.Length];
|
||||||
|
this.interpreter = new InputInterpreter();
|
||||||
|
this.numExpectedArguments = args.Length;
|
||||||
|
|
||||||
|
for (int i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
this.arguments[i] = new InterpretedFunctionArgument(args[i], 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name of the function.
|
||||||
|
/// </summary>
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the number of expected arguments for the function.
|
||||||
|
/// </summary>
|
||||||
|
public int NumExpectedArguments
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.numExpectedArguments;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Computes the value of the function.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="args">The arguments used for computation.</param>
|
||||||
|
/// <returns>The decimal value computed by the function.</returns>
|
||||||
|
public string Compute(params decimal[] args)
|
||||||
|
{
|
||||||
|
if (args.Length != this.numExpectedArguments)
|
||||||
|
{
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (args.Length == this.arguments.Length)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < args.Length; i++)
|
||||||
|
{
|
||||||
|
this.arguments[i].Value = args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (InterpretedFunctionArgument argument in this.arguments)
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(string.Format("{0} :: {1}", argument.Name, argument.Value));
|
||||||
|
}
|
||||||
|
|
||||||
|
this.macroFunction = new MacroBuilder(this.script, this.interpreter);
|
||||||
|
|
||||||
|
return this.macroFunction.FinalOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Because a function's internal pattern may be different, we must manually check to see if the function
|
||||||
|
/// names are the same.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to test.</param>
|
||||||
|
/// <returns>True if the functions are the same.</returns>
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
InterpretedFunction fun = obj as InterpretedFunction;
|
||||||
|
if(fun != null)
|
||||||
|
{
|
||||||
|
return fun.name == this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Serves as a hash function for a particular type. </summary>
|
||||||
|
/// <returns> A hash code for the current <see cref="T:System.Object" />. </returns>
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
return this.script.GetHashCode() & this.name.GetHashCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
84
CS-MIC/csmic/csmic/InterpretedFunctionArgument.cs
Normal file
84
CS-MIC/csmic/csmic/InterpretedFunctionArgument.cs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an argument made in an interpreted function.
|
||||||
|
/// </summary>
|
||||||
|
public class InterpretedFunctionArgument
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the argument.
|
||||||
|
/// </summary>
|
||||||
|
private string name;
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the argument.
|
||||||
|
/// </summary>
|
||||||
|
private decimal value;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructors
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new interpreted function argument.
|
||||||
|
/// </summary>
|
||||||
|
public InterpretedFunctionArgument()
|
||||||
|
{
|
||||||
|
this.name = string.Empty;
|
||||||
|
this.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new interpreted function argument.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name of the argument in the interpreted function.</param>
|
||||||
|
/// <param name="value">The value of the argument to use in the interpreted function.</param>
|
||||||
|
public InterpretedFunctionArgument(string name, decimal value)
|
||||||
|
{
|
||||||
|
this.name = name;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the name of the argument.
|
||||||
|
/// </summary>
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.name = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the value of the argument.
|
||||||
|
/// </summary>
|
||||||
|
public decimal Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
369
CS-MIC/csmic/csmic/InterpreterParser/CSMIC.atg
Normal file
369
CS-MIC/csmic/csmic/InterpreterParser/CSMIC.atg
Normal file
|
@ -0,0 +1,369 @@
|
||||||
|
using csmic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
COMPILER CSMIC
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Class Structures
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
private decimal calcValue = 0;
|
||||||
|
private string stringValue = string.Empty;
|
||||||
|
|
||||||
|
public decimal CalculatedValue
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.calcValue;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.calcValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputInterpreter interpreter = null;
|
||||||
|
|
||||||
|
public InputInterpreter Interpreter
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.interpreter;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.interpreter = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFunctionCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _LPAREN && la.kind == _identifier)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompare()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _COMPARER)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAssignment()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.val == "::" || next.val == ":=" || next.val == "->")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsArrayCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if(next.val == "[")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTERS
|
||||||
|
|
||||||
|
UpperLetter = 'A'..'Z'.
|
||||||
|
LowerLetter = 'a'..'z'.
|
||||||
|
letter = UpperLetter + LowerLetter.
|
||||||
|
digit = "0123456789" .
|
||||||
|
cr = '\r' .
|
||||||
|
lf = '\n' .
|
||||||
|
tab = '\t' .
|
||||||
|
PM = "+-" .
|
||||||
|
NoQuote = ANY - '\"' .
|
||||||
|
|
||||||
|
TOKENS
|
||||||
|
|
||||||
|
identifier = letter { letter | digit}.
|
||||||
|
sign = PM .
|
||||||
|
binary = ( '0' | '1' ) { '0' | '1' } ('B' | 'b') .
|
||||||
|
hex = "0x" ( digit | ('A' | 'B' | 'C' | 'D' | 'E' |'F') | ('a' | 'b' | 'c' | 'd' | 'e' |'f') ) { digit | ('A' | 'B' | 'C' | 'D' | 'E' |'F') | ('a' | 'b' | 'c' | 'd' | 'e' |'f') } .
|
||||||
|
number = digit { digit }['.' {digit}] [('E'|'e')['+'|'-'] digit {digit}] .
|
||||||
|
string = "\"" { NoQuote } "\"" .
|
||||||
|
LPAREN = '(' .
|
||||||
|
RPAREN = ')' .
|
||||||
|
COMPARER = "==" | "<" | ">" | "<=" | ">=" .
|
||||||
|
|
||||||
|
IGNORE cr + tab
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parser specification
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
PRODUCTIONS
|
||||||
|
|
||||||
|
CSMIC (. decimal r = 0;
|
||||||
|
string s = string.Empty;
|
||||||
|
decimal[] a = new decimal[0];
|
||||||
|
bool success = true;
|
||||||
|
if(this.interpreter == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
IF(IsCompare())
|
||||||
|
Comparison<out success> (. this.calcValue = (success == true) ? 1 : 0; this.interpreter.ProduceOutput(success); .)
|
||||||
|
|
|
||||||
|
IF(IsAssignment())
|
||||||
|
Assignment<out r> (. this.calcValue = r; .)
|
||||||
|
|
|
||||||
|
Expression<out r> (. this.calcValue = r; this.interpreter.ProduceOutput(r); .)
|
||||||
|
|
|
||||||
|
String<out s> (. this.stringValue = s; this.interpreter.ProduceOutput(s); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
String<out string s>
|
||||||
|
=
|
||||||
|
string (. s = t.val; .)
|
||||||
|
|
||||||
|
.
|
||||||
|
|
||||||
|
Expression<out decimal r>
|
||||||
|
=
|
||||||
|
(. decimal r1; .)
|
||||||
|
Term<out r>
|
||||||
|
{
|
||||||
|
'+' Term<out r1> (. r += r1; .)
|
||||||
|
|
|
||||||
|
'-' Term<out r1> (. r -= r1; .)
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Term<out decimal r> (. decimal r1; .)
|
||||||
|
=
|
||||||
|
Factor<out r>
|
||||||
|
{
|
||||||
|
'*'
|
||||||
|
Factor<out r1> (. r *= r1; .)
|
||||||
|
|
|
||||||
|
'/'
|
||||||
|
Factor<out r1> (. r /= r1; .)
|
||||||
|
|
|
||||||
|
'%' Term<out r1> (. r %= r1; .)
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Factor<out decimal r> (. decimal r1; .)
|
||||||
|
=
|
||||||
|
Value<out r>
|
||||||
|
{
|
||||||
|
'^'
|
||||||
|
Expression<out r1> (. r = Convert.ToDecimal(Math.Pow(Convert.ToDouble(r), Convert.ToDouble(r1))); .)
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Value<out decimal r> (. r = 0;
|
||||||
|
decimal r1 = 0;
|
||||||
|
string fn;
|
||||||
|
int sign = 1;.)
|
||||||
|
=
|
||||||
|
|
||||||
|
[
|
||||||
|
"+"
|
||||||
|
|
|
||||||
|
"-" (. sign = -1; .)
|
||||||
|
]
|
||||||
|
(
|
||||||
|
IF(IsFunctionCall())
|
||||||
|
Function<out r> (. r = sign * r; .)
|
||||||
|
|
|
||||||
|
IF(IsArrayCall())
|
||||||
|
ArrayCall<out r> (. r = sign * r; .)
|
||||||
|
|
|
||||||
|
identifier (. if(this.interpreter.variables.ContainsKey(t.val))
|
||||||
|
{
|
||||||
|
Variable v = this.interpreter.variables[t.val];
|
||||||
|
if(v.Type == VariableType.Equation)
|
||||||
|
{
|
||||||
|
InputInterpreter i = new InputInterpreter(this.interpreter);
|
||||||
|
i.Interpret(v.Value.ToString());
|
||||||
|
r = i.Decimal;
|
||||||
|
}
|
||||||
|
else if(v.Type == VariableType.Decimal)
|
||||||
|
{
|
||||||
|
r = Convert.ToDecimal(v.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
number (. r = sign * Convert.ToDecimal (t.val); .)
|
||||||
|
|
|
||||||
|
hex (. string expression = t.val.Remove(0,2);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
decimal value = Convert.ToDecimal(Convert.ToInt64(expression, 16));
|
||||||
|
r = sign * value;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
binary (. string expression = t.val.Remove(t.val.Length - 1);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
decimal value = Convert.ToDecimal(Convert.ToInt64(expression, 2));
|
||||||
|
r = sign * value;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
'('
|
||||||
|
Expression<out r>
|
||||||
|
')' (. r = sign * r; .)
|
||||||
|
)
|
||||||
|
.
|
||||||
|
|
||||||
|
ArrayL<out decimal[] d>
|
||||||
|
=
|
||||||
|
'['
|
||||||
|
CommaList<out d>
|
||||||
|
']'
|
||||||
|
.
|
||||||
|
|
||||||
|
ArrayCall<out decimal r> (. string ident = string.Empty; r = 0; decimal pos = 0; .)
|
||||||
|
=
|
||||||
|
identifier (. ident = t.val; .)
|
||||||
|
'['
|
||||||
|
Expression<out pos> (. int i = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
i = Convert.ToInt32(pos);
|
||||||
|
if(this.interpreter.variables.ContainsKey(ident))
|
||||||
|
{
|
||||||
|
decimal[] values = this.interpreter.variables[ident].Value as decimal[];
|
||||||
|
if(values != null)
|
||||||
|
{
|
||||||
|
r = values[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
']'
|
||||||
|
.
|
||||||
|
|
||||||
|
CommaList<out decimal[] d> (. List<decimal> list = new List<decimal>(); decimal r = 0; .)
|
||||||
|
=
|
||||||
|
Expression<out r> (. list.Add(r); d = list.ToArray(); .)
|
||||||
|
{
|
||||||
|
','
|
||||||
|
Expression<out r> (. list.Add(r); d = list.ToArray(); .)
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Assignment<out decimal r> (.
|
||||||
|
string identifier = string.Empty;
|
||||||
|
string expression = string.Empty;
|
||||||
|
decimal[] d = new decimal[0];
|
||||||
|
r = 0;
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
identifier (. identifier = t.val; .)
|
||||||
|
(
|
||||||
|
(
|
||||||
|
"::"
|
||||||
|
Expression<out r> (. this.interpreter.Assign(identifier, r); .)
|
||||||
|
(. this.interpreter.ProduceOutput(r); .)
|
||||||
|
)
|
||||||
|
|
|
||||||
|
(
|
||||||
|
":="
|
||||||
|
AnyExpression<out expression> (. this.interpreter.Assign(identifier, expression); .)
|
||||||
|
(. this.interpreter.ProduceOutput(expression); .)
|
||||||
|
)
|
||||||
|
|
|
||||||
|
(
|
||||||
|
"->"
|
||||||
|
ArrayL<out d> (. this.interpreter.Assign(identifier, d); r = 0; .)
|
||||||
|
(.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
foreach(decimal dec in d)
|
||||||
|
{
|
||||||
|
builder.Append("," + dec.ToString());
|
||||||
|
}
|
||||||
|
builder.Remove(0,1);
|
||||||
|
this.interpreter.ProduceOutput(builder.ToString());
|
||||||
|
.)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.
|
||||||
|
|
||||||
|
Function<out decimal r> (.
|
||||||
|
string functionName = string.Empty;
|
||||||
|
decimal[] d = new decimal[0];
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
identifier (. functionName = t.val; .)
|
||||||
|
'('
|
||||||
|
CommaList<out d>
|
||||||
|
')' (. r = this.interpreter.ExecuteFunction(functionName, d); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
Comparison<out bool result> (.
|
||||||
|
decimal firstValue = 0;
|
||||||
|
decimal secondValue = 0;
|
||||||
|
string compareType = string.Empty;
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
Expression<out firstValue>
|
||||||
|
COMPARER (. compareType = t.val; .)
|
||||||
|
Expression<out secondValue> (.
|
||||||
|
switch(compareType)
|
||||||
|
{
|
||||||
|
case "==":
|
||||||
|
result = (firstValue == secondValue);
|
||||||
|
break;
|
||||||
|
case ">":
|
||||||
|
result = (firstValue > secondValue);
|
||||||
|
break;
|
||||||
|
case "<":
|
||||||
|
result = (firstValue < secondValue);
|
||||||
|
break;
|
||||||
|
case ">=":
|
||||||
|
result = (firstValue >= secondValue);
|
||||||
|
break;
|
||||||
|
case "<=":
|
||||||
|
result = (firstValue <= secondValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
AnyExpression<out string value> (. value = string.Empty; StringBuilder builder = new StringBuilder(); .)
|
||||||
|
=
|
||||||
|
ANY (. builder.Append(t.val); .) { ANY (. builder.Append(t.val); .) } (. value = builder.ToString(); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
END CSMIC.
|
534
CS-MIC/csmic/csmic/InterpreterParser/Parser.cs
Normal file
534
CS-MIC/csmic/csmic/InterpreterParser/Parser.cs
Normal file
|
@ -0,0 +1,534 @@
|
||||||
|
using csmic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
namespace csmic.Interpreter {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Parser {
|
||||||
|
public const int _EOF = 0;
|
||||||
|
public const int _identifier = 1;
|
||||||
|
public const int _sign = 2;
|
||||||
|
public const int _binary = 3;
|
||||||
|
public const int _hex = 4;
|
||||||
|
public const int _number = 5;
|
||||||
|
public const int _string = 6;
|
||||||
|
public const int _LPAREN = 7;
|
||||||
|
public const int _RPAREN = 8;
|
||||||
|
public const int _COMPARER = 9;
|
||||||
|
public const int maxT = 22;
|
||||||
|
|
||||||
|
const bool T = true;
|
||||||
|
const bool x = false;
|
||||||
|
const int minErrDist = 2;
|
||||||
|
|
||||||
|
public Scanner scanner;
|
||||||
|
public Errors errors;
|
||||||
|
|
||||||
|
public Token t; // last recognized token
|
||||||
|
public Token la; // lookahead token
|
||||||
|
int errDist = minErrDist;
|
||||||
|
|
||||||
|
private decimal calcValue = 0;
|
||||||
|
private string stringValue = string.Empty;
|
||||||
|
|
||||||
|
public decimal CalculatedValue
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.calcValue;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.calcValue = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputInterpreter interpreter = null;
|
||||||
|
|
||||||
|
public InputInterpreter Interpreter
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.interpreter;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.interpreter = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFunctionCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _LPAREN && la.kind == _identifier)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompare()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _COMPARER)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAssignment()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.val == "::" || next.val == ":=" || next.val == "->")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsArrayCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if(next.val == "[")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Parser(Scanner scanner) {
|
||||||
|
this.scanner = scanner;
|
||||||
|
errors = new Errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynErr (int n) {
|
||||||
|
if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string msg) {
|
||||||
|
if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Get () {
|
||||||
|
for (;;) {
|
||||||
|
t = la;
|
||||||
|
la = scanner.Scan();
|
||||||
|
if (la.kind <= maxT) { ++errDist; break; }
|
||||||
|
|
||||||
|
la = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expect (int n) {
|
||||||
|
if (la.kind==n) Get(); else { SynErr(n); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartOf (int s) {
|
||||||
|
return set[s, la.kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpectWeak (int n, int follow) {
|
||||||
|
if (la.kind == n) Get();
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!StartOf(follow)) Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WeakSeparator(int n, int syFol, int repFol) {
|
||||||
|
int kind = la.kind;
|
||||||
|
if (kind == n) {Get(); return true;}
|
||||||
|
else if (StartOf(repFol)) {return false;}
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
|
||||||
|
Get();
|
||||||
|
kind = la.kind;
|
||||||
|
}
|
||||||
|
return StartOf(syFol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CSMIC() {
|
||||||
|
decimal r = 0;
|
||||||
|
string s = string.Empty;
|
||||||
|
decimal[] a = new decimal[0];
|
||||||
|
bool success = true;
|
||||||
|
if(this.interpreter == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsCompare()) {
|
||||||
|
Comparison(out success);
|
||||||
|
this.calcValue = (success == true) ? 1 : 0; this.interpreter.ProduceOutput(success);
|
||||||
|
} else if (IsAssignment()) {
|
||||||
|
Assignment(out r);
|
||||||
|
this.calcValue = r;
|
||||||
|
} else if (StartOf(1)) {
|
||||||
|
Expression(out r);
|
||||||
|
this.calcValue = r; this.interpreter.ProduceOutput(r);
|
||||||
|
} else if (la.kind == 6) {
|
||||||
|
String(out s);
|
||||||
|
this.stringValue = s; this.interpreter.ProduceOutput(s);
|
||||||
|
} else SynErr(23);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Comparison(out bool result) {
|
||||||
|
decimal firstValue = 0;
|
||||||
|
decimal secondValue = 0;
|
||||||
|
string compareType = string.Empty;
|
||||||
|
|
||||||
|
Expression(out firstValue);
|
||||||
|
Expect(9);
|
||||||
|
compareType = t.val;
|
||||||
|
Expression(out secondValue);
|
||||||
|
switch(compareType)
|
||||||
|
{
|
||||||
|
case "==":
|
||||||
|
result = (firstValue == secondValue);
|
||||||
|
break;
|
||||||
|
case ">":
|
||||||
|
result = (firstValue > secondValue);
|
||||||
|
break;
|
||||||
|
case "<":
|
||||||
|
result = (firstValue < secondValue);
|
||||||
|
break;
|
||||||
|
case ">=":
|
||||||
|
result = (firstValue >= secondValue);
|
||||||
|
break;
|
||||||
|
case "<=":
|
||||||
|
result = (firstValue <= secondValue);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assignment(out decimal r) {
|
||||||
|
string identifier = string.Empty;
|
||||||
|
string expression = string.Empty;
|
||||||
|
decimal[] d = new decimal[0];
|
||||||
|
r = 0;
|
||||||
|
|
||||||
|
Expect(1);
|
||||||
|
identifier = t.val;
|
||||||
|
if (la.kind == 19) {
|
||||||
|
Get();
|
||||||
|
Expression(out r);
|
||||||
|
this.interpreter.Assign(identifier, r);
|
||||||
|
this.interpreter.ProduceOutput(r);
|
||||||
|
} else if (la.kind == 20) {
|
||||||
|
Get();
|
||||||
|
AnyExpression(out expression);
|
||||||
|
this.interpreter.Assign(identifier, expression);
|
||||||
|
this.interpreter.ProduceOutput(expression);
|
||||||
|
} else if (la.kind == 21) {
|
||||||
|
Get();
|
||||||
|
ArrayL(out d);
|
||||||
|
this.interpreter.Assign(identifier, d); r = 0;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
foreach(decimal dec in d)
|
||||||
|
{
|
||||||
|
builder.Append("," + dec.ToString());
|
||||||
|
}
|
||||||
|
builder.Remove(0,1);
|
||||||
|
this.interpreter.ProduceOutput(builder.ToString());
|
||||||
|
|
||||||
|
} else SynErr(24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expression(out decimal r) {
|
||||||
|
decimal r1;
|
||||||
|
Term(out r);
|
||||||
|
while (la.kind == 10 || la.kind == 11) {
|
||||||
|
if (la.kind == 10) {
|
||||||
|
Get();
|
||||||
|
Term(out r1);
|
||||||
|
r += r1;
|
||||||
|
} else {
|
||||||
|
Get();
|
||||||
|
Term(out r1);
|
||||||
|
r -= r1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void String(out string s) {
|
||||||
|
Expect(6);
|
||||||
|
s = t.val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Term(out decimal r) {
|
||||||
|
decimal r1;
|
||||||
|
Factor(out r);
|
||||||
|
while (la.kind == 12 || la.kind == 13 || la.kind == 14) {
|
||||||
|
if (la.kind == 12) {
|
||||||
|
Get();
|
||||||
|
Factor(out r1);
|
||||||
|
r *= r1;
|
||||||
|
} else if (la.kind == 13) {
|
||||||
|
Get();
|
||||||
|
Factor(out r1);
|
||||||
|
r /= r1;
|
||||||
|
} else {
|
||||||
|
Get();
|
||||||
|
Term(out r1);
|
||||||
|
r %= r1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Factor(out decimal r) {
|
||||||
|
decimal r1;
|
||||||
|
Value(out r);
|
||||||
|
while (la.kind == 15) {
|
||||||
|
Get();
|
||||||
|
Expression(out r1);
|
||||||
|
r = Convert.ToDecimal(Math.Pow(Convert.ToDouble(r), Convert.ToDouble(r1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value(out decimal r) {
|
||||||
|
r = 0;
|
||||||
|
decimal r1 = 0;
|
||||||
|
string fn;
|
||||||
|
int sign = 1;
|
||||||
|
if (la.kind == 10 || la.kind == 11) {
|
||||||
|
if (la.kind == 10) {
|
||||||
|
Get();
|
||||||
|
} else {
|
||||||
|
Get();
|
||||||
|
sign = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IsFunctionCall()) {
|
||||||
|
Function(out r);
|
||||||
|
r = sign * r;
|
||||||
|
} else if (IsArrayCall()) {
|
||||||
|
ArrayCall(out r);
|
||||||
|
r = sign * r;
|
||||||
|
} else if (la.kind == 1) {
|
||||||
|
Get();
|
||||||
|
if(this.interpreter.variables.ContainsKey(t.val))
|
||||||
|
{
|
||||||
|
Variable v = this.interpreter.variables[t.val];
|
||||||
|
if(v.Type == VariableType.Equation)
|
||||||
|
{
|
||||||
|
InputInterpreter i = new InputInterpreter(this.interpreter);
|
||||||
|
i.Interpret(v.Value.ToString());
|
||||||
|
r = i.Decimal;
|
||||||
|
}
|
||||||
|
else if(v.Type == VariableType.Decimal)
|
||||||
|
{
|
||||||
|
r = Convert.ToDecimal(v.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (la.kind == 5) {
|
||||||
|
Get();
|
||||||
|
r = sign * Convert.ToDecimal (t.val);
|
||||||
|
} else if (la.kind == 4) {
|
||||||
|
Get();
|
||||||
|
string expression = t.val.Remove(0,2);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
decimal value = Convert.ToDecimal(Convert.ToInt64(expression, 16));
|
||||||
|
r = sign * value;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (la.kind == 3) {
|
||||||
|
Get();
|
||||||
|
string expression = t.val.Remove(t.val.Length - 1);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
decimal value = Convert.ToDecimal(Convert.ToInt64(expression, 2));
|
||||||
|
r = sign * value;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
r = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if (la.kind == 7) {
|
||||||
|
Get();
|
||||||
|
Expression(out r);
|
||||||
|
Expect(8);
|
||||||
|
r = sign * r;
|
||||||
|
} else SynErr(25);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Function(out decimal r) {
|
||||||
|
string functionName = string.Empty;
|
||||||
|
decimal[] d = new decimal[0];
|
||||||
|
|
||||||
|
Expect(1);
|
||||||
|
functionName = t.val;
|
||||||
|
Expect(7);
|
||||||
|
CommaList(out d);
|
||||||
|
Expect(8);
|
||||||
|
r = this.interpreter.ExecuteFunction(functionName, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayCall(out decimal r) {
|
||||||
|
string ident = string.Empty; r = 0; decimal pos = 0;
|
||||||
|
Expect(1);
|
||||||
|
ident = t.val;
|
||||||
|
Expect(16);
|
||||||
|
Expression(out pos);
|
||||||
|
int i = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
i = Convert.ToInt32(pos);
|
||||||
|
if(this.interpreter.variables.ContainsKey(ident))
|
||||||
|
{
|
||||||
|
decimal[] values = this.interpreter.variables[ident].Value as decimal[];
|
||||||
|
if(values != null)
|
||||||
|
{
|
||||||
|
r = values[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Expect(17);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayL(out decimal[] d) {
|
||||||
|
Expect(16);
|
||||||
|
CommaList(out d);
|
||||||
|
Expect(17);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommaList(out decimal[] d) {
|
||||||
|
List<decimal> list = new List<decimal>(); decimal r = 0;
|
||||||
|
Expression(out r);
|
||||||
|
list.Add(r); d = list.ToArray();
|
||||||
|
while (la.kind == 18) {
|
||||||
|
Get();
|
||||||
|
Expression(out r);
|
||||||
|
list.Add(r); d = list.ToArray();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnyExpression(out string value) {
|
||||||
|
value = string.Empty; StringBuilder builder = new StringBuilder();
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
while (StartOf(2)) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
}
|
||||||
|
value = builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void Parse() {
|
||||||
|
la = new Token();
|
||||||
|
la.val = "";
|
||||||
|
Get();
|
||||||
|
CSMIC();
|
||||||
|
Expect(0);
|
||||||
|
|
||||||
|
Expect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly bool[,] set = {
|
||||||
|
{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
|
||||||
|
{x,T,x,T, T,T,x,T, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x},
|
||||||
|
{x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,x}
|
||||||
|
|
||||||
|
};
|
||||||
|
} // end Parser
|
||||||
|
|
||||||
|
|
||||||
|
public class Errors {
|
||||||
|
public int count = 0; // number of errors detected
|
||||||
|
public StringBuilder builder = new StringBuilder(); // error messages go to this stream
|
||||||
|
public string errMsgFormat = "-- position {0}: {1}"; // 0=line, 1=column, 2=text
|
||||||
|
|
||||||
|
public void SynErr (int line, int col, int n) {
|
||||||
|
string s;
|
||||||
|
switch (n) {
|
||||||
|
case 0: s = "EOF expected"; break;
|
||||||
|
case 1: s = "identifier expected"; break;
|
||||||
|
case 2: s = "sign expected"; break;
|
||||||
|
case 3: s = "binary expected"; break;
|
||||||
|
case 4: s = "hex expected"; break;
|
||||||
|
case 5: s = "number expected"; break;
|
||||||
|
case 6: s = "string expected"; break;
|
||||||
|
case 7: s = "LPAREN expected"; break;
|
||||||
|
case 8: s = "RPAREN expected"; break;
|
||||||
|
case 9: s = "COMPARER expected"; break;
|
||||||
|
case 10: s = "\"+\" expected"; break;
|
||||||
|
case 11: s = "\"-\" expected"; break;
|
||||||
|
case 12: s = "\"*\" expected"; break;
|
||||||
|
case 13: s = "\"/\" expected"; break;
|
||||||
|
case 14: s = "\"%\" expected"; break;
|
||||||
|
case 15: s = "\"^\" expected"; break;
|
||||||
|
case 16: s = "\"[\" expected"; break;
|
||||||
|
case 17: s = "\"]\" expected"; break;
|
||||||
|
case 18: s = "\",\" expected"; break;
|
||||||
|
case 19: s = "\"::\" expected"; break;
|
||||||
|
case 20: s = "\":=\" expected"; break;
|
||||||
|
case 21: s = "\"->\" expected"; break;
|
||||||
|
case 22: s = "??? expected"; break;
|
||||||
|
case 23: s = "invalid CSMIC"; break;
|
||||||
|
case 24: s = "invalid Assignment"; break;
|
||||||
|
case 25: s = "invalid Value"; break;
|
||||||
|
|
||||||
|
default: s = "error " + n; break;
|
||||||
|
}
|
||||||
|
builder.AppendFormat(errMsgFormat, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (int line, int col, string s) {
|
||||||
|
builder.AppendFormat(errMsgFormat, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string s) {
|
||||||
|
builder.AppendLine(s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning (int line, int col, string s) {
|
||||||
|
builder.AppendFormat(errMsgFormat, col, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning(string s) {
|
||||||
|
builder.AppendLine(s);
|
||||||
|
}
|
||||||
|
} // Errors
|
||||||
|
|
||||||
|
|
||||||
|
public class FatalError: Exception {
|
||||||
|
public FatalError(string m): base(m) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
160
CS-MIC/csmic/csmic/InterpreterParser/Parser.frame
Normal file
160
CS-MIC/csmic/csmic/InterpreterParser/Parser.frame
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
Compiler Generator Coco/R,
|
||||||
|
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
||||||
|
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
||||||
|
with improvements by Pat Terry, Rhodes University
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
As an exception, it is allowed to write an extension of Coco/R that is
|
||||||
|
used as a plugin in non-free software.
|
||||||
|
|
||||||
|
If not otherwise stated, any source code generated by Coco/R (other than
|
||||||
|
Coco/R itself) does not fall under the GNU General Public License.
|
||||||
|
----------------------------------------------------------------------*/
|
||||||
|
-->begin
|
||||||
|
using System;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
-->namespace
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Parser {
|
||||||
|
-->constants
|
||||||
|
const bool T = true;
|
||||||
|
const bool x = false;
|
||||||
|
const int minErrDist = 2;
|
||||||
|
|
||||||
|
public Scanner scanner;
|
||||||
|
public Errors errors;
|
||||||
|
|
||||||
|
public Token t; // last recognized token
|
||||||
|
public Token la; // lookahead token
|
||||||
|
int errDist = minErrDist;
|
||||||
|
|
||||||
|
-->declarations
|
||||||
|
|
||||||
|
public Parser(Scanner scanner) {
|
||||||
|
this.scanner = scanner;
|
||||||
|
errors = new Errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynErr (int n) {
|
||||||
|
if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string msg) {
|
||||||
|
if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Get () {
|
||||||
|
for (;;) {
|
||||||
|
t = la;
|
||||||
|
la = scanner.Scan();
|
||||||
|
if (la.kind <= maxT) { ++errDist; break; }
|
||||||
|
-->pragmas
|
||||||
|
la = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expect (int n) {
|
||||||
|
if (la.kind==n) Get(); else { SynErr(n); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartOf (int s) {
|
||||||
|
return set[s, la.kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpectWeak (int n, int follow) {
|
||||||
|
if (la.kind == n) Get();
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!StartOf(follow)) Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WeakSeparator(int n, int syFol, int repFol) {
|
||||||
|
int kind = la.kind;
|
||||||
|
if (kind == n) {Get(); return true;}
|
||||||
|
else if (StartOf(repFol)) {return false;}
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
|
||||||
|
Get();
|
||||||
|
kind = la.kind;
|
||||||
|
}
|
||||||
|
return StartOf(syFol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-->productions
|
||||||
|
|
||||||
|
public void Parse() {
|
||||||
|
la = new Token();
|
||||||
|
la.val = "";
|
||||||
|
Get();
|
||||||
|
-->parseRoot
|
||||||
|
Expect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly bool[,] set = {
|
||||||
|
-->initialization
|
||||||
|
};
|
||||||
|
} // end Parser
|
||||||
|
|
||||||
|
|
||||||
|
public class Errors {
|
||||||
|
public int count = 0; // number of errors detected
|
||||||
|
public StringBuilder builder = new StringBuilder(); // error messages go to this stream
|
||||||
|
public string errMsgFormat = "-- position {0}: {1}"; // 0=line, 1=column, 2=text
|
||||||
|
|
||||||
|
public void SynErr (int line, int col, int n) {
|
||||||
|
string s;
|
||||||
|
switch (n) {
|
||||||
|
-->errors
|
||||||
|
default: s = "error " + n; break;
|
||||||
|
}
|
||||||
|
builder.AppendFormat(errMsgFormat, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (int line, int col, string s) {
|
||||||
|
builder.AppendFormat(errMsgFormat, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string s) {
|
||||||
|
builder.AppendLine(s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning (int line, int col, string s) {
|
||||||
|
builder.AppendFormat(errMsgFormat, col, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning(string s) {
|
||||||
|
builder.AppendLine(s);
|
||||||
|
}
|
||||||
|
} // Errors
|
||||||
|
|
||||||
|
|
||||||
|
public class FatalError: Exception {
|
||||||
|
public FatalError(string m): base(m) {}
|
||||||
|
}
|
||||||
|
|
491
CS-MIC/csmic/csmic/InterpreterParser/Scanner.cs
Normal file
491
CS-MIC/csmic/csmic/InterpreterParser/Scanner.cs
Normal file
|
@ -0,0 +1,491 @@
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
namespace csmic.Interpreter {
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Token {
|
||||||
|
public int kind; // token kind
|
||||||
|
public int pos; // token position in bytes in the source text (starting at 0)
|
||||||
|
public int charPos; // token position in characters in the source text (starting at 0)
|
||||||
|
public int col; // token column (starting at 1)
|
||||||
|
public int line; // token line (starting at 1)
|
||||||
|
public string val; // token value
|
||||||
|
public Token next; // ML 2005-03-11 Tokens are kept in linked list
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Buffer {
|
||||||
|
// This Buffer supports the following cases:
|
||||||
|
// 1) seekable stream (file)
|
||||||
|
// a) whole stream in buffer
|
||||||
|
// b) part of stream in buffer
|
||||||
|
// 2) non seekable stream (network, console)
|
||||||
|
|
||||||
|
public const int EOF = char.MaxValue + 1;
|
||||||
|
const int MIN_BUFFER_LENGTH = 1024; // 1KB
|
||||||
|
const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
|
||||||
|
byte[] buf; // input buffer
|
||||||
|
int bufStart; // position of first byte in buffer relative to input stream
|
||||||
|
int bufLen; // length of buffer
|
||||||
|
int fileLen; // length of input stream (may change if the stream is no file)
|
||||||
|
int bufPos; // current position in buffer
|
||||||
|
Stream stream; // input stream (seekable)
|
||||||
|
bool isUserStream; // was the stream opened by the user?
|
||||||
|
|
||||||
|
public Buffer (Stream s, bool isUserStream) {
|
||||||
|
stream = s; this.isUserStream = isUserStream;
|
||||||
|
|
||||||
|
if (stream.CanSeek) {
|
||||||
|
fileLen = (int) stream.Length;
|
||||||
|
bufLen = Math.Min(fileLen, MAX_BUFFER_LENGTH);
|
||||||
|
bufStart = Int32.MaxValue; // nothing in the buffer so far
|
||||||
|
} else {
|
||||||
|
fileLen = bufLen = bufStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = new byte[(bufLen>0) ? bufLen : MIN_BUFFER_LENGTH];
|
||||||
|
if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
|
||||||
|
else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
|
||||||
|
if (bufLen == fileLen && stream.CanSeek) Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Buffer(Buffer b) { // called in UTF8Buffer constructor
|
||||||
|
buf = b.buf;
|
||||||
|
bufStart = b.bufStart;
|
||||||
|
bufLen = b.bufLen;
|
||||||
|
fileLen = b.fileLen;
|
||||||
|
bufPos = b.bufPos;
|
||||||
|
stream = b.stream;
|
||||||
|
// keep destructor from closing the stream
|
||||||
|
b.stream = null;
|
||||||
|
isUserStream = b.isUserStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Buffer() { Close(); }
|
||||||
|
|
||||||
|
protected void Close() {
|
||||||
|
if (!isUserStream && stream != null) {
|
||||||
|
stream.Close();
|
||||||
|
stream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int Read () {
|
||||||
|
if (bufPos < bufLen) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (Pos < fileLen) {
|
||||||
|
Pos = Pos; // shift buffer start to Pos
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (stream != null && !stream.CanSeek && ReadNextStreamChunk() > 0) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else {
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Peek () {
|
||||||
|
int curPos = Pos;
|
||||||
|
int ch = Read();
|
||||||
|
Pos = curPos;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// beg .. begin, zero-based, inclusive, in byte
|
||||||
|
// end .. end, zero-based, exclusive, in byte
|
||||||
|
public string GetString (int beg, int end) {
|
||||||
|
int len = 0;
|
||||||
|
char[] buf = new char[end - beg];
|
||||||
|
int oldPos = Pos;
|
||||||
|
Pos = beg;
|
||||||
|
while (Pos < end) buf[len++] = (char) Read();
|
||||||
|
Pos = oldPos;
|
||||||
|
return new String(buf, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Pos {
|
||||||
|
get { return bufPos + bufStart; }
|
||||||
|
set {
|
||||||
|
if (value >= fileLen && stream != null && !stream.CanSeek) {
|
||||||
|
// Wanted position is after buffer and the stream
|
||||||
|
// is not seek-able e.g. network or console,
|
||||||
|
// thus we have to read the stream manually till
|
||||||
|
// the wanted position is in sight.
|
||||||
|
while (value >= fileLen && ReadNextStreamChunk() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 || value > fileLen) {
|
||||||
|
throw new FatalError("buffer out of bounds access, position: " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
|
||||||
|
bufPos = value - bufStart;
|
||||||
|
} else if (stream != null) { // must be swapped in
|
||||||
|
stream.Seek(value, SeekOrigin.Begin);
|
||||||
|
bufLen = stream.Read(buf, 0, buf.Length);
|
||||||
|
bufStart = value; bufPos = 0;
|
||||||
|
} else {
|
||||||
|
// set the position to the end of the file, Pos will return fileLen.
|
||||||
|
bufPos = fileLen - bufStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next chunk of bytes from the stream, increases the buffer
|
||||||
|
// if needed and updates the fields fileLen and bufLen.
|
||||||
|
// Returns the number of bytes read.
|
||||||
|
private int ReadNextStreamChunk() {
|
||||||
|
int free = buf.Length - bufLen;
|
||||||
|
if (free == 0) {
|
||||||
|
// in the case of a growing input stream
|
||||||
|
// we can neither seek in the stream, nor can we
|
||||||
|
// foresee the maximum length, thus we must adapt
|
||||||
|
// the buffer size on demand.
|
||||||
|
byte[] newBuf = new byte[bufLen * 2];
|
||||||
|
Array.Copy(buf, newBuf, bufLen);
|
||||||
|
buf = newBuf;
|
||||||
|
free = bufLen;
|
||||||
|
}
|
||||||
|
int read = stream.Read(buf, bufLen, free);
|
||||||
|
if (read > 0) {
|
||||||
|
fileLen = bufLen = (bufLen + read);
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
// end of stream reached
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// UTF8Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class UTF8Buffer: Buffer {
|
||||||
|
public UTF8Buffer(Buffer b): base(b) {}
|
||||||
|
|
||||||
|
public override int Read() {
|
||||||
|
int ch;
|
||||||
|
do {
|
||||||
|
ch = base.Read();
|
||||||
|
// until we find a utf8 start (0xxxxxxx or 11xxxxxx)
|
||||||
|
} while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
|
||||||
|
if (ch < 128 || ch == EOF) {
|
||||||
|
// nothing to do, first 127 chars are the same in ascii and utf8
|
||||||
|
// 0xxxxxxx or end of file character
|
||||||
|
} else if ((ch & 0xF0) == 0xF0) {
|
||||||
|
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x07; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c4 = ch & 0x3F;
|
||||||
|
ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
|
||||||
|
} else if ((ch & 0xE0) == 0xE0) {
|
||||||
|
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x0F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F;
|
||||||
|
ch = (((c1 << 6) | c2) << 6) | c3;
|
||||||
|
} else if ((ch & 0xC0) == 0xC0) {
|
||||||
|
// 110xxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x1F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F;
|
||||||
|
ch = (c1 << 6) | c2;
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Scanner
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Scanner {
|
||||||
|
const char EOL = '\n';
|
||||||
|
const int eofSym = 0; /* pdt */
|
||||||
|
const int maxT = 22;
|
||||||
|
const int noSym = 22;
|
||||||
|
|
||||||
|
|
||||||
|
public Buffer buffer; // scanner buffer
|
||||||
|
|
||||||
|
Token t; // current token
|
||||||
|
int ch; // current input character
|
||||||
|
int pos; // byte position of current character
|
||||||
|
int charPos; // position by unicode characters starting with 0
|
||||||
|
int col; // column number of current character
|
||||||
|
int line; // line number of current character
|
||||||
|
int oldEols; // EOLs that appeared in a comment;
|
||||||
|
static readonly Dictionary<int, int> start; // maps first token character to start state
|
||||||
|
|
||||||
|
Token tokens; // list of tokens already peeked (first token is a dummy)
|
||||||
|
Token pt; // current peek token
|
||||||
|
|
||||||
|
char[] tval = new char[128]; // text of current token
|
||||||
|
int tlen; // length of current token
|
||||||
|
|
||||||
|
static Scanner() {
|
||||||
|
start = new Dictionary<int, int>(128);
|
||||||
|
for (int i = 65; i <= 90; ++i) start[i] = 1;
|
||||||
|
for (int i = 97; i <= 122; ++i) start[i] = 1;
|
||||||
|
start[43] = 2;
|
||||||
|
for (int i = 50; i <= 57; ++i) start[i] = 6;
|
||||||
|
start[48] = 17;
|
||||||
|
start[49] = 18;
|
||||||
|
start[34] = 11;
|
||||||
|
start[40] = 13;
|
||||||
|
start[41] = 14;
|
||||||
|
start[61] = 15;
|
||||||
|
start[60] = 19;
|
||||||
|
start[62] = 20;
|
||||||
|
start[42] = 21;
|
||||||
|
start[47] = 22;
|
||||||
|
start[37] = 23;
|
||||||
|
start[94] = 24;
|
||||||
|
start[91] = 25;
|
||||||
|
start[93] = 26;
|
||||||
|
start[44] = 27;
|
||||||
|
start[58] = 31;
|
||||||
|
start[45] = 32;
|
||||||
|
start[Buffer.EOF] = -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (string fileName) {
|
||||||
|
try {
|
||||||
|
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
buffer = new Buffer(stream, false);
|
||||||
|
Init();
|
||||||
|
} catch (IOException) {
|
||||||
|
throw new FatalError("Cannot open file " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (Stream s) {
|
||||||
|
buffer = new Buffer(s, true);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
pos = -1; line = 1; col = 0; charPos = -1;
|
||||||
|
oldEols = 0;
|
||||||
|
NextCh();
|
||||||
|
if (ch == 0xEF) { // check optional byte order mark for UTF-8
|
||||||
|
NextCh(); int ch1 = ch;
|
||||||
|
NextCh(); int ch2 = ch;
|
||||||
|
if (ch1 != 0xBB || ch2 != 0xBF) {
|
||||||
|
throw new FatalError(String.Format("illegal byte order mark: EF {0,2:X} {1,2:X}", ch1, ch2));
|
||||||
|
}
|
||||||
|
buffer = new UTF8Buffer(buffer); col = 0; charPos = -1;
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
pt = tokens = new Token(); // first token is a dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextCh() {
|
||||||
|
if (oldEols > 0) { ch = EOL; oldEols--; }
|
||||||
|
else {
|
||||||
|
pos = buffer.Pos;
|
||||||
|
// buffer reads unicode chars, if UTF8 has been detected
|
||||||
|
ch = buffer.Read(); col++; charPos++;
|
||||||
|
// replace isolated '\r' by '\n' in order to make
|
||||||
|
// eol handling uniform across Windows, Unix and Mac
|
||||||
|
if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
|
||||||
|
if (ch == EOL) { line++; col = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddCh() {
|
||||||
|
if (tlen >= tval.Length) {
|
||||||
|
char[] newBuf = new char[2 * tval.Length];
|
||||||
|
Array.Copy(tval, 0, newBuf, 0, tval.Length);
|
||||||
|
tval = newBuf;
|
||||||
|
}
|
||||||
|
if (ch != Buffer.EOF) {
|
||||||
|
tval[tlen++] = (char) ch;
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void CheckLiteral() {
|
||||||
|
switch (t.val) {
|
||||||
|
case "+": t.kind = 10; break;
|
||||||
|
case "-": t.kind = 11; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Token NextToken() {
|
||||||
|
while (ch == ' ' ||
|
||||||
|
ch == 9 || ch == 13
|
||||||
|
) NextCh();
|
||||||
|
|
||||||
|
int recKind = noSym;
|
||||||
|
int recEnd = pos;
|
||||||
|
t = new Token();
|
||||||
|
t.pos = pos; t.col = col; t.line = line; t.charPos = charPos;
|
||||||
|
int state;
|
||||||
|
state = (int) start[ch];
|
||||||
|
tlen = 0; AddCh();
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case -1: { t.kind = eofSym; break; } // NextCh already done
|
||||||
|
case 0: {
|
||||||
|
if (recKind != noSym) {
|
||||||
|
tlen = recEnd - t.pos;
|
||||||
|
SetScannerBehindT();
|
||||||
|
}
|
||||||
|
t.kind = recKind; break;
|
||||||
|
} // NextCh already done
|
||||||
|
case 1:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else {t.kind = 1; break;}
|
||||||
|
case 2:
|
||||||
|
{t.kind = 2; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 3:
|
||||||
|
{t.kind = 3; break;}
|
||||||
|
case 4:
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {AddCh(); goto case 5;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 5:
|
||||||
|
recEnd = pos; recKind = 4;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {AddCh(); goto case 5;}
|
||||||
|
else {t.kind = 4; break;}
|
||||||
|
case 6:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 6;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else if (ch == '.') {AddCh(); goto case 10;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 7:
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
|
||||||
|
else if (ch == '+' || ch == '-') {AddCh(); goto case 8;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 8:
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 9:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 10:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 11:
|
||||||
|
if (ch <= '!' || ch >= '#' && ch <= 65535) {AddCh(); goto case 11;}
|
||||||
|
else if (ch == '"') {AddCh(); goto case 12;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 12:
|
||||||
|
{t.kind = 6; break;}
|
||||||
|
case 13:
|
||||||
|
{t.kind = 7; break;}
|
||||||
|
case 14:
|
||||||
|
{t.kind = 8; break;}
|
||||||
|
case 15:
|
||||||
|
if (ch == '=') {AddCh(); goto case 16;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 16:
|
||||||
|
{t.kind = 9; break;}
|
||||||
|
case 17:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '2' && ch <= '9') {AddCh(); goto case 6;}
|
||||||
|
else if (ch == 'B' || ch == 'b') {AddCh(); goto case 3;}
|
||||||
|
else if (ch >= '0' && ch <= '1') {AddCh(); goto case 18;}
|
||||||
|
else if (ch == 'x') {AddCh(); goto case 4;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else if (ch == '.') {AddCh(); goto case 10;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 18:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '2' && ch <= '9') {AddCh(); goto case 6;}
|
||||||
|
else if (ch == 'B' || ch == 'b') {AddCh(); goto case 3;}
|
||||||
|
else if (ch >= '0' && ch <= '1') {AddCh(); goto case 18;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else if (ch == '.') {AddCh(); goto case 10;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 19:
|
||||||
|
recEnd = pos; recKind = 9;
|
||||||
|
if (ch == '=') {AddCh(); goto case 16;}
|
||||||
|
else {t.kind = 9; break;}
|
||||||
|
case 20:
|
||||||
|
recEnd = pos; recKind = 9;
|
||||||
|
if (ch == '=') {AddCh(); goto case 16;}
|
||||||
|
else {t.kind = 9; break;}
|
||||||
|
case 21:
|
||||||
|
{t.kind = 12; break;}
|
||||||
|
case 22:
|
||||||
|
{t.kind = 13; break;}
|
||||||
|
case 23:
|
||||||
|
{t.kind = 14; break;}
|
||||||
|
case 24:
|
||||||
|
{t.kind = 15; break;}
|
||||||
|
case 25:
|
||||||
|
{t.kind = 16; break;}
|
||||||
|
case 26:
|
||||||
|
{t.kind = 17; break;}
|
||||||
|
case 27:
|
||||||
|
{t.kind = 18; break;}
|
||||||
|
case 28:
|
||||||
|
{t.kind = 19; break;}
|
||||||
|
case 29:
|
||||||
|
{t.kind = 20; break;}
|
||||||
|
case 30:
|
||||||
|
{t.kind = 21; break;}
|
||||||
|
case 31:
|
||||||
|
if (ch == ':') {AddCh(); goto case 28;}
|
||||||
|
else if (ch == '=') {AddCh(); goto case 29;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 32:
|
||||||
|
recEnd = pos; recKind = 2;
|
||||||
|
if (ch == '>') {AddCh(); goto case 30;}
|
||||||
|
else {t.kind = 2; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
|
||||||
|
}
|
||||||
|
t.val = new String(tval, 0, tlen);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetScannerBehindT() {
|
||||||
|
buffer.Pos = t.pos;
|
||||||
|
NextCh();
|
||||||
|
line = t.line; col = t.col; charPos = t.charPos;
|
||||||
|
for (int i = 0; i < tlen; i++) NextCh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next token (possibly a token already seen during peeking)
|
||||||
|
public Token Scan () {
|
||||||
|
if (tokens.next == null) {
|
||||||
|
return NextToken();
|
||||||
|
} else {
|
||||||
|
pt = tokens = tokens.next;
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek for the next token, ignore pragmas
|
||||||
|
public Token Peek () {
|
||||||
|
do {
|
||||||
|
if (pt.next == null) {
|
||||||
|
pt.next = NextToken();
|
||||||
|
}
|
||||||
|
pt = pt.next;
|
||||||
|
} while (pt.kind > maxT); // skip pragmas
|
||||||
|
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure that peeking starts at the current scan position
|
||||||
|
public void ResetPeek () { pt = tokens; }
|
||||||
|
|
||||||
|
} // end Scanner
|
||||||
|
}
|
383
CS-MIC/csmic/csmic/InterpreterParser/Scanner.frame
Normal file
383
CS-MIC/csmic/csmic/InterpreterParser/Scanner.frame
Normal file
|
@ -0,0 +1,383 @@
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
Compiler Generator Coco/R,
|
||||||
|
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
||||||
|
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
||||||
|
with improvements by Pat Terry, Rhodes University
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
As an exception, it is allowed to write an extension of Coco/R that is
|
||||||
|
used as a plugin in non-free software.
|
||||||
|
|
||||||
|
If not otherwise stated, any source code generated by Coco/R (other than
|
||||||
|
Coco/R itself) does not fall under the GNU General Public License.
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
-->begin
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
-->namespace
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Token {
|
||||||
|
public int kind; // token kind
|
||||||
|
public int pos; // token position in bytes in the source text (starting at 0)
|
||||||
|
public int charPos; // token position in characters in the source text (starting at 0)
|
||||||
|
public int col; // token column (starting at 1)
|
||||||
|
public int line; // token line (starting at 1)
|
||||||
|
public string val; // token value
|
||||||
|
public Token next; // ML 2005-03-11 Tokens are kept in linked list
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Buffer {
|
||||||
|
// This Buffer supports the following cases:
|
||||||
|
// 1) seekable stream (file)
|
||||||
|
// a) whole stream in buffer
|
||||||
|
// b) part of stream in buffer
|
||||||
|
// 2) non seekable stream (network, console)
|
||||||
|
|
||||||
|
public const int EOF = char.MaxValue + 1;
|
||||||
|
const int MIN_BUFFER_LENGTH = 1024; // 1KB
|
||||||
|
const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
|
||||||
|
byte[] buf; // input buffer
|
||||||
|
int bufStart; // position of first byte in buffer relative to input stream
|
||||||
|
int bufLen; // length of buffer
|
||||||
|
int fileLen; // length of input stream (may change if the stream is no file)
|
||||||
|
int bufPos; // current position in buffer
|
||||||
|
Stream stream; // input stream (seekable)
|
||||||
|
bool isUserStream; // was the stream opened by the user?
|
||||||
|
|
||||||
|
public Buffer (Stream s, bool isUserStream) {
|
||||||
|
stream = s; this.isUserStream = isUserStream;
|
||||||
|
|
||||||
|
if (stream.CanSeek) {
|
||||||
|
fileLen = (int) stream.Length;
|
||||||
|
bufLen = Math.Min(fileLen, MAX_BUFFER_LENGTH);
|
||||||
|
bufStart = Int32.MaxValue; // nothing in the buffer so far
|
||||||
|
} else {
|
||||||
|
fileLen = bufLen = bufStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = new byte[(bufLen>0) ? bufLen : MIN_BUFFER_LENGTH];
|
||||||
|
if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
|
||||||
|
else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
|
||||||
|
if (bufLen == fileLen && stream.CanSeek) Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Buffer(Buffer b) { // called in UTF8Buffer constructor
|
||||||
|
buf = b.buf;
|
||||||
|
bufStart = b.bufStart;
|
||||||
|
bufLen = b.bufLen;
|
||||||
|
fileLen = b.fileLen;
|
||||||
|
bufPos = b.bufPos;
|
||||||
|
stream = b.stream;
|
||||||
|
// keep destructor from closing the stream
|
||||||
|
b.stream = null;
|
||||||
|
isUserStream = b.isUserStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Buffer() { Close(); }
|
||||||
|
|
||||||
|
protected void Close() {
|
||||||
|
if (!isUserStream && stream != null) {
|
||||||
|
stream.Close();
|
||||||
|
stream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int Read () {
|
||||||
|
if (bufPos < bufLen) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (Pos < fileLen) {
|
||||||
|
Pos = Pos; // shift buffer start to Pos
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (stream != null && !stream.CanSeek && ReadNextStreamChunk() > 0) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else {
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Peek () {
|
||||||
|
int curPos = Pos;
|
||||||
|
int ch = Read();
|
||||||
|
Pos = curPos;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// beg .. begin, zero-based, inclusive, in byte
|
||||||
|
// end .. end, zero-based, exclusive, in byte
|
||||||
|
public string GetString (int beg, int end) {
|
||||||
|
int len = 0;
|
||||||
|
char[] buf = new char[end - beg];
|
||||||
|
int oldPos = Pos;
|
||||||
|
Pos = beg;
|
||||||
|
while (Pos < end) buf[len++] = (char) Read();
|
||||||
|
Pos = oldPos;
|
||||||
|
return new String(buf, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Pos {
|
||||||
|
get { return bufPos + bufStart; }
|
||||||
|
set {
|
||||||
|
if (value >= fileLen && stream != null && !stream.CanSeek) {
|
||||||
|
// Wanted position is after buffer and the stream
|
||||||
|
// is not seek-able e.g. network or console,
|
||||||
|
// thus we have to read the stream manually till
|
||||||
|
// the wanted position is in sight.
|
||||||
|
while (value >= fileLen && ReadNextStreamChunk() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 || value > fileLen) {
|
||||||
|
throw new FatalError("buffer out of bounds access, position: " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
|
||||||
|
bufPos = value - bufStart;
|
||||||
|
} else if (stream != null) { // must be swapped in
|
||||||
|
stream.Seek(value, SeekOrigin.Begin);
|
||||||
|
bufLen = stream.Read(buf, 0, buf.Length);
|
||||||
|
bufStart = value; bufPos = 0;
|
||||||
|
} else {
|
||||||
|
// set the position to the end of the file, Pos will return fileLen.
|
||||||
|
bufPos = fileLen - bufStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next chunk of bytes from the stream, increases the buffer
|
||||||
|
// if needed and updates the fields fileLen and bufLen.
|
||||||
|
// Returns the number of bytes read.
|
||||||
|
private int ReadNextStreamChunk() {
|
||||||
|
int free = buf.Length - bufLen;
|
||||||
|
if (free == 0) {
|
||||||
|
// in the case of a growing input stream
|
||||||
|
// we can neither seek in the stream, nor can we
|
||||||
|
// foresee the maximum length, thus we must adapt
|
||||||
|
// the buffer size on demand.
|
||||||
|
byte[] newBuf = new byte[bufLen * 2];
|
||||||
|
Array.Copy(buf, newBuf, bufLen);
|
||||||
|
buf = newBuf;
|
||||||
|
free = bufLen;
|
||||||
|
}
|
||||||
|
int read = stream.Read(buf, bufLen, free);
|
||||||
|
if (read > 0) {
|
||||||
|
fileLen = bufLen = (bufLen + read);
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
// end of stream reached
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// UTF8Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class UTF8Buffer: Buffer {
|
||||||
|
public UTF8Buffer(Buffer b): base(b) {}
|
||||||
|
|
||||||
|
public override int Read() {
|
||||||
|
int ch;
|
||||||
|
do {
|
||||||
|
ch = base.Read();
|
||||||
|
// until we find a utf8 start (0xxxxxxx or 11xxxxxx)
|
||||||
|
} while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
|
||||||
|
if (ch < 128 || ch == EOF) {
|
||||||
|
// nothing to do, first 127 chars are the same in ascii and utf8
|
||||||
|
// 0xxxxxxx or end of file character
|
||||||
|
} else if ((ch & 0xF0) == 0xF0) {
|
||||||
|
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x07; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c4 = ch & 0x3F;
|
||||||
|
ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
|
||||||
|
} else if ((ch & 0xE0) == 0xE0) {
|
||||||
|
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x0F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F;
|
||||||
|
ch = (((c1 << 6) | c2) << 6) | c3;
|
||||||
|
} else if ((ch & 0xC0) == 0xC0) {
|
||||||
|
// 110xxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x1F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F;
|
||||||
|
ch = (c1 << 6) | c2;
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Scanner
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Scanner {
|
||||||
|
const char EOL = '\n';
|
||||||
|
const int eofSym = 0; /* pdt */
|
||||||
|
-->declarations
|
||||||
|
|
||||||
|
public Buffer buffer; // scanner buffer
|
||||||
|
|
||||||
|
Token t; // current token
|
||||||
|
int ch; // current input character
|
||||||
|
int pos; // byte position of current character
|
||||||
|
int charPos; // position by unicode characters starting with 0
|
||||||
|
int col; // column number of current character
|
||||||
|
int line; // line number of current character
|
||||||
|
int oldEols; // EOLs that appeared in a comment;
|
||||||
|
static readonly Dictionary<int, int> start; // maps first token character to start state
|
||||||
|
|
||||||
|
Token tokens; // list of tokens already peeked (first token is a dummy)
|
||||||
|
Token pt; // current peek token
|
||||||
|
|
||||||
|
char[] tval = new char[128]; // text of current token
|
||||||
|
int tlen; // length of current token
|
||||||
|
|
||||||
|
static Scanner() {
|
||||||
|
start = new Dictionary<int, int>(128);
|
||||||
|
-->initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (string fileName) {
|
||||||
|
try {
|
||||||
|
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
buffer = new Buffer(stream, false);
|
||||||
|
Init();
|
||||||
|
} catch (IOException) {
|
||||||
|
throw new FatalError("Cannot open file " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (Stream s) {
|
||||||
|
buffer = new Buffer(s, true);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
pos = -1; line = 1; col = 0; charPos = -1;
|
||||||
|
oldEols = 0;
|
||||||
|
NextCh();
|
||||||
|
if (ch == 0xEF) { // check optional byte order mark for UTF-8
|
||||||
|
NextCh(); int ch1 = ch;
|
||||||
|
NextCh(); int ch2 = ch;
|
||||||
|
if (ch1 != 0xBB || ch2 != 0xBF) {
|
||||||
|
throw new FatalError(String.Format("illegal byte order mark: EF {0,2:X} {1,2:X}", ch1, ch2));
|
||||||
|
}
|
||||||
|
buffer = new UTF8Buffer(buffer); col = 0; charPos = -1;
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
pt = tokens = new Token(); // first token is a dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextCh() {
|
||||||
|
if (oldEols > 0) { ch = EOL; oldEols--; }
|
||||||
|
else {
|
||||||
|
pos = buffer.Pos;
|
||||||
|
// buffer reads unicode chars, if UTF8 has been detected
|
||||||
|
ch = buffer.Read(); col++; charPos++;
|
||||||
|
// replace isolated '\r' by '\n' in order to make
|
||||||
|
// eol handling uniform across Windows, Unix and Mac
|
||||||
|
if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
|
||||||
|
if (ch == EOL) { line++; col = 0; }
|
||||||
|
}
|
||||||
|
-->casing1
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddCh() {
|
||||||
|
if (tlen >= tval.Length) {
|
||||||
|
char[] newBuf = new char[2 * tval.Length];
|
||||||
|
Array.Copy(tval, 0, newBuf, 0, tval.Length);
|
||||||
|
tval = newBuf;
|
||||||
|
}
|
||||||
|
if (ch != Buffer.EOF) {
|
||||||
|
-->casing2
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-->comments
|
||||||
|
|
||||||
|
void CheckLiteral() {
|
||||||
|
-->literals
|
||||||
|
}
|
||||||
|
|
||||||
|
Token NextToken() {
|
||||||
|
while (ch == ' ' ||
|
||||||
|
-->scan1
|
||||||
|
) NextCh();
|
||||||
|
-->scan2
|
||||||
|
int recKind = noSym;
|
||||||
|
int recEnd = pos;
|
||||||
|
t = new Token();
|
||||||
|
t.pos = pos; t.col = col; t.line = line; t.charPos = charPos;
|
||||||
|
int state;
|
||||||
|
state = (int) start[ch];
|
||||||
|
tlen = 0; AddCh();
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case -1: { t.kind = eofSym; break; } // NextCh already done
|
||||||
|
case 0: {
|
||||||
|
if (recKind != noSym) {
|
||||||
|
tlen = recEnd - t.pos;
|
||||||
|
SetScannerBehindT();
|
||||||
|
}
|
||||||
|
t.kind = recKind; break;
|
||||||
|
} // NextCh already done
|
||||||
|
-->scan3
|
||||||
|
}
|
||||||
|
t.val = new String(tval, 0, tlen);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetScannerBehindT() {
|
||||||
|
buffer.Pos = t.pos;
|
||||||
|
NextCh();
|
||||||
|
line = t.line; col = t.col; charPos = t.charPos;
|
||||||
|
for (int i = 0; i < tlen; i++) NextCh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next token (possibly a token already seen during peeking)
|
||||||
|
public Token Scan () {
|
||||||
|
if (tokens.next == null) {
|
||||||
|
return NextToken();
|
||||||
|
} else {
|
||||||
|
pt = tokens = tokens.next;
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek for the next token, ignore pragmas
|
||||||
|
public Token Peek () {
|
||||||
|
do {
|
||||||
|
if (pt.next == null) {
|
||||||
|
pt.next = NextToken();
|
||||||
|
}
|
||||||
|
pt = pt.next;
|
||||||
|
} while (pt.kind > maxT); // skip pragmas
|
||||||
|
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure that peeking starts at the current scan position
|
||||||
|
public void ResetPeek () { pt = tokens; }
|
||||||
|
|
||||||
|
} // end Scanner
|
337
CS-MIC/csmic/csmic/MacroBuilder.cs
Normal file
337
CS-MIC/csmic/csmic/MacroBuilder.cs
Normal file
|
@ -0,0 +1,337 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.IO;
|
||||||
|
using System.Threading;
|
||||||
|
using csmic.Scripting;
|
||||||
|
using System.Runtime.Remoting.Messaging;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A builder object that executes macro scripts.
|
||||||
|
/// </summary>
|
||||||
|
public class MacroBuilder
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The input inputInterpreter.
|
||||||
|
/// </summary>
|
||||||
|
private InputInterpreter interpreter;
|
||||||
|
/// <summary> The script to run as a macro. </summary>
|
||||||
|
private string script;
|
||||||
|
/// <summary>
|
||||||
|
/// The output as a list of strings.
|
||||||
|
/// </summary>
|
||||||
|
private List<string> output;
|
||||||
|
/// <summary>
|
||||||
|
/// The time for execution.
|
||||||
|
/// </summary>
|
||||||
|
private TimeSpan executionTime;
|
||||||
|
/// <summary>
|
||||||
|
/// The root macro operation.
|
||||||
|
/// </summary>
|
||||||
|
private MacroOperation rootOperation;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new builder object that executes a given macro script.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="script">A list of strings representing the macro.</param>
|
||||||
|
/// <param name="inputInterpreter">The InputInterpreter to be used.</param>
|
||||||
|
public MacroBuilder(string script, InputInterpreter inputInterpreter)
|
||||||
|
{
|
||||||
|
this.output = new List<string>();
|
||||||
|
this.executionTime = new TimeSpan();
|
||||||
|
|
||||||
|
this.script = script;
|
||||||
|
this.interpreter = inputInterpreter;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new builder object that executes a given macro script.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="script">A list of strings representing the macro.</param>
|
||||||
|
/// <param name="inputInterpreter">The InputInterpreter to be used.</param>
|
||||||
|
internal MacroBuilder(MacroOperation script, InputInterpreter inputInterpreter)
|
||||||
|
{
|
||||||
|
this.output = new List<string>();
|
||||||
|
this.executionTime = new TimeSpan();
|
||||||
|
DateTime timeStart = DateTime.Now;
|
||||||
|
|
||||||
|
this.interpreter = inputInterpreter;
|
||||||
|
|
||||||
|
this.rootOperation = script;
|
||||||
|
|
||||||
|
ExecuteOperation(this.rootOperation);
|
||||||
|
|
||||||
|
DateTime timeEnd = DateTime.Now;
|
||||||
|
this.executionTime = timeEnd - timeStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of strings representing the output.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Output
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the execution time of the last script computation.
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan LastExecutionTime
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.executionTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the decimal value last computed by the macrobuilder.
|
||||||
|
/// </summary>
|
||||||
|
public string FinalOutput
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.interpreter.Output;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public Methods
|
||||||
|
|
||||||
|
/// <summary> Runs this macro. </summary>
|
||||||
|
public void Run()
|
||||||
|
{
|
||||||
|
DateTime timeStart = DateTime.Now;
|
||||||
|
|
||||||
|
ASCIIEncoding encoder = new ASCIIEncoding();
|
||||||
|
Parser p = new Parser(new Scanner(new MemoryStream(encoder.GetBytes(this.script))));
|
||||||
|
p.Parse();
|
||||||
|
|
||||||
|
this.rootOperation = p.Root;
|
||||||
|
|
||||||
|
ExecuteOperation(p.Root);
|
||||||
|
|
||||||
|
DateTime timeEnd = DateTime.Now;
|
||||||
|
this.executionTime = timeEnd - timeStart;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private Methods
|
||||||
|
|
||||||
|
private void ExecuteOperation(MacroOperation operation)
|
||||||
|
{
|
||||||
|
switch (operation.OperationType)
|
||||||
|
{
|
||||||
|
case OperationType.If:
|
||||||
|
if (operation.Input.Count == 1)
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(operation.Input[0]);
|
||||||
|
if (this.interpreter.Decimal == 1)
|
||||||
|
{
|
||||||
|
foreach (MacroOperation op in operation.Children)
|
||||||
|
{
|
||||||
|
ExecuteOperation(op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.Else:
|
||||||
|
foreach (MacroOperation op in operation.Children)
|
||||||
|
{
|
||||||
|
ExecuteOperation(op);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.IfElse:
|
||||||
|
if (operation.Children.Count == 2 && operation.Children[0].Input.Count == 1)
|
||||||
|
{
|
||||||
|
MacroOperation ifOp = operation.Children[0];
|
||||||
|
MacroOperation elseOp = operation.Children[1];
|
||||||
|
this.interpreter.Interpret(ifOp.Input[0]);
|
||||||
|
if (this.interpreter.Decimal == 1)
|
||||||
|
{
|
||||||
|
foreach (MacroOperation op in ifOp.Children)
|
||||||
|
{
|
||||||
|
ExecuteOperation(op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
foreach (MacroOperation op in elseOp.Children)
|
||||||
|
{
|
||||||
|
ExecuteOperation(op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.While:
|
||||||
|
if (operation.Input.Count == 1)
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(operation.Input[0]);
|
||||||
|
while (this.interpreter.Decimal == 1)
|
||||||
|
{
|
||||||
|
foreach (MacroOperation op in operation.Children)
|
||||||
|
{
|
||||||
|
ExecuteOperation(op);
|
||||||
|
}
|
||||||
|
this.interpreter.Interpret(operation.Input[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.For:
|
||||||
|
if (operation.Input.Count == 3)
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(operation.Input[0]);
|
||||||
|
this.interpreter.Interpret(operation.Input[1]);
|
||||||
|
int loopCount = this.interpreter.Int;
|
||||||
|
while (this.interpreter.Int == 1)
|
||||||
|
{
|
||||||
|
foreach (MacroOperation op in operation.Children)
|
||||||
|
{
|
||||||
|
ExecuteOperation(op);
|
||||||
|
}
|
||||||
|
this.interpreter.Interpret(operation.Input[2]);
|
||||||
|
this.interpreter.Interpret(operation.Input[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.FunctionDeclaration:
|
||||||
|
if (operation.Input.Count > 1)
|
||||||
|
{
|
||||||
|
string name = operation.Input[0];
|
||||||
|
operation.Input.RemoveAt(0);
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
operation.OperationType = OperationType.Unknown;
|
||||||
|
InterpretedFunction function = new InterpretedFunction(name, operation, operation.Input.ToArray());
|
||||||
|
if (this.interpreter.InterpretedFunctions.Contains(function))
|
||||||
|
{
|
||||||
|
this.interpreter.InterpretedFunctions[this.interpreter.InterpretedFunctions.IndexOf(function)] = function;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.interpreter.InterpretedFunctions.Add(function);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.Echo:
|
||||||
|
if (operation.Children.Count == 1)
|
||||||
|
{
|
||||||
|
MacroOperation op = operation.Children[0];
|
||||||
|
if (op.OperationType == OperationType.Statement)
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(op.Input[0]);
|
||||||
|
this.output.Add(this.interpreter.Output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.Say:
|
||||||
|
if (operation.Input.Count == 1)
|
||||||
|
{
|
||||||
|
this.output.Add(operation.Input[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.Display:
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
foreach (MacroOperation op in operation.Children)
|
||||||
|
{
|
||||||
|
if (op.OperationType == OperationType.Statement)
|
||||||
|
{
|
||||||
|
if (op.Input.Count == 1)
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(op.Input[0]);
|
||||||
|
sb.Append(this.interpreter.Output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (op.OperationType == OperationType.String)
|
||||||
|
{
|
||||||
|
if (op.Input.Count == 1)
|
||||||
|
{
|
||||||
|
sb.Append(op.Input[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.output.Add(sb.ToString());
|
||||||
|
break;
|
||||||
|
case OperationType.Statement:
|
||||||
|
if (operation.Input.Count == 1)
|
||||||
|
{
|
||||||
|
this.interpreter.Interpret(operation.Input[0]);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case OperationType.String:
|
||||||
|
//Should not reach this state.
|
||||||
|
break;
|
||||||
|
case OperationType.Unknown:
|
||||||
|
if (operation.Children.Count > 0)
|
||||||
|
{
|
||||||
|
foreach (MacroOperation op in operation.Children)
|
||||||
|
{
|
||||||
|
ExecuteOperation(op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
//CRAP.
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Asynchronous
|
||||||
|
|
||||||
|
/// <summary> Executes the asynchronous operation. </summary>
|
||||||
|
/// <param name="input"> The input. </param>
|
||||||
|
/// <param name="callback"> The callback. </param>
|
||||||
|
public void RunAsync(string input, Action<MacroBuilder> callback)
|
||||||
|
{
|
||||||
|
MacroAsyncDelegate del = new MacroAsyncDelegate(RunAsyncThreadingWork);
|
||||||
|
del.BeginInvoke(input, (result) =>
|
||||||
|
{
|
||||||
|
AsyncResult returned = result as AsyncResult;
|
||||||
|
if (returned != null)
|
||||||
|
{
|
||||||
|
MacroAsyncDelegate end = returned.AsyncDelegate as MacroAsyncDelegate;
|
||||||
|
if (end != null)
|
||||||
|
{
|
||||||
|
MacroBuilder returnValue = end.EndInvoke(result);
|
||||||
|
callback(returnValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Executes the asynchronous threading work operation. </summary>
|
||||||
|
/// <param name="input"> The input. </param>
|
||||||
|
/// <returns> . </returns>
|
||||||
|
private MacroBuilder RunAsyncThreadingWork(string input)
|
||||||
|
{
|
||||||
|
Run();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary> Macro asynchronous delegate. </summary>
|
||||||
|
/// <param name="input"> The input. </param>
|
||||||
|
/// <returns> . </returns>
|
||||||
|
private delegate MacroBuilder MacroAsyncDelegate(string input);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
149
CS-MIC/csmic/csmic/MacroOperation.cs
Normal file
149
CS-MIC/csmic/csmic/MacroOperation.cs
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the operation types supported by a scripted macro.
|
||||||
|
/// </summary>
|
||||||
|
internal enum OperationType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a conditional block.
|
||||||
|
/// </summary>
|
||||||
|
If,
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a conditional else block.
|
||||||
|
/// </summary>
|
||||||
|
Else,
|
||||||
|
/// <summary>
|
||||||
|
/// Represents a complete conditional block.
|
||||||
|
/// </summary>
|
||||||
|
IfElse,
|
||||||
|
/// <summary>
|
||||||
|
/// A while block.
|
||||||
|
/// </summary>
|
||||||
|
While,
|
||||||
|
/// <summary>
|
||||||
|
/// A for block.
|
||||||
|
/// </summary>
|
||||||
|
For,
|
||||||
|
/// <summary>
|
||||||
|
/// A function declaration.
|
||||||
|
/// </summary>
|
||||||
|
FunctionDeclaration,
|
||||||
|
/// <summary>
|
||||||
|
/// An echo statement.
|
||||||
|
/// </summary>
|
||||||
|
Echo,
|
||||||
|
/// <summary>
|
||||||
|
/// A say statement.
|
||||||
|
/// </summary>
|
||||||
|
Say,
|
||||||
|
/// <summary>
|
||||||
|
/// A display statement.
|
||||||
|
/// </summary>
|
||||||
|
Display,
|
||||||
|
/// <summary>
|
||||||
|
/// A statement to execute.
|
||||||
|
/// </summary>
|
||||||
|
Statement,
|
||||||
|
/// <summary>
|
||||||
|
/// A string to display.
|
||||||
|
/// </summary>
|
||||||
|
String,
|
||||||
|
/// <summary>
|
||||||
|
/// An unknown or malformed block.
|
||||||
|
/// </summary>
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An operation object that executes a specified action.
|
||||||
|
/// </summary>
|
||||||
|
internal class MacroOperation
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of operation represented by the operation.
|
||||||
|
/// </summary>
|
||||||
|
private OperationType operationType;
|
||||||
|
/// <summary>
|
||||||
|
/// The collection of children nodes that belong to the operation.
|
||||||
|
/// </summary>
|
||||||
|
private List<MacroOperation> children;
|
||||||
|
/// <summary>
|
||||||
|
/// A list of the necesary input to execute the operation.
|
||||||
|
/// </summary>
|
||||||
|
private List<string> input;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a new macro operation node.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="operationType">The type of operation the node represents.</param>
|
||||||
|
public MacroOperation(OperationType operationType)
|
||||||
|
{
|
||||||
|
this.operationType = operationType;
|
||||||
|
this.children = new List<MacroOperation>();
|
||||||
|
this.input = new List<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the children nodes of the operation.
|
||||||
|
/// </summary>
|
||||||
|
public List<MacroOperation> Children
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.children;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.children = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the input for the operation.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> Input
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.input;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.input = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the operation type for this operation.
|
||||||
|
/// </summary>
|
||||||
|
public OperationType OperationType
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.operationType;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.operationType = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
36
CS-MIC/csmic/csmic/Properties/AssemblyInfo.cs
Normal file
36
CS-MIC/csmic/csmic/Properties/AssemblyInfo.cs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
[assembly: AssemblyTitle("csmic")]
|
||||||
|
[assembly: AssemblyDescription("A .NET component for easy access to parsing simple math and scripting.")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("Jordan Wages")]
|
||||||
|
[assembly: AssemblyProduct("csmic")]
|
||||||
|
[assembly: AssemblyCopyright("Copyright © 2012")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
|
// Setting ComVisible to false makes the types in this assembly not visible
|
||||||
|
// to COM components. If you need to access a type in this assembly from
|
||||||
|
// COM, set the ComVisible attribute to true on that type.
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
|
||||||
|
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||||
|
[assembly: Guid("e36b7d85-f0e6-4f24-ba03-ac53124dd97e")]
|
||||||
|
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
|
[assembly: AssemblyVersion("1.1.5.0")]
|
||||||
|
[assembly: AssemblyFileVersion("1.1.5.0")]
|
798
CS-MIC/csmic/csmic/ScriptParser/Parser.cs
Normal file
798
CS-MIC/csmic/csmic/ScriptParser/Parser.cs
Normal file
|
@ -0,0 +1,798 @@
|
||||||
|
using csmic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
namespace csmic.Scripting {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Parser {
|
||||||
|
public const int _EOF = 0;
|
||||||
|
public const int _identifier = 1;
|
||||||
|
public const int _sign = 2;
|
||||||
|
public const int _binary = 3;
|
||||||
|
public const int _hex = 4;
|
||||||
|
public const int _number = 5;
|
||||||
|
public const int _newline = 6;
|
||||||
|
public const int _string = 7;
|
||||||
|
public const int _LPAREN = 8;
|
||||||
|
public const int _RPAREN = 9;
|
||||||
|
public const int _COMPARER = 10;
|
||||||
|
public const int maxT = 34;
|
||||||
|
|
||||||
|
const bool T = true;
|
||||||
|
const bool x = false;
|
||||||
|
const int minErrDist = 2;
|
||||||
|
|
||||||
|
public Scanner scanner;
|
||||||
|
public Errors errors;
|
||||||
|
|
||||||
|
public Token t; // last recognized token
|
||||||
|
public Token la; // lookahead token
|
||||||
|
int errDist = minErrDist;
|
||||||
|
|
||||||
|
private MacroOperation root = new MacroOperation(OperationType.Unknown);
|
||||||
|
|
||||||
|
internal MacroOperation Root
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.root;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.root = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFunctionCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _LPAREN && la.kind == _identifier)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompare()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _COMPARER)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAssignment()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.val == "::" || next.val == ":=" || next.val == "->")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsArrayCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if(next.val == "[")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public Parser(Scanner scanner) {
|
||||||
|
this.scanner = scanner;
|
||||||
|
errors = new Errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynErr (int n) {
|
||||||
|
if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string msg) {
|
||||||
|
if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Get () {
|
||||||
|
for (;;) {
|
||||||
|
t = la;
|
||||||
|
la = scanner.Scan();
|
||||||
|
if (la.kind <= maxT) { ++errDist; break; }
|
||||||
|
|
||||||
|
la = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expect (int n) {
|
||||||
|
if (la.kind==n) Get(); else { SynErr(n); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartOf (int s) {
|
||||||
|
return set[s, la.kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpectWeak (int n, int follow) {
|
||||||
|
if (la.kind == n) Get();
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!StartOf(follow)) Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WeakSeparator(int n, int syFol, int repFol) {
|
||||||
|
int kind = la.kind;
|
||||||
|
if (kind == n) {Get(); return true;}
|
||||||
|
else if (StartOf(repFol)) {return false;}
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
|
||||||
|
Get();
|
||||||
|
kind = la.kind;
|
||||||
|
}
|
||||||
|
return StartOf(syFol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SCRIPT() {
|
||||||
|
string statement = string.Empty;
|
||||||
|
while (StartOf(1)) {
|
||||||
|
switch (la.kind) {
|
||||||
|
case 1: case 3: case 4: case 5: case 8: case 22: case 23: {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
this.root.Children.Add(operation);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11: {
|
||||||
|
IfBlock(ref this.root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 15: {
|
||||||
|
WhileBlock(ref this.root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 18: {
|
||||||
|
FunctionDeclaration(ref this.root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 19: {
|
||||||
|
EchoStatement(ref this.root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20: {
|
||||||
|
SayStatement(ref this.root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 21: {
|
||||||
|
DisplayStatement(ref this.root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
ForBlock(ref this.root);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Statement(out string value) {
|
||||||
|
value = string.Empty;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
if (IsAssignment()) {
|
||||||
|
Assignment(ref builder);
|
||||||
|
value = builder.ToString();
|
||||||
|
} else if (StartOf(2)) {
|
||||||
|
Expression(ref builder);
|
||||||
|
value = builder.ToString();
|
||||||
|
} else SynErr(35);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IfBlock(ref MacroOperation parent) {
|
||||||
|
MacroOperation ifBlock = new MacroOperation(OperationType.If);
|
||||||
|
MacroOperation elseBlock = new MacroOperation(OperationType.Else);
|
||||||
|
string ifStatement = string.Empty;
|
||||||
|
string statement = string.Empty;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
bool hasElse = false;
|
||||||
|
|
||||||
|
Expect(11);
|
||||||
|
Expect(8);
|
||||||
|
Comparison(ref builder);
|
||||||
|
ifStatement = builder.ToString(); ifBlock.Input.Add(ifStatement);
|
||||||
|
Expect(9);
|
||||||
|
Expect(12);
|
||||||
|
while (StartOf(3)) {
|
||||||
|
switch (la.kind) {
|
||||||
|
case 1: case 3: case 4: case 5: case 8: case 22: case 23: {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
ifBlock.Children.Add(operation);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11: {
|
||||||
|
IfBlock(ref ifBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 15: {
|
||||||
|
WhileBlock(ref ifBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 19: {
|
||||||
|
EchoStatement(ref ifBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20: {
|
||||||
|
SayStatement(ref ifBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 21: {
|
||||||
|
DisplayStatement(ref ifBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
ForBlock(ref ifBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(13);
|
||||||
|
if (la.kind == 14) {
|
||||||
|
Get();
|
||||||
|
hasElse = true;
|
||||||
|
Expect(12);
|
||||||
|
while (StartOf(3)) {
|
||||||
|
switch (la.kind) {
|
||||||
|
case 1: case 3: case 4: case 5: case 8: case 22: case 23: {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
elseBlock.Children.Add(operation);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11: {
|
||||||
|
IfBlock(ref elseBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 15: {
|
||||||
|
WhileBlock(ref elseBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 19: {
|
||||||
|
EchoStatement(ref elseBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20: {
|
||||||
|
SayStatement(ref elseBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 21: {
|
||||||
|
DisplayStatement(ref elseBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
ForBlock(ref elseBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(13);
|
||||||
|
}
|
||||||
|
if(hasElse)
|
||||||
|
{
|
||||||
|
MacroOperation ifelse = new MacroOperation(OperationType.IfElse);
|
||||||
|
ifelse.Children.Add(ifBlock);
|
||||||
|
ifelse.Children.Add(elseBlock);
|
||||||
|
parent.Children.Add(ifelse);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent.Children.Add(ifBlock);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void WhileBlock(ref MacroOperation parent) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation whileBlock = new MacroOperation(OperationType.While);
|
||||||
|
string statement = string.Empty;
|
||||||
|
|
||||||
|
Expect(15);
|
||||||
|
Expect(8);
|
||||||
|
Comparison(ref builder);
|
||||||
|
whileBlock.Input.Add(builder.ToString());
|
||||||
|
Expect(9);
|
||||||
|
Expect(12);
|
||||||
|
while (StartOf(3)) {
|
||||||
|
switch (la.kind) {
|
||||||
|
case 1: case 3: case 4: case 5: case 8: case 22: case 23: {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
whileBlock.Children.Add(operation);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11: {
|
||||||
|
IfBlock(ref whileBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 15: {
|
||||||
|
WhileBlock(ref whileBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 19: {
|
||||||
|
EchoStatement(ref whileBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20: {
|
||||||
|
SayStatement(ref whileBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 21: {
|
||||||
|
DisplayStatement(ref whileBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
ForBlock(ref whileBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(13);
|
||||||
|
parent.Children.Add(whileBlock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void FunctionDeclaration(ref MacroOperation parent) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
string statement = string.Empty;
|
||||||
|
MacroOperation func = new MacroOperation(OperationType.FunctionDeclaration);
|
||||||
|
|
||||||
|
Expect(18);
|
||||||
|
Expect(8);
|
||||||
|
CommaList(ref builder);
|
||||||
|
string[] args = builder.ToString().Split(','); func.Input.AddRange(args);
|
||||||
|
Expect(9);
|
||||||
|
Expect(12);
|
||||||
|
while (StartOf(3)) {
|
||||||
|
switch (la.kind) {
|
||||||
|
case 1: case 3: case 4: case 5: case 8: case 22: case 23: {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
func.Children.Add(operation);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11: {
|
||||||
|
IfBlock(ref func);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 15: {
|
||||||
|
WhileBlock(ref func);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 19: {
|
||||||
|
EchoStatement(ref func);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20: {
|
||||||
|
SayStatement(ref func);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 21: {
|
||||||
|
DisplayStatement(ref func);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
ForBlock(ref func);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(13);
|
||||||
|
parent.Children.Add(func);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void EchoStatement(ref MacroOperation parent) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation echoStatement = new MacroOperation(OperationType.Echo);
|
||||||
|
string statement = string.Empty;
|
||||||
|
|
||||||
|
Expect(19);
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
echoStatement.Children.Add(operation);
|
||||||
|
parent.Children.Add(echoStatement);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SayStatement(ref MacroOperation parent) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation sayStatement = new MacroOperation(OperationType.Say);
|
||||||
|
string statement = string.Empty;
|
||||||
|
|
||||||
|
Expect(20);
|
||||||
|
Expect(7);
|
||||||
|
statement = t.val.Replace("\"", "");
|
||||||
|
sayStatement.Input.Add(statement);
|
||||||
|
parent.Children.Add(sayStatement);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DisplayStatement(ref MacroOperation parent) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation displayStatement = new MacroOperation(OperationType.Display);
|
||||||
|
string statement = string.Empty;
|
||||||
|
|
||||||
|
Expect(21);
|
||||||
|
if (StartOf(2)) {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
|
||||||
|
} else if (la.kind == 7) {
|
||||||
|
Get();
|
||||||
|
statement = t.val.Replace("\"", "");
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.String);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
|
||||||
|
} else SynErr(36);
|
||||||
|
while (la.kind == 17) {
|
||||||
|
Get();
|
||||||
|
if (StartOf(2)) {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
|
||||||
|
} else if (la.kind == 7) {
|
||||||
|
Get();
|
||||||
|
statement = t.val.Replace("\"", "");
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.String);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
|
||||||
|
} else SynErr(37);
|
||||||
|
}
|
||||||
|
parent.Children.Add(displayStatement);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void ForBlock(ref MacroOperation parent) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
string statement = string.Empty;
|
||||||
|
string statement2 = string.Empty;
|
||||||
|
MacroOperation forBlock = new MacroOperation(OperationType.For);
|
||||||
|
|
||||||
|
Expect(16);
|
||||||
|
Expect(8);
|
||||||
|
Statement(out statement);
|
||||||
|
Expect(17);
|
||||||
|
Comparison(ref builder);
|
||||||
|
Expect(17);
|
||||||
|
Statement(out statement2);
|
||||||
|
forBlock.Input.Add(statement); forBlock.Input.Add(builder.ToString()); forBlock.Input.Add(statement2);
|
||||||
|
Expect(9);
|
||||||
|
Expect(12);
|
||||||
|
while (StartOf(3)) {
|
||||||
|
switch (la.kind) {
|
||||||
|
case 1: case 3: case 4: case 5: case 8: case 22: case 23: {
|
||||||
|
Statement(out statement);
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
forBlock.Children.Add(operation);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 11: {
|
||||||
|
IfBlock(ref forBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 15: {
|
||||||
|
WhileBlock(ref forBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 19: {
|
||||||
|
EchoStatement(ref forBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 20: {
|
||||||
|
SayStatement(ref forBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 21: {
|
||||||
|
DisplayStatement(ref forBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 16: {
|
||||||
|
ForBlock(ref forBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Expect(13);
|
||||||
|
parent.Children.Add(forBlock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Comparison(ref StringBuilder result) {
|
||||||
|
Expression(ref result);
|
||||||
|
Expect(10);
|
||||||
|
result.Append(t.val);
|
||||||
|
Expression(ref result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommaList(ref StringBuilder builder) {
|
||||||
|
Expression(ref builder);
|
||||||
|
while (la.kind == 17) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Expression(ref builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assignment(ref StringBuilder builder) {
|
||||||
|
Expect(1);
|
||||||
|
builder.Append(t.val);
|
||||||
|
if (la.kind == 30) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Expression(ref builder);
|
||||||
|
} else if (la.kind == 31) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val); string value = string.Empty;
|
||||||
|
AnyExpression(out value);
|
||||||
|
builder.Append(value);
|
||||||
|
Expect(6);
|
||||||
|
} else if (la.kind == 32) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
ArrayL(ref builder);
|
||||||
|
} else SynErr(38);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expression(ref StringBuilder builder) {
|
||||||
|
Term(ref builder);
|
||||||
|
while (la.kind == 22 || la.kind == 23 || la.kind == 24) {
|
||||||
|
if (la.kind == 22) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Term(ref builder);
|
||||||
|
} else if (la.kind == 23) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Term(ref builder);
|
||||||
|
} else {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Term(ref builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Term(ref StringBuilder builder) {
|
||||||
|
Factor(ref builder);
|
||||||
|
while (la.kind == 25 || la.kind == 26) {
|
||||||
|
if (la.kind == 25) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Factor(ref builder);
|
||||||
|
} else {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Factor(ref builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Factor(ref StringBuilder builder) {
|
||||||
|
Value(ref builder);
|
||||||
|
while (la.kind == 27) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Value(ref builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Value(ref StringBuilder builder) {
|
||||||
|
if (la.kind == 22 || la.kind == 23) {
|
||||||
|
if (la.kind == 22) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
} else {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (IsFunctionCall()) {
|
||||||
|
Function(ref builder);
|
||||||
|
} else if (IsArrayCall()) {
|
||||||
|
ArrayCall(ref builder);
|
||||||
|
} else if (la.kind == 1) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
} else if (la.kind == 5) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
} else if (la.kind == 4) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
} else if (la.kind == 3) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
} else if (la.kind == 8) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
Expression(ref builder);
|
||||||
|
Expect(9);
|
||||||
|
builder.Append(t.val);
|
||||||
|
} else SynErr(39);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Function(ref StringBuilder builder) {
|
||||||
|
Expect(1);
|
||||||
|
builder.Append(t.val);
|
||||||
|
Expect(8);
|
||||||
|
builder.Append(t.val);
|
||||||
|
CommaList(ref builder);
|
||||||
|
Expect(9);
|
||||||
|
builder.Append(t.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayCall(ref StringBuilder builder) {
|
||||||
|
Expect(1);
|
||||||
|
builder.Append(t.val);
|
||||||
|
Expect(28);
|
||||||
|
builder.Append(t.val);
|
||||||
|
Expression(ref builder);
|
||||||
|
Expect(29);
|
||||||
|
builder.Append(t.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArrayL(ref StringBuilder builder) {
|
||||||
|
Expect(28);
|
||||||
|
builder.Append(t.val);
|
||||||
|
CommaList(ref builder);
|
||||||
|
Expect(29);
|
||||||
|
builder.Append(t.val);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AnyExpression(out string value) {
|
||||||
|
value = string.Empty; StringBuilder builder = new StringBuilder();
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
while (StartOf(4)) {
|
||||||
|
Get();
|
||||||
|
builder.Append(t.val);
|
||||||
|
}
|
||||||
|
Expect(33);
|
||||||
|
value = builder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void Parse() {
|
||||||
|
la = new Token();
|
||||||
|
la.val = "";
|
||||||
|
Get();
|
||||||
|
SCRIPT();
|
||||||
|
Expect(0);
|
||||||
|
|
||||||
|
Expect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly bool[,] set = {
|
||||||
|
{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x},
|
||||||
|
{x,T,x,T, T,T,x,x, T,x,x,T, x,x,x,T, T,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x},
|
||||||
|
{x,T,x,T, T,T,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, x,x,x,x, x,x,x,x, x,x,x,x},
|
||||||
|
{x,T,x,T, T,T,x,x, T,x,x,T, x,x,x,T, T,x,x,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x,x,x},
|
||||||
|
{x,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,T,T,T, T,x,T,x}
|
||||||
|
|
||||||
|
};
|
||||||
|
} // end Parser
|
||||||
|
|
||||||
|
|
||||||
|
public class Errors {
|
||||||
|
public int count = 0; // number of errors detected
|
||||||
|
public System.IO.TextWriter errorStream = Console.Out; // error messages go to this stream
|
||||||
|
public string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
|
||||||
|
|
||||||
|
public void SynErr (int line, int col, int n) {
|
||||||
|
string s;
|
||||||
|
switch (n) {
|
||||||
|
case 0: s = "EOF expected"; break;
|
||||||
|
case 1: s = "identifier expected"; break;
|
||||||
|
case 2: s = "sign expected"; break;
|
||||||
|
case 3: s = "binary expected"; break;
|
||||||
|
case 4: s = "hex expected"; break;
|
||||||
|
case 5: s = "number expected"; break;
|
||||||
|
case 6: s = "newline expected"; break;
|
||||||
|
case 7: s = "string expected"; break;
|
||||||
|
case 8: s = "LPAREN expected"; break;
|
||||||
|
case 9: s = "RPAREN expected"; break;
|
||||||
|
case 10: s = "COMPARER expected"; break;
|
||||||
|
case 11: s = "\"if\" expected"; break;
|
||||||
|
case 12: s = "\"{\" expected"; break;
|
||||||
|
case 13: s = "\"}\" expected"; break;
|
||||||
|
case 14: s = "\"else\" expected"; break;
|
||||||
|
case 15: s = "\"while\" expected"; break;
|
||||||
|
case 16: s = "\"for\" expected"; break;
|
||||||
|
case 17: s = "\",\" expected"; break;
|
||||||
|
case 18: s = "\"function\" expected"; break;
|
||||||
|
case 19: s = "\"echo:\" expected"; break;
|
||||||
|
case 20: s = "\"say:\" expected"; break;
|
||||||
|
case 21: s = "\"display:\" expected"; break;
|
||||||
|
case 22: s = "\"+\" expected"; break;
|
||||||
|
case 23: s = "\"-\" expected"; break;
|
||||||
|
case 24: s = "\"%\" expected"; break;
|
||||||
|
case 25: s = "\"*\" expected"; break;
|
||||||
|
case 26: s = "\"/\" expected"; break;
|
||||||
|
case 27: s = "\"^\" expected"; break;
|
||||||
|
case 28: s = "\"[\" expected"; break;
|
||||||
|
case 29: s = "\"]\" expected"; break;
|
||||||
|
case 30: s = "\"::\" expected"; break;
|
||||||
|
case 31: s = "\":=\" expected"; break;
|
||||||
|
case 32: s = "\"->\" expected"; break;
|
||||||
|
case 33: s = "\"\\n\" expected"; break;
|
||||||
|
case 34: s = "??? expected"; break;
|
||||||
|
case 35: s = "invalid Statement"; break;
|
||||||
|
case 36: s = "invalid DisplayStatement"; break;
|
||||||
|
case 37: s = "invalid DisplayStatement"; break;
|
||||||
|
case 38: s = "invalid Assignment"; break;
|
||||||
|
case 39: s = "invalid Value"; break;
|
||||||
|
|
||||||
|
default: s = "error " + n; break;
|
||||||
|
}
|
||||||
|
errorStream.WriteLine(errMsgFormat, line, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (int line, int col, string s) {
|
||||||
|
errorStream.WriteLine(errMsgFormat, line, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string s) {
|
||||||
|
errorStream.WriteLine(s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning (int line, int col, string s) {
|
||||||
|
errorStream.WriteLine(errMsgFormat, line, col, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning(string s) {
|
||||||
|
errorStream.WriteLine(s);
|
||||||
|
}
|
||||||
|
} // Errors
|
||||||
|
|
||||||
|
|
||||||
|
public class FatalError: Exception {
|
||||||
|
public FatalError(string m): base(m) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
160
CS-MIC/csmic/csmic/ScriptParser/Parser.frame
Normal file
160
CS-MIC/csmic/csmic/ScriptParser/Parser.frame
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
Compiler Generator Coco/R,
|
||||||
|
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
||||||
|
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
||||||
|
with improvements by Pat Terry, Rhodes University
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
As an exception, it is allowed to write an extension of Coco/R that is
|
||||||
|
used as a plugin in non-free software.
|
||||||
|
|
||||||
|
If not otherwise stated, any source code generated by Coco/R (other than
|
||||||
|
Coco/R itself) does not fall under the GNU General Public License.
|
||||||
|
----------------------------------------------------------------------*/
|
||||||
|
-->begin
|
||||||
|
using System;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
-->namespace
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Parser {
|
||||||
|
-->constants
|
||||||
|
const bool T = true;
|
||||||
|
const bool x = false;
|
||||||
|
const int minErrDist = 2;
|
||||||
|
|
||||||
|
public Scanner scanner;
|
||||||
|
public Errors errors;
|
||||||
|
|
||||||
|
public Token t; // last recognized token
|
||||||
|
public Token la; // lookahead token
|
||||||
|
int errDist = minErrDist;
|
||||||
|
|
||||||
|
-->declarations
|
||||||
|
|
||||||
|
public Parser(Scanner scanner) {
|
||||||
|
this.scanner = scanner;
|
||||||
|
errors = new Errors();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SynErr (int n) {
|
||||||
|
if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string msg) {
|
||||||
|
if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg);
|
||||||
|
errDist = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Get () {
|
||||||
|
for (;;) {
|
||||||
|
t = la;
|
||||||
|
la = scanner.Scan();
|
||||||
|
if (la.kind <= maxT) { ++errDist; break; }
|
||||||
|
-->pragmas
|
||||||
|
la = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Expect (int n) {
|
||||||
|
if (la.kind==n) Get(); else { SynErr(n); }
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StartOf (int s) {
|
||||||
|
return set[s, la.kind];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ExpectWeak (int n, int follow) {
|
||||||
|
if (la.kind == n) Get();
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!StartOf(follow)) Get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool WeakSeparator(int n, int syFol, int repFol) {
|
||||||
|
int kind = la.kind;
|
||||||
|
if (kind == n) {Get(); return true;}
|
||||||
|
else if (StartOf(repFol)) {return false;}
|
||||||
|
else {
|
||||||
|
SynErr(n);
|
||||||
|
while (!(set[syFol, kind] || set[repFol, kind] || set[0, kind])) {
|
||||||
|
Get();
|
||||||
|
kind = la.kind;
|
||||||
|
}
|
||||||
|
return StartOf(syFol);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-->productions
|
||||||
|
|
||||||
|
public void Parse() {
|
||||||
|
la = new Token();
|
||||||
|
la.val = "";
|
||||||
|
Get();
|
||||||
|
-->parseRoot
|
||||||
|
Expect(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static readonly bool[,] set = {
|
||||||
|
-->initialization
|
||||||
|
};
|
||||||
|
} // end Parser
|
||||||
|
|
||||||
|
|
||||||
|
public class Errors {
|
||||||
|
public int count = 0; // number of errors detected
|
||||||
|
public System.IO.TextWriter errorStream = Console.Out; // error messages go to this stream
|
||||||
|
public string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
|
||||||
|
|
||||||
|
public void SynErr (int line, int col, int n) {
|
||||||
|
string s;
|
||||||
|
switch (n) {
|
||||||
|
-->errors
|
||||||
|
default: s = "error " + n; break;
|
||||||
|
}
|
||||||
|
errorStream.WriteLine(errMsgFormat, line, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (int line, int col, string s) {
|
||||||
|
errorStream.WriteLine(errMsgFormat, line, col, s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SemErr (string s) {
|
||||||
|
errorStream.WriteLine(s);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning (int line, int col, string s) {
|
||||||
|
errorStream.WriteLine(errMsgFormat, line, col, s);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warning(string s) {
|
||||||
|
errorStream.WriteLine(s);
|
||||||
|
}
|
||||||
|
} // Errors
|
||||||
|
|
||||||
|
|
||||||
|
public class FatalError: Exception {
|
||||||
|
public FatalError(string m): base(m) {}
|
||||||
|
}
|
||||||
|
|
637
CS-MIC/csmic/csmic/ScriptParser/Scanner.cs
Normal file
637
CS-MIC/csmic/csmic/ScriptParser/Scanner.cs
Normal file
|
@ -0,0 +1,637 @@
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
namespace csmic.Scripting {
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Token {
|
||||||
|
public int kind; // token kind
|
||||||
|
public int pos; // token position in bytes in the source text (starting at 0)
|
||||||
|
public int charPos; // token position in characters in the source text (starting at 0)
|
||||||
|
public int col; // token column (starting at 1)
|
||||||
|
public int line; // token line (starting at 1)
|
||||||
|
public string val; // token value
|
||||||
|
public Token next; // ML 2005-03-11 Tokens are kept in linked list
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Buffer {
|
||||||
|
// This Buffer supports the following cases:
|
||||||
|
// 1) seekable stream (file)
|
||||||
|
// a) whole stream in buffer
|
||||||
|
// b) part of stream in buffer
|
||||||
|
// 2) non seekable stream (network, console)
|
||||||
|
|
||||||
|
public const int EOF = char.MaxValue + 1;
|
||||||
|
const int MIN_BUFFER_LENGTH = 1024; // 1KB
|
||||||
|
const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
|
||||||
|
byte[] buf; // input buffer
|
||||||
|
int bufStart; // position of first byte in buffer relative to input stream
|
||||||
|
int bufLen; // length of buffer
|
||||||
|
int fileLen; // length of input stream (may change if the stream is no file)
|
||||||
|
int bufPos; // current position in buffer
|
||||||
|
Stream stream; // input stream (seekable)
|
||||||
|
bool isUserStream; // was the stream opened by the user?
|
||||||
|
|
||||||
|
public Buffer (Stream s, bool isUserStream) {
|
||||||
|
stream = s; this.isUserStream = isUserStream;
|
||||||
|
|
||||||
|
if (stream.CanSeek) {
|
||||||
|
fileLen = (int) stream.Length;
|
||||||
|
bufLen = Math.Min(fileLen, MAX_BUFFER_LENGTH);
|
||||||
|
bufStart = Int32.MaxValue; // nothing in the buffer so far
|
||||||
|
} else {
|
||||||
|
fileLen = bufLen = bufStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = new byte[(bufLen>0) ? bufLen : MIN_BUFFER_LENGTH];
|
||||||
|
if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
|
||||||
|
else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
|
||||||
|
if (bufLen == fileLen && stream.CanSeek) Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Buffer(Buffer b) { // called in UTF8Buffer constructor
|
||||||
|
buf = b.buf;
|
||||||
|
bufStart = b.bufStart;
|
||||||
|
bufLen = b.bufLen;
|
||||||
|
fileLen = b.fileLen;
|
||||||
|
bufPos = b.bufPos;
|
||||||
|
stream = b.stream;
|
||||||
|
// keep destructor from closing the stream
|
||||||
|
b.stream = null;
|
||||||
|
isUserStream = b.isUserStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Buffer() { Close(); }
|
||||||
|
|
||||||
|
protected void Close() {
|
||||||
|
if (!isUserStream && stream != null) {
|
||||||
|
stream.Close();
|
||||||
|
stream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int Read () {
|
||||||
|
if (bufPos < bufLen) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (Pos < fileLen) {
|
||||||
|
Pos = Pos; // shift buffer start to Pos
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (stream != null && !stream.CanSeek && ReadNextStreamChunk() > 0) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else {
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Peek () {
|
||||||
|
int curPos = Pos;
|
||||||
|
int ch = Read();
|
||||||
|
Pos = curPos;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// beg .. begin, zero-based, inclusive, in byte
|
||||||
|
// end .. end, zero-based, exclusive, in byte
|
||||||
|
public string GetString (int beg, int end) {
|
||||||
|
int len = 0;
|
||||||
|
char[] buf = new char[end - beg];
|
||||||
|
int oldPos = Pos;
|
||||||
|
Pos = beg;
|
||||||
|
while (Pos < end) buf[len++] = (char) Read();
|
||||||
|
Pos = oldPos;
|
||||||
|
return new String(buf, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Pos {
|
||||||
|
get { return bufPos + bufStart; }
|
||||||
|
set {
|
||||||
|
if (value >= fileLen && stream != null && !stream.CanSeek) {
|
||||||
|
// Wanted position is after buffer and the stream
|
||||||
|
// is not seek-able e.g. network or console,
|
||||||
|
// thus we have to read the stream manually till
|
||||||
|
// the wanted position is in sight.
|
||||||
|
while (value >= fileLen && ReadNextStreamChunk() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 || value > fileLen) {
|
||||||
|
throw new FatalError("buffer out of bounds access, position: " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
|
||||||
|
bufPos = value - bufStart;
|
||||||
|
} else if (stream != null) { // must be swapped in
|
||||||
|
stream.Seek(value, SeekOrigin.Begin);
|
||||||
|
bufLen = stream.Read(buf, 0, buf.Length);
|
||||||
|
bufStart = value; bufPos = 0;
|
||||||
|
} else {
|
||||||
|
// set the position to the end of the file, Pos will return fileLen.
|
||||||
|
bufPos = fileLen - bufStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next chunk of bytes from the stream, increases the buffer
|
||||||
|
// if needed and updates the fields fileLen and bufLen.
|
||||||
|
// Returns the number of bytes read.
|
||||||
|
private int ReadNextStreamChunk() {
|
||||||
|
int free = buf.Length - bufLen;
|
||||||
|
if (free == 0) {
|
||||||
|
// in the case of a growing input stream
|
||||||
|
// we can neither seek in the stream, nor can we
|
||||||
|
// foresee the maximum length, thus we must adapt
|
||||||
|
// the buffer size on demand.
|
||||||
|
byte[] newBuf = new byte[bufLen * 2];
|
||||||
|
Array.Copy(buf, newBuf, bufLen);
|
||||||
|
buf = newBuf;
|
||||||
|
free = bufLen;
|
||||||
|
}
|
||||||
|
int read = stream.Read(buf, bufLen, free);
|
||||||
|
if (read > 0) {
|
||||||
|
fileLen = bufLen = (bufLen + read);
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
// end of stream reached
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// UTF8Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class UTF8Buffer: Buffer {
|
||||||
|
public UTF8Buffer(Buffer b): base(b) {}
|
||||||
|
|
||||||
|
public override int Read() {
|
||||||
|
int ch;
|
||||||
|
do {
|
||||||
|
ch = base.Read();
|
||||||
|
// until we find a utf8 start (0xxxxxxx or 11xxxxxx)
|
||||||
|
} while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
|
||||||
|
if (ch < 128 || ch == EOF) {
|
||||||
|
// nothing to do, first 127 chars are the same in ascii and utf8
|
||||||
|
// 0xxxxxxx or end of file character
|
||||||
|
} else if ((ch & 0xF0) == 0xF0) {
|
||||||
|
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x07; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c4 = ch & 0x3F;
|
||||||
|
ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
|
||||||
|
} else if ((ch & 0xE0) == 0xE0) {
|
||||||
|
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x0F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F;
|
||||||
|
ch = (((c1 << 6) | c2) << 6) | c3;
|
||||||
|
} else if ((ch & 0xC0) == 0xC0) {
|
||||||
|
// 110xxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x1F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F;
|
||||||
|
ch = (c1 << 6) | c2;
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Scanner
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Scanner {
|
||||||
|
const char EOL = '\n';
|
||||||
|
const int eofSym = 0; /* pdt */
|
||||||
|
const int maxT = 34;
|
||||||
|
const int noSym = 34;
|
||||||
|
|
||||||
|
|
||||||
|
public Buffer buffer; // scanner buffer
|
||||||
|
|
||||||
|
Token t; // current token
|
||||||
|
int ch; // current input character
|
||||||
|
int pos; // byte position of current character
|
||||||
|
int charPos; // position by unicode characters starting with 0
|
||||||
|
int col; // column number of current character
|
||||||
|
int line; // line number of current character
|
||||||
|
int oldEols; // EOLs that appeared in a comment;
|
||||||
|
static readonly Dictionary<int, int> start; // maps first token character to start state
|
||||||
|
|
||||||
|
Token tokens; // list of tokens already peeked (first token is a dummy)
|
||||||
|
Token pt; // current peek token
|
||||||
|
|
||||||
|
char[] tval = new char[128]; // text of current token
|
||||||
|
int tlen; // length of current token
|
||||||
|
|
||||||
|
static Scanner() {
|
||||||
|
start = new Dictionary<int, int>(128);
|
||||||
|
for (int i = 65; i <= 90; ++i) start[i] = 1;
|
||||||
|
for (int i = 97; i <= 99; ++i) start[i] = 1;
|
||||||
|
for (int i = 102; i <= 114; ++i) start[i] = 1;
|
||||||
|
for (int i = 116; i <= 122; ++i) start[i] = 1;
|
||||||
|
start[43] = 2;
|
||||||
|
for (int i = 50; i <= 57; ++i) start[i] = 6;
|
||||||
|
for (int i = 10; i <= 10; ++i) start[i] = 12;
|
||||||
|
for (int i = 13; i <= 13; ++i) start[i] = 11;
|
||||||
|
start[48] = 19;
|
||||||
|
start[49] = 20;
|
||||||
|
start[34] = 13;
|
||||||
|
start[40] = 15;
|
||||||
|
start[41] = 16;
|
||||||
|
start[61] = 17;
|
||||||
|
start[60] = 21;
|
||||||
|
start[62] = 22;
|
||||||
|
start[123] = 23;
|
||||||
|
start[125] = 24;
|
||||||
|
start[44] = 25;
|
||||||
|
start[101] = 38;
|
||||||
|
start[115] = 39;
|
||||||
|
start[100] = 40;
|
||||||
|
start[37] = 29;
|
||||||
|
start[42] = 30;
|
||||||
|
start[47] = 31;
|
||||||
|
start[94] = 32;
|
||||||
|
start[91] = 33;
|
||||||
|
start[93] = 34;
|
||||||
|
start[58] = 41;
|
||||||
|
start[45] = 42;
|
||||||
|
start[Buffer.EOF] = -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (string fileName) {
|
||||||
|
try {
|
||||||
|
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
buffer = new Buffer(stream, false);
|
||||||
|
Init();
|
||||||
|
} catch (IOException) {
|
||||||
|
throw new FatalError("Cannot open file " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (Stream s) {
|
||||||
|
buffer = new Buffer(s, true);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
pos = -1; line = 1; col = 0; charPos = -1;
|
||||||
|
oldEols = 0;
|
||||||
|
NextCh();
|
||||||
|
if (ch == 0xEF) { // check optional byte order mark for UTF-8
|
||||||
|
NextCh(); int ch1 = ch;
|
||||||
|
NextCh(); int ch2 = ch;
|
||||||
|
if (ch1 != 0xBB || ch2 != 0xBF) {
|
||||||
|
throw new FatalError(String.Format("illegal byte order mark: EF {0,2:X} {1,2:X}", ch1, ch2));
|
||||||
|
}
|
||||||
|
buffer = new UTF8Buffer(buffer); col = 0; charPos = -1;
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
pt = tokens = new Token(); // first token is a dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextCh() {
|
||||||
|
if (oldEols > 0) { ch = EOL; oldEols--; }
|
||||||
|
else {
|
||||||
|
pos = buffer.Pos;
|
||||||
|
// buffer reads unicode chars, if UTF8 has been detected
|
||||||
|
ch = buffer.Read(); col++; charPos++;
|
||||||
|
// replace isolated '\r' by '\n' in order to make
|
||||||
|
// eol handling uniform across Windows, Unix and Mac
|
||||||
|
if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
|
||||||
|
if (ch == EOL) { line++; col = 0; }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddCh() {
|
||||||
|
if (tlen >= tval.Length) {
|
||||||
|
char[] newBuf = new char[2 * tval.Length];
|
||||||
|
Array.Copy(tval, 0, newBuf, 0, tval.Length);
|
||||||
|
tval = newBuf;
|
||||||
|
}
|
||||||
|
if (ch != Buffer.EOF) {
|
||||||
|
tval[tlen++] = (char) ch;
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bool Comment0() {
|
||||||
|
int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
|
||||||
|
NextCh();
|
||||||
|
if (ch == '/') {
|
||||||
|
NextCh();
|
||||||
|
for(;;) {
|
||||||
|
if (ch == 10) {
|
||||||
|
level--;
|
||||||
|
if (level == 0) { oldEols = line - line0; NextCh(); return true; }
|
||||||
|
NextCh();
|
||||||
|
} else if (ch == Buffer.EOF) return false;
|
||||||
|
else NextCh();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Comment1() {
|
||||||
|
int level = 1, pos0 = pos, line0 = line, col0 = col, charPos0 = charPos;
|
||||||
|
NextCh();
|
||||||
|
if (ch == '*') {
|
||||||
|
NextCh();
|
||||||
|
for(;;) {
|
||||||
|
if (ch == '*') {
|
||||||
|
NextCh();
|
||||||
|
if (ch == '/') {
|
||||||
|
level--;
|
||||||
|
if (level == 0) { oldEols = line - line0; NextCh(); return true; }
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
} else if (ch == '/') {
|
||||||
|
NextCh();
|
||||||
|
if (ch == '*') {
|
||||||
|
level++; NextCh();
|
||||||
|
}
|
||||||
|
} else if (ch == Buffer.EOF) return false;
|
||||||
|
else NextCh();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
buffer.Pos = pos0; NextCh(); line = line0; col = col0; charPos = charPos0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CheckLiteral() {
|
||||||
|
switch (t.val) {
|
||||||
|
case "if": t.kind = 11; break;
|
||||||
|
case "else": t.kind = 14; break;
|
||||||
|
case "while": t.kind = 15; break;
|
||||||
|
case "for": t.kind = 16; break;
|
||||||
|
case "function": t.kind = 18; break;
|
||||||
|
case "+": t.kind = 22; break;
|
||||||
|
case "-": t.kind = 23; break;
|
||||||
|
case "\n": t.kind = 33; break;
|
||||||
|
default: break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Token NextToken() {
|
||||||
|
while (ch == ' ' ||
|
||||||
|
ch >= 9 && ch <= 10 || ch == 13
|
||||||
|
) NextCh();
|
||||||
|
if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken();
|
||||||
|
int recKind = noSym;
|
||||||
|
int recEnd = pos;
|
||||||
|
t = new Token();
|
||||||
|
t.pos = pos; t.col = col; t.line = line; t.charPos = charPos;
|
||||||
|
int state;
|
||||||
|
state = (int) start[ch];
|
||||||
|
tlen = 0; AddCh();
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case -1: { t.kind = eofSym; break; } // NextCh already done
|
||||||
|
case 0: {
|
||||||
|
if (recKind != noSym) {
|
||||||
|
tlen = recEnd - t.pos;
|
||||||
|
SetScannerBehindT();
|
||||||
|
}
|
||||||
|
t.kind = recKind; break;
|
||||||
|
} // NextCh already done
|
||||||
|
case 1:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 2:
|
||||||
|
{t.kind = 2; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 3:
|
||||||
|
{t.kind = 3; break;}
|
||||||
|
case 4:
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {AddCh(); goto case 5;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 5:
|
||||||
|
recEnd = pos; recKind = 4;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {AddCh(); goto case 5;}
|
||||||
|
else {t.kind = 4; break;}
|
||||||
|
case 6:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 6;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else if (ch == '.') {AddCh(); goto case 10;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 7:
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
|
||||||
|
else if (ch == '+' || ch == '-') {AddCh(); goto case 8;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 8:
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 9:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 9;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 10:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '0' && ch <= '9') {AddCh(); goto case 10;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 11:
|
||||||
|
if (ch == 10) {AddCh(); goto case 12;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 12:
|
||||||
|
{t.kind = 6; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 13:
|
||||||
|
if (ch <= '!' || ch >= '#' && ch <= 65535) {AddCh(); goto case 13;}
|
||||||
|
else if (ch == '"') {AddCh(); goto case 14;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 14:
|
||||||
|
{t.kind = 7; break;}
|
||||||
|
case 15:
|
||||||
|
{t.kind = 8; break;}
|
||||||
|
case 16:
|
||||||
|
{t.kind = 9; break;}
|
||||||
|
case 17:
|
||||||
|
if (ch == '=') {AddCh(); goto case 18;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 18:
|
||||||
|
{t.kind = 10; break;}
|
||||||
|
case 19:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '2' && ch <= '9') {AddCh(); goto case 6;}
|
||||||
|
else if (ch == 'B' || ch == 'b') {AddCh(); goto case 3;}
|
||||||
|
else if (ch >= '0' && ch <= '1') {AddCh(); goto case 20;}
|
||||||
|
else if (ch == 'x') {AddCh(); goto case 4;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else if (ch == '.') {AddCh(); goto case 10;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 20:
|
||||||
|
recEnd = pos; recKind = 5;
|
||||||
|
if (ch >= '2' && ch <= '9') {AddCh(); goto case 6;}
|
||||||
|
else if (ch == 'B' || ch == 'b') {AddCh(); goto case 3;}
|
||||||
|
else if (ch >= '0' && ch <= '1') {AddCh(); goto case 20;}
|
||||||
|
else if (ch == 'E' || ch == 'e') {AddCh(); goto case 7;}
|
||||||
|
else if (ch == '.') {AddCh(); goto case 10;}
|
||||||
|
else {t.kind = 5; break;}
|
||||||
|
case 21:
|
||||||
|
recEnd = pos; recKind = 10;
|
||||||
|
if (ch == '=') {AddCh(); goto case 18;}
|
||||||
|
else {t.kind = 10; break;}
|
||||||
|
case 22:
|
||||||
|
recEnd = pos; recKind = 10;
|
||||||
|
if (ch == '=') {AddCh(); goto case 18;}
|
||||||
|
else {t.kind = 10; break;}
|
||||||
|
case 23:
|
||||||
|
{t.kind = 12; break;}
|
||||||
|
case 24:
|
||||||
|
{t.kind = 13; break;}
|
||||||
|
case 25:
|
||||||
|
{t.kind = 17; break;}
|
||||||
|
case 26:
|
||||||
|
{t.kind = 19; break;}
|
||||||
|
case 27:
|
||||||
|
{t.kind = 20; break;}
|
||||||
|
case 28:
|
||||||
|
{t.kind = 21; break;}
|
||||||
|
case 29:
|
||||||
|
{t.kind = 24; break;}
|
||||||
|
case 30:
|
||||||
|
{t.kind = 25; break;}
|
||||||
|
case 31:
|
||||||
|
{t.kind = 26; break;}
|
||||||
|
case 32:
|
||||||
|
{t.kind = 27; break;}
|
||||||
|
case 33:
|
||||||
|
{t.kind = 28; break;}
|
||||||
|
case 34:
|
||||||
|
{t.kind = 29; break;}
|
||||||
|
case 35:
|
||||||
|
{t.kind = 30; break;}
|
||||||
|
case 36:
|
||||||
|
{t.kind = 31; break;}
|
||||||
|
case 37:
|
||||||
|
{t.kind = 32; break;}
|
||||||
|
case 38:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'b' || ch >= 'd' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'c') {AddCh(); goto case 43;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 39:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'b' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'a') {AddCh(); goto case 44;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 40:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'h' || ch >= 'j' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'i') {AddCh(); goto case 45;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 41:
|
||||||
|
if (ch == ':') {AddCh(); goto case 35;}
|
||||||
|
else if (ch == '=') {AddCh(); goto case 36;}
|
||||||
|
else {goto case 0;}
|
||||||
|
case 42:
|
||||||
|
recEnd = pos; recKind = 2;
|
||||||
|
if (ch == '>') {AddCh(); goto case 37;}
|
||||||
|
else {t.kind = 2; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 43:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'g' || ch >= 'i' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'h') {AddCh(); goto case 46;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 44:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'x' || ch == 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'y') {AddCh(); goto case 47;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 45:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'r' || ch >= 't' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 's') {AddCh(); goto case 48;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 46:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'n' || ch >= 'p' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'o') {AddCh(); goto case 49;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 47:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == ':') {AddCh(); goto case 27;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 48:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'o' || ch >= 'q' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'p') {AddCh(); goto case 50;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 49:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == ':') {AddCh(); goto case 26;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 50:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'k' || ch >= 'm' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'l') {AddCh(); goto case 51;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 51:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'b' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'a') {AddCh(); goto case 52;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 52:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'x' || ch == 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == 'y') {AddCh(); goto case 53;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
case 53:
|
||||||
|
recEnd = pos; recKind = 1;
|
||||||
|
if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); goto case 1;}
|
||||||
|
else if (ch == ':') {AddCh(); goto case 28;}
|
||||||
|
else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;}
|
||||||
|
|
||||||
|
}
|
||||||
|
t.val = new String(tval, 0, tlen);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetScannerBehindT() {
|
||||||
|
buffer.Pos = t.pos;
|
||||||
|
NextCh();
|
||||||
|
line = t.line; col = t.col; charPos = t.charPos;
|
||||||
|
for (int i = 0; i < tlen; i++) NextCh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next token (possibly a token already seen during peeking)
|
||||||
|
public Token Scan () {
|
||||||
|
if (tokens.next == null) {
|
||||||
|
return NextToken();
|
||||||
|
} else {
|
||||||
|
pt = tokens = tokens.next;
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek for the next token, ignore pragmas
|
||||||
|
public Token Peek () {
|
||||||
|
do {
|
||||||
|
if (pt.next == null) {
|
||||||
|
pt.next = NextToken();
|
||||||
|
}
|
||||||
|
pt = pt.next;
|
||||||
|
} while (pt.kind > maxT); // skip pragmas
|
||||||
|
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure that peeking starts at the current scan position
|
||||||
|
public void ResetPeek () { pt = tokens; }
|
||||||
|
|
||||||
|
} // end Scanner
|
||||||
|
}
|
383
CS-MIC/csmic/csmic/ScriptParser/Scanner.frame
Normal file
383
CS-MIC/csmic/csmic/ScriptParser/Scanner.frame
Normal file
|
@ -0,0 +1,383 @@
|
||||||
|
/*----------------------------------------------------------------------
|
||||||
|
Compiler Generator Coco/R,
|
||||||
|
Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
|
||||||
|
extended by M. Loeberbauer & A. Woess, Univ. of Linz
|
||||||
|
with improvements by Pat Terry, Rhodes University
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by the
|
||||||
|
Free Software Foundation; either version 2, or (at your option) any
|
||||||
|
later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but
|
||||||
|
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along
|
||||||
|
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
As an exception, it is allowed to write an extension of Coco/R that is
|
||||||
|
used as a plugin in non-free software.
|
||||||
|
|
||||||
|
If not otherwise stated, any source code generated by Coco/R (other than
|
||||||
|
Coco/R itself) does not fall under the GNU General Public License.
|
||||||
|
-----------------------------------------------------------------------*/
|
||||||
|
-->begin
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
|
||||||
|
-->namespace
|
||||||
|
|
||||||
|
[GeneratedCodeAttribute("Coco/R", "")]
|
||||||
|
public class Token {
|
||||||
|
public int kind; // token kind
|
||||||
|
public int pos; // token position in bytes in the source text (starting at 0)
|
||||||
|
public int charPos; // token position in characters in the source text (starting at 0)
|
||||||
|
public int col; // token column (starting at 1)
|
||||||
|
public int line; // token line (starting at 1)
|
||||||
|
public string val; // token value
|
||||||
|
public Token next; // ML 2005-03-11 Tokens are kept in linked list
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Buffer {
|
||||||
|
// This Buffer supports the following cases:
|
||||||
|
// 1) seekable stream (file)
|
||||||
|
// a) whole stream in buffer
|
||||||
|
// b) part of stream in buffer
|
||||||
|
// 2) non seekable stream (network, console)
|
||||||
|
|
||||||
|
public const int EOF = char.MaxValue + 1;
|
||||||
|
const int MIN_BUFFER_LENGTH = 1024; // 1KB
|
||||||
|
const int MAX_BUFFER_LENGTH = MIN_BUFFER_LENGTH * 64; // 64KB
|
||||||
|
byte[] buf; // input buffer
|
||||||
|
int bufStart; // position of first byte in buffer relative to input stream
|
||||||
|
int bufLen; // length of buffer
|
||||||
|
int fileLen; // length of input stream (may change if the stream is no file)
|
||||||
|
int bufPos; // current position in buffer
|
||||||
|
Stream stream; // input stream (seekable)
|
||||||
|
bool isUserStream; // was the stream opened by the user?
|
||||||
|
|
||||||
|
public Buffer (Stream s, bool isUserStream) {
|
||||||
|
stream = s; this.isUserStream = isUserStream;
|
||||||
|
|
||||||
|
if (stream.CanSeek) {
|
||||||
|
fileLen = (int) stream.Length;
|
||||||
|
bufLen = Math.Min(fileLen, MAX_BUFFER_LENGTH);
|
||||||
|
bufStart = Int32.MaxValue; // nothing in the buffer so far
|
||||||
|
} else {
|
||||||
|
fileLen = bufLen = bufStart = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf = new byte[(bufLen>0) ? bufLen : MIN_BUFFER_LENGTH];
|
||||||
|
if (fileLen > 0) Pos = 0; // setup buffer to position 0 (start)
|
||||||
|
else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
|
||||||
|
if (bufLen == fileLen && stream.CanSeek) Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Buffer(Buffer b) { // called in UTF8Buffer constructor
|
||||||
|
buf = b.buf;
|
||||||
|
bufStart = b.bufStart;
|
||||||
|
bufLen = b.bufLen;
|
||||||
|
fileLen = b.fileLen;
|
||||||
|
bufPos = b.bufPos;
|
||||||
|
stream = b.stream;
|
||||||
|
// keep destructor from closing the stream
|
||||||
|
b.stream = null;
|
||||||
|
isUserStream = b.isUserStream;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Buffer() { Close(); }
|
||||||
|
|
||||||
|
protected void Close() {
|
||||||
|
if (!isUserStream && stream != null) {
|
||||||
|
stream.Close();
|
||||||
|
stream = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual int Read () {
|
||||||
|
if (bufPos < bufLen) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (Pos < fileLen) {
|
||||||
|
Pos = Pos; // shift buffer start to Pos
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else if (stream != null && !stream.CanSeek && ReadNextStreamChunk() > 0) {
|
||||||
|
return buf[bufPos++];
|
||||||
|
} else {
|
||||||
|
return EOF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Peek () {
|
||||||
|
int curPos = Pos;
|
||||||
|
int ch = Read();
|
||||||
|
Pos = curPos;
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
|
||||||
|
// beg .. begin, zero-based, inclusive, in byte
|
||||||
|
// end .. end, zero-based, exclusive, in byte
|
||||||
|
public string GetString (int beg, int end) {
|
||||||
|
int len = 0;
|
||||||
|
char[] buf = new char[end - beg];
|
||||||
|
int oldPos = Pos;
|
||||||
|
Pos = beg;
|
||||||
|
while (Pos < end) buf[len++] = (char) Read();
|
||||||
|
Pos = oldPos;
|
||||||
|
return new String(buf, 0, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int Pos {
|
||||||
|
get { return bufPos + bufStart; }
|
||||||
|
set {
|
||||||
|
if (value >= fileLen && stream != null && !stream.CanSeek) {
|
||||||
|
// Wanted position is after buffer and the stream
|
||||||
|
// is not seek-able e.g. network or console,
|
||||||
|
// thus we have to read the stream manually till
|
||||||
|
// the wanted position is in sight.
|
||||||
|
while (value >= fileLen && ReadNextStreamChunk() > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value < 0 || value > fileLen) {
|
||||||
|
throw new FatalError("buffer out of bounds access, position: " + value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value >= bufStart && value < bufStart + bufLen) { // already in buffer
|
||||||
|
bufPos = value - bufStart;
|
||||||
|
} else if (stream != null) { // must be swapped in
|
||||||
|
stream.Seek(value, SeekOrigin.Begin);
|
||||||
|
bufLen = stream.Read(buf, 0, buf.Length);
|
||||||
|
bufStart = value; bufPos = 0;
|
||||||
|
} else {
|
||||||
|
// set the position to the end of the file, Pos will return fileLen.
|
||||||
|
bufPos = fileLen - bufStart;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the next chunk of bytes from the stream, increases the buffer
|
||||||
|
// if needed and updates the fields fileLen and bufLen.
|
||||||
|
// Returns the number of bytes read.
|
||||||
|
private int ReadNextStreamChunk() {
|
||||||
|
int free = buf.Length - bufLen;
|
||||||
|
if (free == 0) {
|
||||||
|
// in the case of a growing input stream
|
||||||
|
// we can neither seek in the stream, nor can we
|
||||||
|
// foresee the maximum length, thus we must adapt
|
||||||
|
// the buffer size on demand.
|
||||||
|
byte[] newBuf = new byte[bufLen * 2];
|
||||||
|
Array.Copy(buf, newBuf, bufLen);
|
||||||
|
buf = newBuf;
|
||||||
|
free = bufLen;
|
||||||
|
}
|
||||||
|
int read = stream.Read(buf, bufLen, free);
|
||||||
|
if (read > 0) {
|
||||||
|
fileLen = bufLen = (bufLen + read);
|
||||||
|
return read;
|
||||||
|
}
|
||||||
|
// end of stream reached
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// UTF8Buffer
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class UTF8Buffer: Buffer {
|
||||||
|
public UTF8Buffer(Buffer b): base(b) {}
|
||||||
|
|
||||||
|
public override int Read() {
|
||||||
|
int ch;
|
||||||
|
do {
|
||||||
|
ch = base.Read();
|
||||||
|
// until we find a utf8 start (0xxxxxxx or 11xxxxxx)
|
||||||
|
} while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EOF));
|
||||||
|
if (ch < 128 || ch == EOF) {
|
||||||
|
// nothing to do, first 127 chars are the same in ascii and utf8
|
||||||
|
// 0xxxxxxx or end of file character
|
||||||
|
} else if ((ch & 0xF0) == 0xF0) {
|
||||||
|
// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x07; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c4 = ch & 0x3F;
|
||||||
|
ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
|
||||||
|
} else if ((ch & 0xE0) == 0xE0) {
|
||||||
|
// 1110xxxx 10xxxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x0F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F; ch = base.Read();
|
||||||
|
int c3 = ch & 0x3F;
|
||||||
|
ch = (((c1 << 6) | c2) << 6) | c3;
|
||||||
|
} else if ((ch & 0xC0) == 0xC0) {
|
||||||
|
// 110xxxxx 10xxxxxx
|
||||||
|
int c1 = ch & 0x1F; ch = base.Read();
|
||||||
|
int c2 = ch & 0x3F;
|
||||||
|
ch = (c1 << 6) | c2;
|
||||||
|
}
|
||||||
|
return ch;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
// Scanner
|
||||||
|
//-----------------------------------------------------------------------------------
|
||||||
|
public class Scanner {
|
||||||
|
const char EOL = '\n';
|
||||||
|
const int eofSym = 0; /* pdt */
|
||||||
|
-->declarations
|
||||||
|
|
||||||
|
public Buffer buffer; // scanner buffer
|
||||||
|
|
||||||
|
Token t; // current token
|
||||||
|
int ch; // current input character
|
||||||
|
int pos; // byte position of current character
|
||||||
|
int charPos; // position by unicode characters starting with 0
|
||||||
|
int col; // column number of current character
|
||||||
|
int line; // line number of current character
|
||||||
|
int oldEols; // EOLs that appeared in a comment;
|
||||||
|
static readonly Dictionary<int, int> start; // maps first token character to start state
|
||||||
|
|
||||||
|
Token tokens; // list of tokens already peeked (first token is a dummy)
|
||||||
|
Token pt; // current peek token
|
||||||
|
|
||||||
|
char[] tval = new char[128]; // text of current token
|
||||||
|
int tlen; // length of current token
|
||||||
|
|
||||||
|
static Scanner() {
|
||||||
|
start = new Dictionary<int, int>(128);
|
||||||
|
-->initialization
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (string fileName) {
|
||||||
|
try {
|
||||||
|
Stream stream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
|
buffer = new Buffer(stream, false);
|
||||||
|
Init();
|
||||||
|
} catch (IOException) {
|
||||||
|
throw new FatalError("Cannot open file " + fileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scanner (Stream s) {
|
||||||
|
buffer = new Buffer(s, true);
|
||||||
|
Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Init() {
|
||||||
|
pos = -1; line = 1; col = 0; charPos = -1;
|
||||||
|
oldEols = 0;
|
||||||
|
NextCh();
|
||||||
|
if (ch == 0xEF) { // check optional byte order mark for UTF-8
|
||||||
|
NextCh(); int ch1 = ch;
|
||||||
|
NextCh(); int ch2 = ch;
|
||||||
|
if (ch1 != 0xBB || ch2 != 0xBF) {
|
||||||
|
throw new FatalError(String.Format("illegal byte order mark: EF {0,2:X} {1,2:X}", ch1, ch2));
|
||||||
|
}
|
||||||
|
buffer = new UTF8Buffer(buffer); col = 0; charPos = -1;
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
pt = tokens = new Token(); // first token is a dummy
|
||||||
|
}
|
||||||
|
|
||||||
|
void NextCh() {
|
||||||
|
if (oldEols > 0) { ch = EOL; oldEols--; }
|
||||||
|
else {
|
||||||
|
pos = buffer.Pos;
|
||||||
|
// buffer reads unicode chars, if UTF8 has been detected
|
||||||
|
ch = buffer.Read(); col++; charPos++;
|
||||||
|
// replace isolated '\r' by '\n' in order to make
|
||||||
|
// eol handling uniform across Windows, Unix and Mac
|
||||||
|
if (ch == '\r' && buffer.Peek() != '\n') ch = EOL;
|
||||||
|
if (ch == EOL) { line++; col = 0; }
|
||||||
|
}
|
||||||
|
-->casing1
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddCh() {
|
||||||
|
if (tlen >= tval.Length) {
|
||||||
|
char[] newBuf = new char[2 * tval.Length];
|
||||||
|
Array.Copy(tval, 0, newBuf, 0, tval.Length);
|
||||||
|
tval = newBuf;
|
||||||
|
}
|
||||||
|
if (ch != Buffer.EOF) {
|
||||||
|
-->casing2
|
||||||
|
NextCh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
-->comments
|
||||||
|
|
||||||
|
void CheckLiteral() {
|
||||||
|
-->literals
|
||||||
|
}
|
||||||
|
|
||||||
|
Token NextToken() {
|
||||||
|
while (ch == ' ' ||
|
||||||
|
-->scan1
|
||||||
|
) NextCh();
|
||||||
|
-->scan2
|
||||||
|
int recKind = noSym;
|
||||||
|
int recEnd = pos;
|
||||||
|
t = new Token();
|
||||||
|
t.pos = pos; t.col = col; t.line = line; t.charPos = charPos;
|
||||||
|
int state;
|
||||||
|
state = (int) start[ch];
|
||||||
|
tlen = 0; AddCh();
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case -1: { t.kind = eofSym; break; } // NextCh already done
|
||||||
|
case 0: {
|
||||||
|
if (recKind != noSym) {
|
||||||
|
tlen = recEnd - t.pos;
|
||||||
|
SetScannerBehindT();
|
||||||
|
}
|
||||||
|
t.kind = recKind; break;
|
||||||
|
} // NextCh already done
|
||||||
|
-->scan3
|
||||||
|
}
|
||||||
|
t.val = new String(tval, 0, tlen);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetScannerBehindT() {
|
||||||
|
buffer.Pos = t.pos;
|
||||||
|
NextCh();
|
||||||
|
line = t.line; col = t.col; charPos = t.charPos;
|
||||||
|
for (int i = 0; i < tlen; i++) NextCh();
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the next token (possibly a token already seen during peeking)
|
||||||
|
public Token Scan () {
|
||||||
|
if (tokens.next == null) {
|
||||||
|
return NextToken();
|
||||||
|
} else {
|
||||||
|
pt = tokens = tokens.next;
|
||||||
|
return tokens;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// peek for the next token, ignore pragmas
|
||||||
|
public Token Peek () {
|
||||||
|
do {
|
||||||
|
if (pt.next == null) {
|
||||||
|
pt.next = NextToken();
|
||||||
|
}
|
||||||
|
pt = pt.next;
|
||||||
|
} while (pt.kind > maxT); // skip pragmas
|
||||||
|
|
||||||
|
return pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// make sure that peeking starts at the current scan position
|
||||||
|
public void ResetPeek () { pt = tokens; }
|
||||||
|
|
||||||
|
} // end Scanner
|
525
CS-MIC/csmic/csmic/ScriptParser/Scripting.atg
Normal file
525
CS-MIC/csmic/csmic/ScriptParser/Scripting.atg
Normal file
|
@ -0,0 +1,525 @@
|
||||||
|
using csmic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
COMPILER SCRIPT
|
||||||
|
|
||||||
|
/*
|
||||||
|
*
|
||||||
|
* Class Structures
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
private MacroOperation root = new MacroOperation(OperationType.Unknown);
|
||||||
|
|
||||||
|
internal MacroOperation Root
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.root;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.root = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsFunctionCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _LPAREN && la.kind == _identifier)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsCompare()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.kind == _COMPARER)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsAssignment()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if (next.val == "::" || next.val == ":=" || next.val == "->")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsArrayCall()
|
||||||
|
{
|
||||||
|
scanner.ResetPeek();
|
||||||
|
Token next = scanner.Peek();
|
||||||
|
if(next.val == "[")
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHARACTERS
|
||||||
|
|
||||||
|
UpperLetter = 'A'..'Z'.
|
||||||
|
LowerLetter = 'a'..'z'.
|
||||||
|
letter = UpperLetter + LowerLetter.
|
||||||
|
NoQuote = ANY - '\"' .
|
||||||
|
digit = "0123456789" .
|
||||||
|
cr = '\r' .
|
||||||
|
lf = '\n' .
|
||||||
|
tab = '\t' .
|
||||||
|
PM = "+-" .
|
||||||
|
|
||||||
|
TOKENS
|
||||||
|
|
||||||
|
identifier = letter { letter | digit }.
|
||||||
|
sign = PM .
|
||||||
|
binary = ( '0' | '1' ) { '0' | '1' } ('B' | 'b') .
|
||||||
|
hex = "0x" ( digit | ('A' | 'B' | 'C' | 'D' | 'E' |'F') | ('a' | 'b' | 'c' | 'd' | 'e' |'f') ) { digit | ('A' | 'B' | 'C' | 'D' | 'E' |'F') | ('a' | 'b' | 'c' | 'd' | 'e' |'f') } .
|
||||||
|
number = digit { digit }['.' {digit}] [('E'|'e')['+'|'-'] digit {digit}] .
|
||||||
|
newline = [cr] lf .
|
||||||
|
string = "\"" { NoQuote } "\"" .
|
||||||
|
LPAREN = '(' .
|
||||||
|
RPAREN = ')' .
|
||||||
|
COMPARER = "==" | "<" | ">" | "<=" | ">=" .
|
||||||
|
|
||||||
|
COMMENTS FROM "/*" TO "*/" NESTED
|
||||||
|
COMMENTS FROM "//" TO lf
|
||||||
|
|
||||||
|
IGNORE cr + lf + tab
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parser specification
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
PRODUCTIONS
|
||||||
|
|
||||||
|
SCRIPT (. string statement = string.Empty; .)
|
||||||
|
=
|
||||||
|
{
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
this.root.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
IfBlock<ref this.root>
|
||||||
|
|
|
||||||
|
WhileBlock<ref this.root>
|
||||||
|
|
|
||||||
|
FunctionDeclaration<ref this.root>
|
||||||
|
|
|
||||||
|
EchoStatement<ref this.root>
|
||||||
|
|
|
||||||
|
SayStatement<ref this.root>
|
||||||
|
|
|
||||||
|
DisplayStatement<ref this.root>
|
||||||
|
|
|
||||||
|
ForBlock<ref this.root>
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
IfBlock<ref MacroOperation parent> (.
|
||||||
|
MacroOperation ifBlock = new MacroOperation(OperationType.If);
|
||||||
|
MacroOperation elseBlock = new MacroOperation(OperationType.Else);
|
||||||
|
string ifStatement = string.Empty;
|
||||||
|
string statement = string.Empty;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
bool hasElse = false;
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
"if"
|
||||||
|
LPAREN
|
||||||
|
Comparison<ref builder> (. ifStatement = builder.ToString(); ifBlock.Input.Add(ifStatement); .)
|
||||||
|
RPAREN
|
||||||
|
'{'
|
||||||
|
{
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
ifBlock.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
IfBlock<ref ifBlock>
|
||||||
|
|
|
||||||
|
WhileBlock<ref ifBlock>
|
||||||
|
|
|
||||||
|
EchoStatement<ref ifBlock>
|
||||||
|
|
|
||||||
|
SayStatement<ref ifBlock>
|
||||||
|
|
|
||||||
|
DisplayStatement<ref ifBlock>
|
||||||
|
|
|
||||||
|
ForBlock<ref ifBlock>
|
||||||
|
}
|
||||||
|
'}'
|
||||||
|
[
|
||||||
|
"else" (. hasElse = true; .)
|
||||||
|
'{'
|
||||||
|
{
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
elseBlock.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
IfBlock<ref elseBlock>
|
||||||
|
|
|
||||||
|
WhileBlock<ref elseBlock>
|
||||||
|
|
|
||||||
|
EchoStatement<ref elseBlock>
|
||||||
|
|
|
||||||
|
SayStatement<ref elseBlock>
|
||||||
|
|
|
||||||
|
DisplayStatement<ref elseBlock>
|
||||||
|
|
|
||||||
|
ForBlock<ref elseBlock>
|
||||||
|
}
|
||||||
|
'}'
|
||||||
|
]
|
||||||
|
(.
|
||||||
|
if(hasElse)
|
||||||
|
{
|
||||||
|
MacroOperation ifelse = new MacroOperation(OperationType.IfElse);
|
||||||
|
ifelse.Children.Add(ifBlock);
|
||||||
|
ifelse.Children.Add(elseBlock);
|
||||||
|
parent.Children.Add(ifelse);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
parent.Children.Add(ifBlock);
|
||||||
|
}
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WhileBlock<ref MacroOperation parent> (.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation whileBlock = new MacroOperation(OperationType.While);
|
||||||
|
string statement = string.Empty;
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
"while"
|
||||||
|
LPAREN
|
||||||
|
Comparison<ref builder> (. whileBlock.Input.Add(builder.ToString()); .)
|
||||||
|
RPAREN
|
||||||
|
'{'
|
||||||
|
{
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
whileBlock.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
IfBlock<ref whileBlock>
|
||||||
|
|
|
||||||
|
WhileBlock<ref whileBlock>
|
||||||
|
|
|
||||||
|
EchoStatement<ref whileBlock>
|
||||||
|
|
|
||||||
|
SayStatement<ref whileBlock>
|
||||||
|
|
|
||||||
|
DisplayStatement<ref whileBlock>
|
||||||
|
|
|
||||||
|
ForBlock<ref whileBlock>
|
||||||
|
}
|
||||||
|
'}'
|
||||||
|
(.
|
||||||
|
parent.Children.Add(whileBlock);
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
ForBlock<ref MacroOperation parent> (.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
string statement = string.Empty;
|
||||||
|
string statement2 = string.Empty;
|
||||||
|
MacroOperation forBlock = new MacroOperation(OperationType.For);
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
"for"
|
||||||
|
LPAREN
|
||||||
|
Statement<out statement>
|
||||||
|
','
|
||||||
|
Comparison<ref builder>
|
||||||
|
','
|
||||||
|
Statement<out statement2> (. forBlock.Input.Add(statement); forBlock.Input.Add(builder.ToString()); forBlock.Input.Add(statement2); .)
|
||||||
|
RPAREN
|
||||||
|
'{'
|
||||||
|
{
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
forBlock.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
IfBlock<ref forBlock>
|
||||||
|
|
|
||||||
|
WhileBlock<ref forBlock>
|
||||||
|
|
|
||||||
|
EchoStatement<ref forBlock>
|
||||||
|
|
|
||||||
|
SayStatement<ref forBlock>
|
||||||
|
|
|
||||||
|
DisplayStatement<ref forBlock>
|
||||||
|
|
|
||||||
|
ForBlock<ref forBlock>
|
||||||
|
}
|
||||||
|
'}'
|
||||||
|
(.
|
||||||
|
parent.Children.Add(forBlock);
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
FunctionDeclaration<ref MacroOperation parent> (.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
string statement = string.Empty;
|
||||||
|
MacroOperation func = new MacroOperation(OperationType.FunctionDeclaration);
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
"function"
|
||||||
|
LPAREN
|
||||||
|
CommaList<ref builder> (. string[] args = builder.ToString().Split(','); func.Input.AddRange(args); .)
|
||||||
|
RPAREN
|
||||||
|
'{'
|
||||||
|
{
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
func.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
IfBlock<ref func>
|
||||||
|
|
|
||||||
|
WhileBlock<ref func>
|
||||||
|
|
|
||||||
|
EchoStatement<ref func>
|
||||||
|
|
|
||||||
|
SayStatement<ref func>
|
||||||
|
|
|
||||||
|
DisplayStatement<ref func>
|
||||||
|
|
|
||||||
|
ForBlock<ref func>
|
||||||
|
}
|
||||||
|
'}'
|
||||||
|
(.
|
||||||
|
parent.Children.Add(func);
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
EchoStatement<ref MacroOperation parent> (.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation echoStatement = new MacroOperation(OperationType.Echo);
|
||||||
|
string statement = string.Empty;
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
"echo:"
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
echoStatement.Children.Add(operation);
|
||||||
|
parent.Children.Add(echoStatement);
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
SayStatement<ref MacroOperation parent> (.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation sayStatement = new MacroOperation(OperationType.Say);
|
||||||
|
string statement = string.Empty;
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
"say:"
|
||||||
|
string (.
|
||||||
|
statement = t.val.Replace("\"", "");
|
||||||
|
sayStatement.Input.Add(statement);
|
||||||
|
parent.Children.Add(sayStatement);
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
DisplayStatement<ref MacroOperation parent> (.
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
MacroOperation displayStatement = new MacroOperation(OperationType.Display);
|
||||||
|
string statement = string.Empty;
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
"display:"
|
||||||
|
(
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
string (.
|
||||||
|
statement = t.val.Replace("\"", "");
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.String);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
','
|
||||||
|
(
|
||||||
|
Statement<out statement> (.
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.Statement);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
|
|
||||||
|
string (.
|
||||||
|
statement = t.val.Replace("\"", "");
|
||||||
|
MacroOperation operation = new MacroOperation(OperationType.String);
|
||||||
|
operation.Input.Add(statement);
|
||||||
|
displayStatement.Children.Add(operation);
|
||||||
|
.)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
(.
|
||||||
|
parent.Children.Add(displayStatement);
|
||||||
|
.)
|
||||||
|
.
|
||||||
|
|
||||||
|
Statement<out string value> (.
|
||||||
|
value = string.Empty;
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
.)
|
||||||
|
=
|
||||||
|
IF(IsAssignment())
|
||||||
|
Assignment<ref builder> (. value = builder.ToString(); .)
|
||||||
|
|
|
||||||
|
Expression<ref builder> (. value = builder.ToString(); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
Expression<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
Term<ref builder>
|
||||||
|
{
|
||||||
|
'+' (. builder.Append(t.val); .) Term<ref builder>
|
||||||
|
|
|
||||||
|
'-' (. builder.Append(t.val); .) Term<ref builder>
|
||||||
|
|
|
||||||
|
'%' (. builder.Append(t.val); .) Term<ref builder>
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Term<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
Factor<ref builder>
|
||||||
|
{
|
||||||
|
'*' (. builder.Append(t.val); .)
|
||||||
|
Factor<ref builder>
|
||||||
|
|
|
||||||
|
'/' (. builder.Append(t.val); .)
|
||||||
|
Factor<ref builder>
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Factor<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
Value<ref builder>
|
||||||
|
{
|
||||||
|
'^' (. builder.Append(t.val); .)
|
||||||
|
Value<ref builder>
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Value<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
|
||||||
|
[
|
||||||
|
"+" (. builder.Append(t.val); .)
|
||||||
|
|
|
||||||
|
"-" (. builder.Append(t.val); .)
|
||||||
|
]
|
||||||
|
(
|
||||||
|
IF(IsFunctionCall())
|
||||||
|
Function<ref builder>
|
||||||
|
|
|
||||||
|
IF(IsArrayCall())
|
||||||
|
ArrayCall<ref builder>
|
||||||
|
|
|
||||||
|
identifier (. builder.Append(t.val); .)
|
||||||
|
|
|
||||||
|
number (. builder.Append(t.val); .)
|
||||||
|
|
|
||||||
|
hex (. builder.Append(t.val); .)
|
||||||
|
|
|
||||||
|
binary (. builder.Append(t.val); .)
|
||||||
|
|
|
||||||
|
'(' (. builder.Append(t.val); .)
|
||||||
|
Expression<ref builder>
|
||||||
|
')' (. builder.Append(t.val); .)
|
||||||
|
)
|
||||||
|
.
|
||||||
|
|
||||||
|
ArrayL<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
'[' (. builder.Append(t.val); .)
|
||||||
|
CommaList<ref builder>
|
||||||
|
']' (. builder.Append(t.val); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
CommaList<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
Expression<ref builder>
|
||||||
|
{
|
||||||
|
',' (. builder.Append(t.val); .)
|
||||||
|
Expression<ref builder>
|
||||||
|
}
|
||||||
|
.
|
||||||
|
|
||||||
|
Assignment<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
identifier (. builder.Append(t.val); .)
|
||||||
|
(
|
||||||
|
(
|
||||||
|
"::" (. builder.Append(t.val); .)
|
||||||
|
Expression<ref builder>
|
||||||
|
)
|
||||||
|
|
|
||||||
|
(
|
||||||
|
":=" (. builder.Append(t.val); string value = string.Empty; .)
|
||||||
|
AnyExpression<out value> (. builder.Append(value); .)
|
||||||
|
newline
|
||||||
|
)
|
||||||
|
|
|
||||||
|
(
|
||||||
|
"->" (. builder.Append(t.val); .)
|
||||||
|
ArrayL<ref builder>
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.
|
||||||
|
|
||||||
|
Function<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
identifier (. builder.Append(t.val); .)
|
||||||
|
'(' (. builder.Append(t.val); .)
|
||||||
|
CommaList<ref builder>
|
||||||
|
')' (. builder.Append(t.val); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
ArrayCall<ref StringBuilder builder>
|
||||||
|
=
|
||||||
|
identifier (. builder.Append(t.val); .)
|
||||||
|
'[' (. builder.Append(t.val); .)
|
||||||
|
Expression<ref builder>
|
||||||
|
']' (. builder.Append(t.val); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
Comparison<ref StringBuilder result>
|
||||||
|
=
|
||||||
|
Expression<ref result>
|
||||||
|
COMPARER (. result.Append(t.val); .)
|
||||||
|
Expression<ref result>
|
||||||
|
.
|
||||||
|
|
||||||
|
AnyExpression<out string value> (. value = string.Empty; StringBuilder builder = new StringBuilder(); .)
|
||||||
|
=
|
||||||
|
ANY (. builder.Append(t.val); .) { ANY (. builder.Append(t.val); .) } '\n' (. value = builder.ToString(); .)
|
||||||
|
.
|
||||||
|
|
||||||
|
|
||||||
|
END SCRIPT.
|
100
CS-MIC/csmic/csmic/Variable.cs
Normal file
100
CS-MIC/csmic/csmic/Variable.cs
Normal file
|
@ -0,0 +1,100 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace csmic
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Represents the data types supported in a variable.
|
||||||
|
/// </summary>
|
||||||
|
public enum VariableType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Decimal
|
||||||
|
/// </summary>
|
||||||
|
Decimal,
|
||||||
|
/// <summary>
|
||||||
|
/// Equation
|
||||||
|
/// </summary>
|
||||||
|
Equation,
|
||||||
|
/// <summary>
|
||||||
|
/// Array
|
||||||
|
/// </summary>
|
||||||
|
Array,
|
||||||
|
/// <summary>
|
||||||
|
/// Unknown
|
||||||
|
/// </summary>
|
||||||
|
Unknown,
|
||||||
|
/// <summary>
|
||||||
|
/// No type associated
|
||||||
|
/// </summary>
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An object that contains information about a variable.
|
||||||
|
/// </summary>
|
||||||
|
public class Variable
|
||||||
|
{
|
||||||
|
#region Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The type of variable.
|
||||||
|
/// </summary>
|
||||||
|
private VariableType type;
|
||||||
|
/// <summary>
|
||||||
|
/// The value of the variable.
|
||||||
|
/// </summary>
|
||||||
|
private object value;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Constructor
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an empty variable.
|
||||||
|
/// </summary>
|
||||||
|
public Variable()
|
||||||
|
{
|
||||||
|
this.type = VariableType.None;
|
||||||
|
this.value = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets an object representing the variable's value.
|
||||||
|
/// </summary>
|
||||||
|
public object Value
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the type of the variable.
|
||||||
|
/// </summary>
|
||||||
|
public VariableType Type
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
set
|
||||||
|
{
|
||||||
|
this.type = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
}
|
136
CS-MIC/csmic/csmic/csmic.csproj
Normal file
136
CS-MIC/csmic/csmic/csmic.csproj
Normal file
|
@ -0,0 +1,136 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup>
|
||||||
|
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||||
|
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||||
|
<ProductVersion>9.0.21022</ProductVersion>
|
||||||
|
<SchemaVersion>2.0</SchemaVersion>
|
||||||
|
<ProjectGuid>{7BBA4BA2-E885-4D89-8710-F1A609616B7D}</ProjectGuid>
|
||||||
|
<OutputType>Library</OutputType>
|
||||||
|
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||||
|
<RootNamespace>csmic</RootNamespace>
|
||||||
|
<AssemblyName>csmic</AssemblyName>
|
||||||
|
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
|
||||||
|
<FileAlignment>512</FileAlignment>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>csmic_open.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<FileUpgradeFlags>
|
||||||
|
</FileUpgradeFlags>
|
||||||
|
<OldToolsVersion>3.5</OldToolsVersion>
|
||||||
|
<UpgradeBackupLocation />
|
||||||
|
<PublishUrl>publish\</PublishUrl>
|
||||||
|
<Install>true</Install>
|
||||||
|
<InstallFrom>Disk</InstallFrom>
|
||||||
|
<UpdateEnabled>false</UpdateEnabled>
|
||||||
|
<UpdateMode>Foreground</UpdateMode>
|
||||||
|
<UpdateInterval>7</UpdateInterval>
|
||||||
|
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
|
||||||
|
<UpdatePeriodically>false</UpdatePeriodically>
|
||||||
|
<UpdateRequired>false</UpdateRequired>
|
||||||
|
<MapFileExtensions>true</MapFileExtensions>
|
||||||
|
<ApplicationRevision>0</ApplicationRevision>
|
||||||
|
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||||
|
<IsWebBootstrapper>false</IsWebBootstrapper>
|
||||||
|
<UseApplicationTrust>false</UseApplicationTrust>
|
||||||
|
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
|
<SccProjectName>SAK</SccProjectName>
|
||||||
|
<SccLocalPath>SAK</SccLocalPath>
|
||||||
|
<SccAuxPath>SAK</SccAuxPath>
|
||||||
|
<SccProvider>SAK</SccProvider>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
|
<DebugSymbols>true</DebugSymbols>
|
||||||
|
<DebugType>full</DebugType>
|
||||||
|
<Optimize>false</Optimize>
|
||||||
|
<OutputPath>bin\Debug\</OutputPath>
|
||||||
|
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<DocumentationFile>bin\Debug\csmic.XML</DocumentationFile>
|
||||||
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||||
|
<DebugType>pdbonly</DebugType>
|
||||||
|
<Optimize>true</Optimize>
|
||||||
|
<OutputPath>bin\Release\</OutputPath>
|
||||||
|
<DefineConstants>
|
||||||
|
</DefineConstants>
|
||||||
|
<ErrorReport>prompt</ErrorReport>
|
||||||
|
<WarningLevel>4</WarningLevel>
|
||||||
|
<DocumentationFile>bin\Release\csmic.XML</DocumentationFile>
|
||||||
|
<CodeAnalysisRuleSet>AllRules.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<RunCodeAnalysis>false</RunCodeAnalysis>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Reference Include="System" />
|
||||||
|
<Reference Include="System.Core">
|
||||||
|
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||||
|
</Reference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="CodedFunctionFactory.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Abs.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Exp.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Log.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Precision.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Sqrt.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Cos.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Round.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Sin.cs" />
|
||||||
|
<Compile Include="CodedFunctions\CF_Tan.cs" />
|
||||||
|
<Compile Include="Computable\Computable.cs" />
|
||||||
|
<Compile Include="Extensions\CSMICExtension.cs" />
|
||||||
|
<Compile Include="GenericCodedFunction.cs" />
|
||||||
|
<Compile Include="ICodedFunction.cs" />
|
||||||
|
<Compile Include="InputInterpreter.cs" />
|
||||||
|
<Compile Include="InterpretedFunction.cs" />
|
||||||
|
<Compile Include="InterpretedFunctionArgument.cs" />
|
||||||
|
<Compile Include="MacroBuilder.cs" />
|
||||||
|
<Compile Include="MacroOperation.cs" />
|
||||||
|
<Compile Include="InterpreterParser\Parser.cs" />
|
||||||
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="InterpreterParser\Scanner.cs" />
|
||||||
|
<Compile Include="ScriptParser\Parser.cs" />
|
||||||
|
<Compile Include="ScriptParser\Scanner.cs" />
|
||||||
|
<Compile Include="Variable.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="csmic_open.snk" />
|
||||||
|
<None Include="InterpreterParser\Parser.frame" />
|
||||||
|
<None Include="InterpreterParser\Scanner.frame" />
|
||||||
|
<None Include="ScriptParser\Parser.frame" />
|
||||||
|
<None Include="ScriptParser\Scanner.frame" />
|
||||||
|
<None Include="ScriptParser\Scripting.atg" />
|
||||||
|
<None Include="InterpreterParser\CSMIC.atg" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1 Client Profile</ProductName>
|
||||||
|
<Install>false</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>.NET Framework 3.5 SP1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
<BootstrapperPackage Include="Microsoft.Windows.Installer.3.1">
|
||||||
|
<Visible>False</Visible>
|
||||||
|
<ProductName>Windows Installer 3.1</ProductName>
|
||||||
|
<Install>true</Install>
|
||||||
|
</BootstrapperPackage>
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.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">
|
||||||
|
</Target>
|
||||||
|
<Target Name="AfterBuild">
|
||||||
|
</Target>
|
||||||
|
-->
|
||||||
|
<PropertyGroup>
|
||||||
|
<PreBuildEvent>"$(ProjectDir)\coco.exe" -namespace csmic.Interpreter -frames . "$(ProjectDir)\InterpreterParser\CSMIC.atg"
|
||||||
|
"$(ProjectDir)\coco.exe" -namespace csmic.Scripting -frames . "$(ProjectDir)\ScriptParser\Scripting.atg"</PreBuildEvent>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
10
CS-MIC/csmic/csmic/csmic.csproj.vspscc
Normal file
10
CS-MIC/csmic/csmic/csmic.csproj.vspscc
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
""
|
||||||
|
{
|
||||||
|
"FILE_VERSION" = "9237"
|
||||||
|
"ENLISTMENT_CHOICE" = "NEVER"
|
||||||
|
"PROJECT_FILE_RELATIVE_PATH" = ""
|
||||||
|
"NUMBER_OF_EXCLUDED_FILES" = "0"
|
||||||
|
"ORIGINAL_PROJECT_FILE_PATH" = ""
|
||||||
|
"NUMBER_OF_NESTED_PROJECTS" = "0"
|
||||||
|
"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER"
|
||||||
|
}
|
BIN
CS-MIC/csmic/csmic/csmic_open.snk
Normal file
BIN
CS-MIC/csmic/csmic/csmic_open.snk
Normal file
Binary file not shown.
Loading…
Reference in a new issue