aboutsummaryrefslogtreecommitdiff
path: root/runtime/CSharp3/Sources/Antlr3.Runtime.Debug
diff options
context:
space:
mode:
Diffstat (limited to 'runtime/CSharp3/Sources/Antlr3.Runtime.Debug')
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj84
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj.vspscc10
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/BlankDebugEventListener.cs165
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventHub.cs366
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventListenerConstants.cs46
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventRepeater.cs196
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventSocketProxy.cs445
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugParser.cs129
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTokenStream.cs212
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeAdaptor.cs329
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeNodeStream.cs216
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeParser.cs137
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/JavaExtensions/ExceptionExtensions.cs51
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/DoubleKeyMap`3.cs86
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/Stats.cs131
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParseTreeBuilder.cs139
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParserDebugger.cs49
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Profiler.cs797
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Properties/AssemblyInfo.cs70
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs744
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/TraceDebugEventListener.cs135
-rw-r--r--runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Tracer.cs85
22 files changed, 4622 insertions, 0 deletions
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj
new file mode 100644
index 0000000..5ca19d8
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj
@@ -0,0 +1,84 @@
+<?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.30729</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{5EE27A90-B023-42C9-AAF1-52B0424C5D0B}</ProjectGuid>
+ <OutputType>Library</OutputType>
+ <AppDesignerFolder>Properties</AppDesignerFolder>
+ <RootNamespace>Antlr.Runtime.Debug</RootNamespace>
+ <AssemblyName>Antlr3.Runtime.Debug</AssemblyName>
+ <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
+ <FileAlignment>512</FileAlignment>
+ <SccProjectName>Perforce Project</SccProjectName>
+ <SccLocalPath>..\..\..\..\..\..</SccLocalPath>
+ <SccAuxPath>
+ </SccAuxPath>
+ <SccProvider>MSSCCI:Perforce SCM</SccProvider>
+ <SignAssembly>true</SignAssembly>
+ <AssemblyOriginatorKeyFile>..\..\..\..\..\..\..\keys\antlr\Key.snk</AssemblyOriginatorKeyFile>
+ <TargetFrameworkProfile>
+ </TargetFrameworkProfile>
+ </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>
+ </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>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System" />
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="BlankDebugEventListener.cs" />
+ <Compile Include="DebugEventHub.cs" />
+ <Compile Include="DebugEventListenerConstants.cs" />
+ <Compile Include="DebugEventRepeater.cs" />
+ <Compile Include="DebugEventSocketProxy.cs" />
+ <Compile Include="DebugParser.cs" />
+ <Compile Include="DebugTokenStream.cs" />
+ <Compile Include="DebugTreeAdaptor.cs" />
+ <Compile Include="DebugTreeNodeStream.cs" />
+ <Compile Include="DebugTreeParser.cs" />
+ <Compile Include="JavaExtensions\ExceptionExtensions.cs" />
+ <Compile Include="Misc\DoubleKeyMap`3.cs" />
+ <Compile Include="Misc\Stats.cs" />
+ <None Include="..\..\..\..\..\..\..\keys\antlr\Key.snk">
+ <Link>Key.snk</Link>
+ </None>
+ <None Include="ParserDebugger.cs" />
+ <Compile Include="ParseTreeBuilder.cs" />
+ <Compile Include="Profiler.cs" />
+ <Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="RemoteDebugEventSocketListener.cs" />
+ <Compile Include="TraceDebugEventListener.cs" />
+ <Compile Include="Tracer.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\Antlr3.Runtime\Antlr3.Runtime.csproj">
+ <Project>{8FDC0A87-9005-4D5A-AB75-E55CEB575559}</Project>
+ <Name>Antlr3.Runtime</Name>
+ </ProjectReference>
+ </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>
+ -->
+</Project> \ No newline at end of file
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj.vspscc b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj.vspscc
new file mode 100644
index 0000000..b6d3289
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Antlr3.Runtime.Debug.csproj.vspscc
@@ -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"
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/BlankDebugEventListener.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/BlankDebugEventListener.cs
new file mode 100644
index 0000000..61d54ff
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/BlankDebugEventListener.cs
@@ -0,0 +1,165 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ /** <summary>
+ * A blank listener that does nothing; useful for real classes so
+ * they don't have to have lots of blank methods and are less
+ * sensitive to updates to debug interface.
+ * </summary>
+ */
+ public class BlankDebugEventListener : IDebugEventListener
+ {
+ public int RuleLevel
+ {
+ get;
+ protected set;
+ }
+
+ public virtual void Initialize()
+ {
+ }
+
+ public virtual void EnterRule( string grammarFileName, string ruleName )
+ {
+ if ( RuleLevel == 0 )
+ Commence();
+ RuleLevel++;
+ }
+ public virtual void ExitRule( string grammarFileName, string ruleName )
+ {
+ RuleLevel--;
+ if ( RuleLevel == 0 )
+ Terminate();
+ }
+ public virtual void EnterAlt( int alt )
+ {
+ }
+ public virtual void EnterSubRule( int decisionNumber )
+ {
+ }
+ public virtual void ExitSubRule( int decisionNumber )
+ {
+ }
+ public virtual void EnterDecision(int decisionNumber, bool couldBacktrack)
+ {
+ }
+ public virtual void ExitDecision( int decisionNumber )
+ {
+ }
+ public virtual void Location( int line, int pos )
+ {
+ }
+ public virtual void ConsumeToken( IToken token )
+ {
+ }
+ public virtual void ConsumeHiddenToken( IToken token )
+ {
+ }
+ public virtual void LT( int i, IToken t )
+ {
+ }
+ public virtual void Mark( int i )
+ {
+ }
+ public virtual void Rewind( int i )
+ {
+ }
+ public virtual void Rewind()
+ {
+ }
+ public virtual void BeginBacktrack( int level )
+ {
+ }
+ public virtual void EndBacktrack( int level, bool successful )
+ {
+ }
+ public virtual void RecognitionException( RecognitionException e )
+ {
+ }
+ public virtual void BeginResync()
+ {
+ }
+ public virtual void EndResync()
+ {
+ }
+ public virtual void SemanticPredicate( bool result, string predicate )
+ {
+ }
+ public virtual void Commence()
+ {
+ }
+ public virtual void Terminate()
+ {
+ }
+
+ #region Tree parsing stuff
+
+ public virtual void ConsumeNode( object t )
+ {
+ }
+ public virtual void LT( int i, object t )
+ {
+ }
+
+ #endregion
+
+
+ #region AST Stuff
+
+ public virtual void NilNode( object t )
+ {
+ }
+ public virtual void ErrorNode( object t )
+ {
+ }
+ public virtual void CreateNode( object t )
+ {
+ }
+ public virtual void CreateNode( object node, IToken token )
+ {
+ }
+ public virtual void BecomeRoot( object newRoot, object oldRoot )
+ {
+ }
+ public virtual void AddChild( object root, object child )
+ {
+ }
+ public virtual void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex )
+ {
+ }
+
+ #endregion
+ }
+}
+
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventHub.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventHub.cs
new file mode 100644
index 0000000..bea6799
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventHub.cs
@@ -0,0 +1,366 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using System.Collections.Generic;
+
+ /** <summary>
+ * Broadcast debug events to multiple listeners. Lets you debug and still
+ * use the event mechanism to build parse trees etc... Not thread-safe.
+ * Don't add events in one thread while parser fires events in another.
+ * </summary>
+ *
+ * <seealso cref="DebugEventRepeater"/>
+ */
+ public class DebugEventHub : IDebugEventListener
+ {
+ List<IDebugEventListener> _listeners = new List<IDebugEventListener>();
+
+ public DebugEventHub( params IDebugEventListener[] listeners )
+ {
+ _listeners = new List<IDebugEventListener>( listeners );
+ }
+
+ public virtual void Initialize()
+ {
+ }
+
+ /** <summary>
+ * Add another listener to broadcast events too. Not thread-safe.
+ * Don't add events in one thread while parser fires events in another.
+ * </summary>
+ */
+ public virtual void AddListener( IDebugEventListener listener )
+ {
+ _listeners.Add( listener );
+ }
+
+ /* To avoid a mess like this:
+ public void enterRule(final String ruleName) {
+ broadcast(new Code(){
+ public void exec(DebugEventListener listener) {listener.enterRule(ruleName);}}
+ );
+ }
+ I am dup'ing the for-loop in each. Where are Java closures!? blech!
+ */
+
+ public virtual void EnterRule( string grammarFileName, string ruleName )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.EnterRule( grammarFileName, ruleName );
+ }
+ }
+
+ public virtual void ExitRule( string grammarFileName, string ruleName )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.ExitRule( grammarFileName, ruleName );
+ }
+ }
+
+ public virtual void EnterAlt( int alt )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.EnterAlt( alt );
+ }
+ }
+
+ public virtual void EnterSubRule( int decisionNumber )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.EnterSubRule( decisionNumber );
+ }
+ }
+
+ public virtual void ExitSubRule( int decisionNumber )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.ExitSubRule( decisionNumber );
+ }
+ }
+
+ public virtual void EnterDecision(int decisionNumber, bool couldBacktrack)
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.EnterDecision( decisionNumber, couldBacktrack );
+ }
+ }
+
+ public virtual void ExitDecision( int decisionNumber )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.ExitDecision( decisionNumber );
+ }
+ }
+
+ public virtual void Location( int line, int pos )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.Location( line, pos );
+ }
+ }
+
+ public virtual void ConsumeToken( IToken token )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.ConsumeToken( token );
+ }
+ }
+
+ public virtual void ConsumeHiddenToken( IToken token )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.ConsumeHiddenToken( token );
+ }
+ }
+
+ public virtual void LT( int index, IToken t )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.LT( index, t );
+ }
+ }
+
+ public virtual void Mark( int index )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.Mark( index );
+ }
+ }
+
+ public virtual void Rewind( int index )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.Rewind( index );
+ }
+ }
+
+ public virtual void Rewind()
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.Rewind();
+ }
+ }
+
+ public virtual void BeginBacktrack( int level )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.BeginBacktrack( level );
+ }
+ }
+
+ public virtual void EndBacktrack( int level, bool successful )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.EndBacktrack( level, successful );
+ }
+ }
+
+ public virtual void RecognitionException( RecognitionException e )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.RecognitionException( e );
+ }
+ }
+
+ public virtual void BeginResync()
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.BeginResync();
+ }
+ }
+
+ public virtual void EndResync()
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.EndResync();
+ }
+ }
+
+ public virtual void SemanticPredicate( bool result, string predicate )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.SemanticPredicate( result, predicate );
+ }
+ }
+
+ public virtual void Commence()
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.Commence();
+ }
+ }
+
+ public virtual void Terminate()
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.Terminate();
+ }
+ }
+
+
+ #region Tree parsing stuff
+
+ public virtual void ConsumeNode( object t )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.ConsumeNode( t );
+ }
+ }
+
+ public virtual void LT( int index, object t )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.LT( index, t );
+ }
+ }
+
+ #endregion
+
+
+ #region AST Stuff
+
+ public virtual void NilNode( object t )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.NilNode( t );
+ }
+ }
+
+ public virtual void ErrorNode( object t )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.ErrorNode( t );
+ }
+ }
+
+ public virtual void CreateNode( object t )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.CreateNode( t );
+ }
+ }
+
+ public virtual void CreateNode( object node, IToken token )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.CreateNode( node, token );
+ }
+ }
+
+ public virtual void BecomeRoot( object newRoot, object oldRoot )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.BecomeRoot( newRoot, oldRoot );
+ }
+ }
+
+ public virtual void AddChild( object root, object child )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.AddChild( root, child );
+ }
+ }
+
+ public virtual void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex )
+ {
+ for ( int i = 0; i < _listeners.Count; i++ )
+ {
+ IDebugEventListener listener = _listeners[i];
+ listener.SetTokenBoundaries( t, tokenStartIndex, tokenStopIndex );
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventListenerConstants.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventListenerConstants.cs
new file mode 100644
index 0000000..9032492
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventListenerConstants.cs
@@ -0,0 +1,46 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+
+ public static class DebugEventListenerConstants
+ {
+ /** <summary>Moved to version 2 for v3.1: added grammar name to enter/exit Rule</summary> */
+ public const string ProtocolVersion = "2";
+
+ /** <summary>Serialized version of true</summary> */
+ public const int True = 1;
+ public const int False = 0;
+ }
+
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventRepeater.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventRepeater.cs
new file mode 100644
index 0000000..181b649
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventRepeater.cs
@@ -0,0 +1,196 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+
+ /** <summary>
+ * A simple event repeater (proxy) that delegates all functionality to the
+ * listener sent into the ctor. Useful if you want to listen in on a few
+ * debug events w/o interrupting the debugger. Just subclass the repeater
+ * and override the methods you want to listen in on. Remember to call
+ * the method in this class so the event will continue on to the original
+ * recipient.
+ * </summary>
+ *
+ * <seealso cref="DebugEventHub"/>
+ */
+ public class DebugEventRepeater : IDebugEventListener
+ {
+ IDebugEventListener _listener;
+
+ public DebugEventRepeater( IDebugEventListener listener )
+ {
+ _listener = listener;
+ }
+
+ public virtual void Initialize()
+ {
+ }
+
+ public virtual void EnterRule( string grammarFileName, string ruleName )
+ {
+ _listener.EnterRule( grammarFileName, ruleName );
+ }
+ public virtual void ExitRule( string grammarFileName, string ruleName )
+ {
+ _listener.ExitRule( grammarFileName, ruleName );
+ }
+ public virtual void EnterAlt( int alt )
+ {
+ _listener.EnterAlt( alt );
+ }
+ public virtual void EnterSubRule( int decisionNumber )
+ {
+ _listener.EnterSubRule( decisionNumber );
+ }
+ public virtual void ExitSubRule( int decisionNumber )
+ {
+ _listener.ExitSubRule( decisionNumber );
+ }
+ public virtual void EnterDecision(int decisionNumber, bool couldBacktrack)
+ {
+ _listener.EnterDecision( decisionNumber, couldBacktrack );
+ }
+ public virtual void ExitDecision( int decisionNumber )
+ {
+ _listener.ExitDecision( decisionNumber );
+ }
+ public virtual void Location( int line, int pos )
+ {
+ _listener.Location( line, pos );
+ }
+ public virtual void ConsumeToken( IToken token )
+ {
+ _listener.ConsumeToken( token );
+ }
+ public virtual void ConsumeHiddenToken( IToken token )
+ {
+ _listener.ConsumeHiddenToken( token );
+ }
+ public virtual void LT( int i, IToken t )
+ {
+ _listener.LT( i, t );
+ }
+ public virtual void Mark( int i )
+ {
+ _listener.Mark( i );
+ }
+ public virtual void Rewind( int i )
+ {
+ _listener.Rewind( i );
+ }
+ public virtual void Rewind()
+ {
+ _listener.Rewind();
+ }
+ public virtual void BeginBacktrack( int level )
+ {
+ _listener.BeginBacktrack( level );
+ }
+ public virtual void EndBacktrack( int level, bool successful )
+ {
+ _listener.EndBacktrack( level, successful );
+ }
+ public virtual void RecognitionException( RecognitionException e )
+ {
+ _listener.RecognitionException( e );
+ }
+ public virtual void BeginResync()
+ {
+ _listener.BeginResync();
+ }
+ public virtual void EndResync()
+ {
+ _listener.EndResync();
+ }
+ public virtual void SemanticPredicate( bool result, string predicate )
+ {
+ _listener.SemanticPredicate( result, predicate );
+ }
+ public virtual void Commence()
+ {
+ _listener.Commence();
+ }
+ public virtual void Terminate()
+ {
+ _listener.Terminate();
+ }
+
+ #region Tree parsing stuff
+
+ public virtual void ConsumeNode( object t )
+ {
+ _listener.ConsumeNode( t );
+ }
+ public virtual void LT( int i, object t )
+ {
+ _listener.LT( i, t );
+ }
+
+ #endregion
+
+
+ #region AST Stuff
+
+ public virtual void NilNode( object t )
+ {
+ _listener.NilNode( t );
+ }
+ public virtual void ErrorNode( object t )
+ {
+ _listener.ErrorNode( t );
+ }
+ public virtual void CreateNode( object t )
+ {
+ _listener.CreateNode( t );
+ }
+ public virtual void CreateNode( object node, IToken token )
+ {
+ _listener.CreateNode( node, token );
+ }
+ public virtual void BecomeRoot( object newRoot, object oldRoot )
+ {
+ _listener.BecomeRoot( newRoot, oldRoot );
+ }
+ public virtual void AddChild( object root, object child )
+ {
+ _listener.AddChild( root, child );
+ }
+ public virtual void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex )
+ {
+ _listener.SetTokenBoundaries( t, tokenStartIndex, tokenStopIndex );
+ }
+
+ #endregion
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventSocketProxy.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventSocketProxy.cs
new file mode 100644
index 0000000..64b0fd2
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugEventSocketProxy.cs
@@ -0,0 +1,445 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using System;
+ using Antlr.Runtime.JavaExtensions;
+
+ using IOException = System.IO.IOException;
+ using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor;
+ using Socket = System.Net.Sockets.Socket;
+ using StringBuilder = System.Text.StringBuilder;
+ using TcpListener = System.Net.Sockets.TcpListener;
+
+ /** <summary>
+ * A proxy debug event listener that forwards events over a socket to
+ * a debugger (or any other listener) using a simple text-based protocol;
+ * one event per line. ANTLRWorks listens on server socket with a
+ * RemoteDebugEventSocketListener instance. These two objects must therefore
+ * be kept in sync. New events must be handled on both sides of socket.
+ * </summary>
+ */
+ public class DebugEventSocketProxy : BlankDebugEventListener
+ {
+ public const int DefaultDebuggerPort = 49100;
+ protected int port = DefaultDebuggerPort;
+ protected TcpListener serverSocket;
+ protected Socket socket;
+ protected string grammarFileName;
+ //protected PrintWriter @out;
+ //protected BufferedReader @in;
+
+ /** <summary>Who am i debugging?</summary> */
+ protected BaseRecognizer recognizer;
+
+ /** <summary>
+ * Almost certainly the recognizer will have adaptor set, but
+ * we don't know how to cast it (Parser or TreeParser) to get
+ * the adaptor field. Must be set with a constructor. :(
+ * </summary>
+ */
+ protected ITreeAdaptor adaptor;
+
+ public DebugEventSocketProxy( BaseRecognizer recognizer, ITreeAdaptor adaptor ) :
+ this( recognizer, DefaultDebuggerPort, adaptor )
+ {
+ }
+
+ public DebugEventSocketProxy( BaseRecognizer recognizer, int port, ITreeAdaptor adaptor )
+ {
+ this.grammarFileName = recognizer.GrammarFileName;
+ this.adaptor = adaptor;
+ this.port = port;
+ }
+
+ #region Properties
+ public virtual ITreeAdaptor TreeAdaptor
+ {
+ get
+ {
+ return adaptor;
+ }
+ set
+ {
+ adaptor = value;
+ }
+ }
+ #endregion
+
+ public virtual void Handshake()
+ {
+ if ( serverSocket == null )
+ {
+ System.Net.IPHostEntry hostInfo = System.Net.Dns.GetHostEntry( "localhost" );
+ System.Net.IPAddress ipAddress = hostInfo.AddressList[0];
+ serverSocket = new TcpListener( ipAddress, port );
+ socket = serverSocket.AcceptSocket();
+ socket.NoDelay = true;
+
+ System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
+ socket.Send( encoding.GetBytes( "ANTLR " + DebugEventListenerConstants.ProtocolVersion + "\n" ) );
+ socket.Send( encoding.GetBytes( "grammar \"" + grammarFileName + "\n" ) );
+ Ack();
+
+ //serverSocket = new ServerSocket( port );
+ //socket = serverSocket.accept();
+ //socket.setTcpNoDelay( true );
+ //OutputStream os = socket.getOutputStream();
+ //OutputStreamWriter osw = new OutputStreamWriter( os, "UTF8" );
+ //@out = new PrintWriter( new BufferedWriter( osw ) );
+ //InputStream @is = socket.getInputStream();
+ //InputStreamReader isr = new InputStreamReader( @is, "UTF8" );
+ //@in = new BufferedReader( isr );
+ //@out.println( "ANTLR " + DebugEventListenerConstants.PROTOCOL_VERSION );
+ //@out.println( "grammar \"" + grammarFileName );
+ //@out.flush();
+ //ack();
+ }
+ }
+
+ public override void Commence()
+ {
+ // don't bother sending event; listener will trigger upon connection
+ }
+
+ public override void Terminate()
+ {
+ Transmit( "terminate" );
+ //@out.close();
+ try
+ {
+ socket.Close();
+ }
+ catch ( IOException ioe )
+ {
+ ExceptionExtensions.PrintStackTrace( ioe, Console.Error );
+ }
+ }
+
+ protected virtual void Ack()
+ {
+ try
+ {
+ throw new NotImplementedException();
+ //@in.readLine();
+ }
+ catch ( IOException ioe )
+ {
+ ExceptionExtensions.PrintStackTrace( ioe, Console.Error );
+ }
+ }
+
+ protected virtual void Transmit( string @event )
+ {
+ socket.Send( new System.Text.UTF8Encoding().GetBytes( @event + "\n" ) );
+ //@out.println( @event );
+ //@out.flush();
+ Ack();
+ }
+
+ public override void EnterRule( string grammarFileName, string ruleName )
+ {
+ Transmit( "enterRule\t" + grammarFileName + "\t" + ruleName );
+ }
+
+ public override void EnterAlt( int alt )
+ {
+ Transmit( "enterAlt\t" + alt );
+ }
+
+ public override void ExitRule( string grammarFileName, string ruleName )
+ {
+ Transmit( "exitRule\t" + grammarFileName + "\t" + ruleName );
+ }
+
+ public override void EnterSubRule( int decisionNumber )
+ {
+ Transmit( "enterSubRule\t" + decisionNumber );
+ }
+
+ public override void ExitSubRule( int decisionNumber )
+ {
+ Transmit( "exitSubRule\t" + decisionNumber );
+ }
+
+ public override void EnterDecision(int decisionNumber, bool couldBacktrack)
+ {
+ Transmit( "enterDecision\t" + decisionNumber );
+ }
+
+ public override void ExitDecision( int decisionNumber )
+ {
+ Transmit( "exitDecision\t" + decisionNumber );
+ }
+
+ public override void ConsumeToken( IToken t )
+ {
+ string buf = SerializeToken( t );
+ Transmit( "consumeToken\t" + buf );
+ }
+
+ public override void ConsumeHiddenToken( IToken t )
+ {
+ string buf = SerializeToken( t );
+ Transmit( "consumeHiddenToken\t" + buf );
+ }
+
+ public override void LT( int i, IToken t )
+ {
+ if ( t != null )
+ Transmit( "LT\t" + i + "\t" + SerializeToken( t ) );
+ }
+
+ public override void Mark( int i )
+ {
+ Transmit( "mark\t" + i );
+ }
+
+ public override void Rewind( int i )
+ {
+ Transmit( "rewind\t" + i );
+ }
+
+ public override void Rewind()
+ {
+ Transmit( "rewind" );
+ }
+
+ public override void BeginBacktrack( int level )
+ {
+ Transmit( "beginBacktrack\t" + level );
+ }
+
+ public override void EndBacktrack( int level, bool successful )
+ {
+ Transmit( "endBacktrack\t" + level + "\t" + ( successful ? DebugEventListenerConstants.True : DebugEventListenerConstants.False ) );
+ }
+
+ public override void Location( int line, int pos )
+ {
+ Transmit( "location\t" + line + "\t" + pos );
+ }
+
+ public override void RecognitionException( RecognitionException e )
+ {
+ StringBuilder buf = new StringBuilder( 50 );
+ buf.Append( "exception\t" );
+ buf.Append( e.GetType().Name );
+ // dump only the data common to all exceptions for now
+ buf.Append( "\t" );
+ buf.Append( e.Index );
+ buf.Append( "\t" );
+ buf.Append( e.Line );
+ buf.Append( "\t" );
+ buf.Append( e.CharPositionInLine );
+ Transmit( buf.ToString() );
+ }
+
+ public override void BeginResync()
+ {
+ Transmit( "beginResync" );
+ }
+
+ public override void EndResync()
+ {
+ Transmit( "endResync" );
+ }
+
+ public override void SemanticPredicate( bool result, string predicate )
+ {
+ StringBuilder buf = new StringBuilder( 50 );
+ buf.Append( "semanticPredicate\t" );
+ buf.Append( result );
+ SerializeText( buf, predicate );
+ Transmit( buf.ToString() );
+ }
+
+ #region AST Parsing Events
+
+ public override void ConsumeNode( object t )
+ {
+ StringBuilder buf = new StringBuilder( 50 );
+ buf.Append( "consumeNode" );
+ SerializeNode( buf, t );
+ Transmit( buf.ToString() );
+ }
+
+ public override void LT( int i, object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ string text = adaptor.GetText( t );
+ int type = adaptor.GetType( t );
+ StringBuilder buf = new StringBuilder( 50 );
+ buf.Append( "LN\t" ); // lookahead node; distinguish from LT in protocol
+ buf.Append( i );
+ SerializeNode( buf, t );
+ Transmit( buf.ToString() );
+ }
+
+ protected virtual void SerializeNode( StringBuilder buf, object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ string text = adaptor.GetText( t );
+ int type = adaptor.GetType( t );
+ buf.Append( "\t" );
+ buf.Append( ID );
+ buf.Append( "\t" );
+ buf.Append( type );
+ IToken token = adaptor.GetToken( t );
+ int line = -1;
+ int pos = -1;
+ if ( token != null )
+ {
+ line = token.Line;
+ pos = token.CharPositionInLine;
+ }
+ buf.Append( "\t" );
+ buf.Append( line );
+ buf.Append( "\t" );
+ buf.Append( pos );
+ int tokenIndex = adaptor.GetTokenStartIndex( t );
+ buf.Append( "\t" );
+ buf.Append( tokenIndex );
+ SerializeText( buf, text );
+ }
+
+ #endregion
+
+
+ #region AST Events
+
+ public override void NilNode( object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ Transmit( "nilNode\t" + ID );
+ }
+
+ public override void ErrorNode( object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ string text = t.ToString();
+ StringBuilder buf = new StringBuilder( 50 );
+ buf.Append( "errorNode\t" );
+ buf.Append( ID );
+ buf.Append( "\t" );
+ buf.Append( TokenTypes.Invalid );
+ SerializeText( buf, text );
+ Transmit( buf.ToString() );
+ }
+
+ public override void CreateNode( object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ string text = adaptor.GetText( t );
+ int type = adaptor.GetType( t );
+ StringBuilder buf = new StringBuilder( 50 );
+ buf.Append( "createNodeFromTokenElements\t" );
+ buf.Append( ID );
+ buf.Append( "\t" );
+ buf.Append( type );
+ SerializeText( buf, text );
+ Transmit( buf.ToString() );
+ }
+
+ public override void CreateNode( object node, IToken token )
+ {
+ int ID = adaptor.GetUniqueID( node );
+ int tokenIndex = token.TokenIndex;
+ Transmit( "createNode\t" + ID + "\t" + tokenIndex );
+ }
+
+ public override void BecomeRoot( object newRoot, object oldRoot )
+ {
+ int newRootID = adaptor.GetUniqueID( newRoot );
+ int oldRootID = adaptor.GetUniqueID( oldRoot );
+ Transmit( "becomeRoot\t" + newRootID + "\t" + oldRootID );
+ }
+
+ public override void AddChild( object root, object child )
+ {
+ int rootID = adaptor.GetUniqueID( root );
+ int childID = adaptor.GetUniqueID( child );
+ Transmit( "addChild\t" + rootID + "\t" + childID );
+ }
+
+ public override void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ Transmit( "setTokenBoundaries\t" + ID + "\t" + tokenStartIndex + "\t" + tokenStopIndex );
+ }
+
+ #endregion
+
+
+ #region Support
+
+ protected virtual string SerializeToken( IToken t )
+ {
+ StringBuilder buf = new StringBuilder( 50 );
+ buf.Append( t.TokenIndex );
+ buf.Append( '\t' );
+ buf.Append( t.Type );
+ buf.Append( '\t' );
+ buf.Append( t.Channel );
+ buf.Append( '\t' );
+ buf.Append( t.Line );
+ buf.Append( '\t' );
+ buf.Append( t.CharPositionInLine );
+ SerializeText( buf, t.Text );
+ return buf.ToString();
+ }
+
+ protected virtual void SerializeText( StringBuilder buf, string text )
+ {
+ buf.Append( "\t\"" );
+ if ( text == null )
+ {
+ text = "";
+ }
+ // escape \n and \r all text for token appears to exist on one line
+ // this escape is slow but easy to understand
+ text = EscapeNewlines( text );
+ buf.Append( text );
+ }
+
+ protected virtual string EscapeNewlines( string txt )
+ {
+ txt = txt.Replace( "%", "%25" ); // escape all escape char ;)
+ txt = txt.Replace( "\n", "%0A" ); // escape \n
+ txt = txt.Replace( "\r", "%0D" ); // escape \r
+ return txt;
+ }
+
+ #endregion
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugParser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugParser.cs
new file mode 100644
index 0000000..18d8db8
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugParser.cs
@@ -0,0 +1,129 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using Antlr.Runtime.JavaExtensions;
+
+ using Console = System.Console;
+ using IOException = System.IO.IOException;
+
+ public class DebugParser : Parser
+ {
+ /** <summary>Who to notify when events in the parser occur.</summary> */
+ public IDebugEventListener dbg = null;
+
+ /** <summary>
+ * Used to differentiate between fixed lookahead and cyclic DFA decisions
+ * while profiling.
+ * </summary>
+ */
+ public bool isCyclicDecision = false;
+
+ /** <summary>
+ * Create a normal parser except wrap the token stream in a debug
+ * proxy that fires consume events.
+ * </summary>
+ */
+ public DebugParser( ITokenStream input, IDebugEventListener dbg, RecognizerSharedState state )
+ : base( input is DebugTokenStream ? input : new DebugTokenStream( input, dbg ), state )
+ {
+ SetDebugListener(dbg);
+ }
+
+ public DebugParser( ITokenStream input, RecognizerSharedState state )
+ : base( input is DebugTokenStream ? input : new DebugTokenStream( input, null ), state )
+ {
+ }
+
+ public DebugParser( ITokenStream input, IDebugEventListener dbg )
+ : this( input is DebugTokenStream ? input : new DebugTokenStream( input, dbg ), dbg, null )
+ {
+ }
+
+ public override IDebugEventListener DebugListener
+ {
+ get
+ {
+ return dbg;
+ }
+ }
+
+ /** <summary>
+ * Provide a new debug event listener for this parser. Notify the
+ * input stream too that it should send events to this listener.
+ * </summary>
+ */
+ public virtual void SetDebugListener(IDebugEventListener value)
+ {
+ DebugTokenStream debugTokenStream = input as DebugTokenStream;
+ if (debugTokenStream != null)
+ debugTokenStream.DebugListener = value;
+
+ dbg = value;
+ }
+
+ public virtual void ReportError( IOException e )
+ {
+ Console.Error.WriteLine( e );
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+
+ public override void BeginResync()
+ {
+ dbg.BeginResync();
+ base.BeginResync();
+ }
+
+ public override void EndResync()
+ {
+ dbg.EndResync();
+ base.EndResync();
+ }
+
+ public virtual void BeginBacktrack( int level )
+ {
+ dbg.BeginBacktrack( level );
+ }
+
+ public virtual void EndBacktrack( int level, bool successful )
+ {
+ dbg.EndBacktrack( level, successful );
+ }
+
+ public override void ReportError( RecognitionException e )
+ {
+ base.ReportError(e);
+ dbg.RecognitionException( e );
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTokenStream.cs
new file mode 100644
index 0000000..ef61376
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTokenStream.cs
@@ -0,0 +1,212 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+
+ public class DebugTokenStream : ITokenStream
+ {
+ protected IDebugEventListener dbg;
+ public ITokenStream input;
+ protected bool initialStreamState = true;
+
+ /** <summary>Track the last mark() call result value for use in rewind().</summary> */
+ protected int lastMarker;
+
+ public DebugTokenStream( ITokenStream input, IDebugEventListener dbg )
+ {
+ this.input = input;
+ DebugListener = dbg;
+ // force TokenStream to get at least first valid token
+ // so we know if there are any hidden tokens first in the stream
+ input.LT( 1 );
+ }
+
+ #region Properties
+
+ public virtual int Index
+ {
+ get
+ {
+ return input.Index;
+ }
+ }
+
+ public virtual int Range
+ {
+ get
+ {
+ return input.Range;
+ }
+ }
+
+ public virtual IDebugEventListener DebugListener
+ {
+ get
+ {
+ return dbg;
+ }
+ set
+ {
+ dbg = value;
+ }
+ }
+
+ #endregion
+
+ public virtual void Consume()
+ {
+ if ( initialStreamState )
+ {
+ ConsumeInitialHiddenTokens();
+ }
+ int a = input.Index;
+ IToken t = input.LT( 1 );
+ input.Consume();
+ int b = input.Index;
+ dbg.ConsumeToken( t );
+ if ( b > a + 1 )
+ {
+ // then we consumed more than one token; must be off channel tokens
+ for ( int i = a + 1; i < b; i++ )
+ {
+ dbg.ConsumeHiddenToken( input.Get( i ) );
+ }
+ }
+ }
+
+ /** <summary>Consume all initial off-channel tokens</summary> */
+ protected virtual void ConsumeInitialHiddenTokens()
+ {
+ int firstOnChannelTokenIndex = input.Index;
+ for ( int i = 0; i < firstOnChannelTokenIndex; i++ )
+ {
+ dbg.ConsumeHiddenToken( input.Get( i ) );
+ }
+ initialStreamState = false;
+ }
+
+ public virtual IToken LT( int i )
+ {
+ if ( initialStreamState )
+ {
+ ConsumeInitialHiddenTokens();
+ }
+ dbg.LT( i, input.LT( i ) );
+ return input.LT( i );
+ }
+
+ public virtual int LA( int i )
+ {
+ if ( initialStreamState )
+ {
+ ConsumeInitialHiddenTokens();
+ }
+ dbg.LT( i, input.LT( i ) );
+ return input.LA( i );
+ }
+
+ public virtual IToken Get( int i )
+ {
+ return input.Get( i );
+ }
+
+ public virtual int Mark()
+ {
+ lastMarker = input.Mark();
+ dbg.Mark( lastMarker );
+ return lastMarker;
+ }
+
+ public virtual void Rewind( int marker )
+ {
+ dbg.Rewind( marker );
+ input.Rewind( marker );
+ }
+
+ public virtual void Rewind()
+ {
+ dbg.Rewind();
+ input.Rewind( lastMarker );
+ }
+
+ public virtual void Release( int marker )
+ {
+ }
+
+ public virtual void Seek( int index )
+ {
+ // TODO: implement seek in dbg interface
+ // db.seek(index);
+ input.Seek( index );
+ }
+
+ public virtual int Count
+ {
+ get
+ {
+ return input.Count;
+ }
+ }
+
+ public virtual ITokenSource TokenSource
+ {
+ get
+ {
+ return input.TokenSource;
+ }
+ }
+
+ public virtual string SourceName
+ {
+ get
+ {
+ return TokenSource.SourceName;
+ }
+ }
+
+ public override string ToString()
+ {
+ return input.ToString();
+ }
+
+ public virtual string ToString( int start, int stop )
+ {
+ return input.ToString( start, stop );
+ }
+
+ public virtual string ToString( IToken start, IToken stop )
+ {
+ return input.ToString( start, stop );
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeAdaptor.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeAdaptor.cs
new file mode 100644
index 0000000..1399b53
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeAdaptor.cs
@@ -0,0 +1,329 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2011 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor;
+
+ /** <summary>
+ * A TreeAdaptor proxy that fires debugging events to a DebugEventListener
+ * delegate and uses the TreeAdaptor delegate to do the actual work. All
+ * AST events are triggered by this adaptor; no code gen changes are needed
+ * in generated rules. Debugging events are triggered *after* invoking
+ * tree adaptor routines.
+ * </summary>
+ *
+ * <remarks>
+ * Trees created with actions in rewrite actions like "-&gt; ^(ADD {foo} {bar})"
+ * cannot be tracked as they might not use the adaptor to create foo, bar.
+ * The debug listener has to deal with tree node IDs for which it did
+ * not see a createNode event. A single &lt;unknown&gt; node is sufficient even
+ * if it represents a whole tree.
+ * </remarks>
+ */
+ public class DebugTreeAdaptor : ITreeAdaptor
+ {
+ protected IDebugEventListener dbg;
+ protected ITreeAdaptor adaptor;
+
+ public DebugTreeAdaptor( IDebugEventListener dbg, ITreeAdaptor adaptor )
+ {
+ this.dbg = dbg;
+ this.adaptor = adaptor;
+ }
+
+ public virtual object Create( IToken payload )
+ {
+ if ( payload.TokenIndex < 0 )
+ {
+ // could be token conjured up during error recovery
+ return Create( payload.Type, payload.Text );
+ }
+ object node = adaptor.Create( payload );
+ dbg.CreateNode( node, payload );
+ return node;
+ }
+
+ public virtual object ErrorNode( ITokenStream input, IToken start, IToken stop,
+ RecognitionException e )
+ {
+ object node = adaptor.ErrorNode( input, start, stop, e );
+ if ( node != null )
+ {
+ dbg.ErrorNode( node );
+ }
+ return node;
+ }
+
+ public virtual object DupTree( object tree )
+ {
+ object t = adaptor.DupTree( tree );
+ // walk the tree and emit create and add child events
+ // to simulate what dupTree has done. dupTree does not call this debug
+ // adapter so I must simulate.
+ SimulateTreeConstruction( t );
+ return t;
+ }
+
+ /** <summary>^(A B C): emit create A, create B, add child, ...</summary> */
+ protected virtual void SimulateTreeConstruction( object t )
+ {
+ dbg.CreateNode( t );
+ int n = adaptor.GetChildCount( t );
+ for ( int i = 0; i < n; i++ )
+ {
+ object child = adaptor.GetChild( t, i );
+ SimulateTreeConstruction( child );
+ dbg.AddChild( t, child );
+ }
+ }
+
+ public virtual object DupNode( object treeNode )
+ {
+ object d = adaptor.DupNode( treeNode );
+ dbg.CreateNode( d );
+ return d;
+ }
+
+ public object DupNode(int type, object treeNode)
+ {
+ object d = adaptor.DupNode(type, treeNode);
+ dbg.CreateNode(d);
+ return d;
+ }
+
+ public object DupNode(object treeNode, string text)
+ {
+ object d = adaptor.DupNode(treeNode, text);
+ dbg.CreateNode(d);
+ return d;
+ }
+
+ public object DupNode(int type, object treeNode, string text)
+ {
+ object d = adaptor.DupNode(type, treeNode, text);
+ dbg.CreateNode(d);
+ return d;
+ }
+
+ public virtual object Nil()
+ {
+ object node = adaptor.Nil();
+ dbg.NilNode( node );
+ return node;
+ }
+
+ public virtual bool IsNil( object tree )
+ {
+ return adaptor.IsNil( tree );
+ }
+
+ public virtual void AddChild( object t, object child )
+ {
+ if ( t == null || child == null )
+ {
+ return;
+ }
+ adaptor.AddChild( t, child );
+ dbg.AddChild( t, child );
+ }
+
+ public virtual object BecomeRoot( object newRoot, object oldRoot )
+ {
+ object n = adaptor.BecomeRoot( newRoot, oldRoot );
+ dbg.BecomeRoot( newRoot, oldRoot );
+ return n;
+ }
+
+ public virtual object RulePostProcessing( object root )
+ {
+ return adaptor.RulePostProcessing( root );
+ }
+
+ public virtual void AddChild( object t, IToken child )
+ {
+ object n = this.Create( child );
+ this.AddChild( t, n );
+ }
+
+ public virtual object BecomeRoot( IToken newRoot, object oldRoot )
+ {
+ object n = this.Create( newRoot );
+ adaptor.BecomeRoot( n, oldRoot );
+ dbg.BecomeRoot( newRoot, oldRoot );
+ return n;
+ }
+
+ public virtual object Create( int tokenType, IToken fromToken )
+ {
+ object node = adaptor.Create( tokenType, fromToken );
+ dbg.CreateNode( node );
+ return node;
+ }
+
+ public virtual object Create( int tokenType, IToken fromToken, string text )
+ {
+ object node = adaptor.Create( tokenType, fromToken, text );
+ dbg.CreateNode( node );
+ return node;
+ }
+
+ public virtual object Create( int tokenType, string text )
+ {
+ object node = adaptor.Create( tokenType, text );
+ dbg.CreateNode( node );
+ return node;
+ }
+
+ public object Create(IToken fromToken, string text)
+ {
+ object node = adaptor.Create(fromToken, text);
+ dbg.CreateNode(node);
+ return node;
+ }
+
+ public virtual int GetType( object t )
+ {
+ return adaptor.GetType( t );
+ }
+
+ public virtual void SetType( object t, int type )
+ {
+ adaptor.SetType( t, type );
+ }
+
+ public virtual string GetText( object t )
+ {
+ return adaptor.GetText( t );
+ }
+
+ public virtual void SetText( object t, string text )
+ {
+ adaptor.SetText( t, text );
+ }
+
+ public virtual IToken GetToken( object t )
+ {
+ return adaptor.GetToken( t );
+ }
+
+ public virtual void SetTokenBoundaries( object t, IToken startToken, IToken stopToken )
+ {
+ adaptor.SetTokenBoundaries( t, startToken, stopToken );
+ if ( t != null && startToken != null && stopToken != null )
+ {
+ dbg.SetTokenBoundaries(
+ t, startToken.TokenIndex,
+ stopToken.TokenIndex );
+ }
+ }
+
+ public virtual int GetTokenStartIndex( object t )
+ {
+ return adaptor.GetTokenStartIndex( t );
+ }
+
+ public virtual int GetTokenStopIndex( object t )
+ {
+ return adaptor.GetTokenStopIndex( t );
+ }
+
+ public virtual object GetChild( object t, int i )
+ {
+ return adaptor.GetChild( t, i );
+ }
+
+ public virtual void SetChild( object t, int i, object child )
+ {
+ adaptor.SetChild( t, i, child );
+ }
+
+ public virtual object DeleteChild( object t, int i )
+ {
+ return DeleteChild( t, i );
+ }
+
+ public virtual int GetChildCount( object t )
+ {
+ return adaptor.GetChildCount( t );
+ }
+
+ public virtual int GetUniqueID( object node )
+ {
+ return adaptor.GetUniqueID( node );
+ }
+
+ public virtual object GetParent( object t )
+ {
+ return adaptor.GetParent( t );
+ }
+
+ public virtual int GetChildIndex( object t )
+ {
+ return adaptor.GetChildIndex( t );
+ }
+
+ public virtual void SetParent( object t, object parent )
+ {
+ adaptor.SetParent( t, parent );
+ }
+
+ public virtual void SetChildIndex( object t, int index )
+ {
+ adaptor.SetChildIndex( t, index );
+ }
+
+ public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )
+ {
+ adaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t );
+ }
+
+ #region support
+
+ public virtual IDebugEventListener GetDebugListener()
+ {
+ return dbg;
+ }
+
+ public virtual void SetDebugListener( IDebugEventListener dbg )
+ {
+ this.dbg = dbg;
+ }
+
+ public virtual ITreeAdaptor GetTreeAdaptor()
+ {
+ return adaptor;
+ }
+
+ #endregion
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeNodeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeNodeStream.cs
new file mode 100644
index 0000000..4af8c5b
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeNodeStream.cs
@@ -0,0 +1,216 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using Obsolete = System.ObsoleteAttribute;
+ using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor;
+ using ITreeNodeStream = Antlr.Runtime.Tree.ITreeNodeStream;
+
+ /** <summary>
+ * Debug any tree node stream. The constructor accepts the stream
+ * and a debug listener. As node stream calls come in, debug events
+ * are triggered.
+ * </summary>
+ */
+ public class DebugTreeNodeStream : ITreeNodeStream
+ {
+ protected IDebugEventListener dbg;
+ protected ITreeAdaptor adaptor;
+ protected ITreeNodeStream input;
+ protected bool initialStreamState = true;
+
+ /** <summary>Track the last mark() call result value for use in rewind().</summary> */
+ protected int lastMarker;
+
+ public DebugTreeNodeStream( ITreeNodeStream input,
+ IDebugEventListener dbg )
+ {
+ this.input = input;
+ this.adaptor = input.TreeAdaptor;
+ this.input.UniqueNavigationNodes = true;
+ DebugListener = dbg;
+ }
+
+ #region Properties
+ public virtual IDebugEventListener DebugListener
+ {
+ get
+ {
+ return dbg;
+ }
+ set
+ {
+ dbg = value;
+ }
+ }
+ public virtual int Index
+ {
+ get
+ {
+ return input.Index;
+ }
+ }
+ public virtual ITokenStream TokenStream
+ {
+ get
+ {
+ return input.TokenStream;
+ }
+ }
+ public virtual ITreeAdaptor TreeAdaptor
+ {
+ get
+ {
+ return adaptor;
+ }
+ }
+ public virtual object TreeSource
+ {
+ get
+ {
+ return input;
+ }
+ }
+ /** <summary>
+ * It is normally this object that instructs the node stream to
+ * create unique nav nodes, but to satisfy interface, we have to
+ * define it. It might be better to ignore the parameter but
+ * there might be a use for it later, so I'll leave.
+ * </summary>
+ */
+ public bool UniqueNavigationNodes
+ {
+ get
+ {
+ return input.UniqueNavigationNodes;
+ }
+ set
+ {
+ input.UniqueNavigationNodes = value;
+ }
+ }
+
+ #endregion
+
+ public virtual void Consume()
+ {
+ object node = input.LT( 1 );
+ input.Consume();
+ dbg.ConsumeNode( node );
+ }
+
+ public virtual object this[int i]
+ {
+ get
+ {
+ return input[i];
+ }
+ }
+
+ public virtual object LT( int i )
+ {
+ object node = input.LT( i );
+ int ID = adaptor.GetUniqueID( node );
+ string text = adaptor.GetText( node );
+ int type = adaptor.GetType( node );
+ dbg.LT( i, node );
+ return node;
+ }
+
+ public virtual int LA( int i )
+ {
+ object node = input.LT( i );
+ int ID = adaptor.GetUniqueID( node );
+ string text = adaptor.GetText( node );
+ int type = adaptor.GetType( node );
+ dbg.LT( i, node );
+ return type;
+ }
+
+ public virtual int Mark()
+ {
+ lastMarker = input.Mark();
+ dbg.Mark( lastMarker );
+ return lastMarker;
+ }
+
+ public virtual void Rewind( int marker )
+ {
+ dbg.Rewind( marker );
+ input.Rewind( marker );
+ }
+
+ public virtual void Rewind()
+ {
+ dbg.Rewind();
+ input.Rewind( lastMarker );
+ }
+
+ public virtual void Release( int marker )
+ {
+ }
+
+ public virtual void Seek( int index )
+ {
+ // TODO: implement seek in dbg interface
+ // db.seek(index);
+ input.Seek( index );
+ }
+
+ public virtual int Count
+ {
+ get
+ {
+ return input.Count;
+ }
+ }
+
+ public virtual string SourceName
+ {
+ get
+ {
+ return TokenStream.SourceName;
+ }
+ }
+
+ public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t )
+ {
+ input.ReplaceChildren( parent, startChildIndex, stopChildIndex, t );
+ }
+
+ public virtual string ToString( object start, object stop )
+ {
+ return input.ToString( start, stop );
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeParser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeParser.cs
new file mode 100644
index 0000000..6461387
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/DebugTreeParser.cs
@@ -0,0 +1,137 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using Antlr.Runtime.JavaExtensions;
+
+ using Console = System.Console;
+ using IOException = System.IO.IOException;
+ using ITreeNodeStream = Antlr.Runtime.Tree.ITreeNodeStream;
+ using TreeParser = Antlr.Runtime.Tree.TreeParser;
+
+ public class DebugTreeParser : TreeParser
+ {
+ /** <summary>Who to notify when events in the parser occur.</summary> */
+ public IDebugEventListener dbg = null;
+
+ /** <summary>
+ * Used to differentiate between fixed lookahead and cyclic DFA decisions
+ * while profiling.
+ * </summary>
+ */
+ public bool isCyclicDecision = false;
+
+ /** <summary>
+ * Create a normal parser except wrap the token stream in a debug
+ * proxy that fires consume events.
+ * </summary>
+ */
+ public DebugTreeParser( ITreeNodeStream input, IDebugEventListener dbg, RecognizerSharedState state )
+ : base( input is DebugTreeNodeStream ? input : new DebugTreeNodeStream( input, dbg ), state )
+ {
+ SetDebugListener(dbg);
+ }
+
+ public DebugTreeParser( ITreeNodeStream input, RecognizerSharedState state )
+ : base( input is DebugTreeNodeStream ? input : new DebugTreeNodeStream( input, null ), state )
+ {
+ }
+
+ public DebugTreeParser( ITreeNodeStream input, IDebugEventListener dbg )
+ : this( input is DebugTreeNodeStream ? input : new DebugTreeNodeStream( input, dbg ), dbg, null )
+ {
+ }
+
+ public override IDebugEventListener DebugListener
+ {
+ get
+ {
+ return dbg;
+ }
+ }
+
+ /** <summary>
+ * Provide a new debug event listener for this parser. Notify the
+ * input stream too that it should send events to this listener.
+ * </summary>
+ */
+ public virtual void SetDebugListener(IDebugEventListener value)
+ {
+ if (input is DebugTreeNodeStream)
+ ((DebugTreeNodeStream)input).DebugListener = value;
+
+ this.dbg = value;
+ }
+
+ public virtual void ReportError( IOException e )
+ {
+ Console.Error.WriteLine( e );
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+
+ public override void ReportError( RecognitionException e )
+ {
+ dbg.RecognitionException( e );
+ }
+
+ protected override object GetMissingSymbol( IIntStream input,
+ RecognitionException e,
+ int expectedTokenType,
+ BitSet follow )
+ {
+ object o = base.GetMissingSymbol( input, e, expectedTokenType, follow );
+ dbg.ConsumeNode( o );
+ return o;
+ }
+
+ public override void BeginResync()
+ {
+ dbg.BeginResync();
+ }
+
+ public override void EndResync()
+ {
+ dbg.EndResync();
+ }
+
+ public virtual void BeginBacktrack( int level )
+ {
+ dbg.BeginBacktrack( level );
+ }
+
+ public virtual void EndBacktrack( int level, bool successful )
+ {
+ dbg.EndBacktrack( level, successful );
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/JavaExtensions/ExceptionExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/JavaExtensions/ExceptionExtensions.cs
new file mode 100644
index 0000000..0776cfe
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/JavaExtensions/ExceptionExtensions.cs
@@ -0,0 +1,51 @@
+/*
+ * [The "BSD license"]
+ * Copyright (c) 2011 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.JavaExtensions
+{
+ using Exception = System.Exception;
+ using TextWriter = System.IO.TextWriter;
+
+ internal static class ExceptionExtensions
+ {
+ public static void PrintStackTrace( Exception e, TextWriter writer )
+ {
+ writer.WriteLine( e.ToString() );
+ string trace = e.StackTrace ?? string.Empty;
+ foreach ( string line in trace.Split( '\n', '\r' ) )
+ {
+ if ( !string.IsNullOrEmpty( line ) )
+ writer.WriteLine( " " + line );
+ }
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/DoubleKeyMap`3.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/DoubleKeyMap`3.cs
new file mode 100644
index 0000000..16cfc26
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/DoubleKeyMap`3.cs
@@ -0,0 +1,86 @@
+namespace Antlr.Runtime.Debug.Misc
+{
+ using System.Collections.Generic;
+
+ public class DoubleKeyMap<TKey1, TKey2, TValue>
+ {
+ internal IDictionary<TKey1, IDictionary<TKey2, TValue>> data = new Dictionary<TKey1, IDictionary<TKey2, TValue>>();
+
+ public virtual TValue Put(TKey1 k1, TKey2 k2, TValue v)
+ {
+ IDictionary<TKey2, TValue> data2;
+ data.TryGetValue(k1, out data2);
+ TValue prev = default(TValue);
+ if (data2 == null)
+ {
+ data2 = new Dictionary<TKey2, TValue>();
+ data[k1]=data2;
+ }
+ else
+ {
+ data2.TryGetValue(k2, out prev);
+ }
+ data2[k2]= v;
+ return prev;
+ }
+
+ public virtual TValue Get(TKey1 k1, TKey2 k2)
+ {
+ IDictionary<TKey2, TValue> data2;
+ data.TryGetValue(k1, out data2);
+ if (data2 == null)
+ return default(TValue);
+
+ TValue value;
+ data2.TryGetValue(k2, out value);
+ return value;
+ }
+
+ public virtual IDictionary<TKey2, TValue> Get(TKey1 k1)
+ {
+ IDictionary<TKey2, TValue> value;
+ data.TryGetValue(k1, out value);
+ return value;
+ }
+
+ /** Get all values associated with primary key */
+ public virtual ICollection<TValue> Values(TKey1 k1)
+ {
+ IDictionary<TKey2, TValue> data2;
+ data.TryGetValue(k1, out data2);
+ if (data2 == null)
+ return null;
+
+ return data2.Values;
+ }
+
+ /** get all primary keys */
+ public virtual ICollection<TKey1> KeySet()
+ {
+ return data.Keys;
+ }
+
+ /** get all secondary keys associated with a primary key */
+ public virtual ICollection<TKey2> KeySet(TKey1 k1)
+ {
+ IDictionary<TKey2, TValue> data2;
+ data.TryGetValue(k1, out data2);
+ if (data2 == null)
+ return null;
+
+ return data2.Keys;
+ }
+
+ public virtual ICollection<TValue> Values()
+ {
+ Dictionary<TValue, bool> s = new Dictionary<TValue, bool>();
+ foreach (IDictionary<TKey2, TValue> k2 in data.Values)
+ {
+ foreach (TValue v in k2.Values)
+ s[v] = true;
+ }
+
+ return s.Keys;
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/Stats.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/Stats.cs
new file mode 100644
index 0000000..6a465f7
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Misc/Stats.cs
@@ -0,0 +1,131 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Misc
+{
+ using System.Collections.Generic;
+
+ using Directory = System.IO.Directory;
+ using Environment = System.Environment;
+ using File = System.IO.File;
+ using Math = System.Math;
+ using Path = System.IO.Path;
+
+ /** <summary>Stats routines needed by profiler etc...</summary>
+ *
+ * <remarks>
+ * note that these routines return 0.0 if no values exist in the X[]
+ * which is not "correct", but it is useful so I don't generate NaN
+ * in my output
+ * </remarks>
+ */
+ public class Stats
+ {
+ public const string ANTLRWORKS_DIR = "antlrworks";
+
+ /** <summary>Compute the sample (unbiased estimator) standard deviation following:</summary>
+ *
+ * <remarks>
+ * Computing Deviations: Standard Accuracy
+ * Tony F. Chan and John Gregg Lewis
+ * Stanford University
+ * Communications of ACM September 1979 of Volume 22 the ACM Number 9
+ *
+ * The "two-pass" method from the paper; supposed to have better
+ * numerical properties than the textbook summation/sqrt. To me
+ * this looks like the textbook method, but I ain't no numerical
+ * methods guy.
+ * </remarks>
+ */
+ public static double Stddev( int[] X )
+ {
+ int m = X.Length;
+ if ( m <= 1 )
+ {
+ return 0;
+ }
+ double xbar = Average(X);
+ double s2 = 0.0;
+ for ( int i = 0; i < m; i++ )
+ {
+ s2 += ( X[i] - xbar ) * ( X[i] - xbar );
+ }
+ s2 = s2 / ( m - 1 );
+ return Math.Sqrt( s2 );
+ }
+ public static double Stddev( List<int> X )
+ {
+ int m = X.Count;
+ if ( m <= 1 )
+ {
+ return 0;
+ }
+ double xbar = Average(X);
+ double s2 = 0.0;
+ for ( int i = 0; i < m; i++ )
+ {
+ s2 += ( X[i] - xbar ) * ( X[i] - xbar );
+ }
+ s2 = s2 / ( m - 1 );
+ return Math.Sqrt( s2 );
+ }
+
+ /** <summary>Compute the sample mean</summary> */
+ public static double Average(ICollection<int> X)
+ {
+ if (X.Count == 0)
+ return 0.0;
+
+ double sum = 0.0;
+ foreach (int i in X)
+ sum += i;
+
+ return sum / X.Count;
+ }
+
+ public static void WriteReport( string filename, string data )
+ {
+ string absoluteFilename = GetAbsoluteFileName( filename );
+
+ Directory.CreateDirectory( Path.GetDirectoryName( absoluteFilename ) );
+ File.AppendAllText( absoluteFilename, data );
+ }
+
+ public static string GetAbsoluteFileName( string filename )
+ {
+ string personalFolder = Environment.GetFolderPath( Environment.SpecialFolder.Personal );
+ return personalFolder + Path.DirectorySeparatorChar +
+ ANTLRWORKS_DIR + Path.DirectorySeparatorChar +
+ filename;
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParseTreeBuilder.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParseTreeBuilder.cs
new file mode 100644
index 0000000..deeaf3b
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParseTreeBuilder.cs
@@ -0,0 +1,139 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using System.Collections.Generic;
+ using ParseTree = Antlr.Runtime.Tree.ParseTree;
+
+ /** <summary>
+ * This parser listener tracks rule entry/exit and token matches
+ * to build a simple parse tree using ParseTree nodes.
+ * </summary>
+ */
+ public class ParseTreeBuilder : BlankDebugEventListener
+ {
+ public const string EPSILON_PAYLOAD = "<epsilon>";
+
+ Stack<ParseTree> callStack = new Stack<ParseTree>();
+ List<IToken> hiddenTokens = new List<IToken>();
+ int backtracking = 0;
+
+ public ParseTreeBuilder( string grammarName )
+ {
+ ParseTree root = Create( "<grammar " + grammarName + ">" );
+ callStack.Push( root );
+ }
+
+ public virtual ParseTree Tree
+ {
+ get
+ {
+ return callStack.Peek();
+ }
+ }
+
+ /** <summary>
+ * What kind of node to create. You might want to override
+ * so I factored out creation here.
+ * </summary>
+ */
+ public virtual ParseTree Create( object payload )
+ {
+ return new ParseTree( payload );
+ }
+
+ public virtual ParseTree EpsilonNode()
+ {
+ return Create( EPSILON_PAYLOAD );
+ }
+
+ /** <summary>Backtracking or cyclic DFA, don't want to add nodes to tree</summary> */
+ public override void EnterDecision( int d, bool couldBacktrack )
+ {
+ backtracking++;
+ }
+ public override void ExitDecision( int i )
+ {
+ backtracking--;
+ }
+
+ public override void EnterRule( string filename, string ruleName )
+ {
+ if ( backtracking > 0 )
+ return;
+ ParseTree parentRuleNode = callStack.Peek();
+ ParseTree ruleNode = Create( ruleName );
+ parentRuleNode.AddChild( ruleNode );
+ callStack.Push( ruleNode );
+ }
+
+ public override void ExitRule( string filename, string ruleName )
+ {
+ if ( backtracking > 0 )
+ return;
+ ParseTree ruleNode = callStack.Peek();
+ if ( ruleNode.ChildCount == 0 )
+ {
+ ruleNode.AddChild( EpsilonNode() );
+ }
+ callStack.Pop();
+ }
+
+ public override void ConsumeToken( IToken token )
+ {
+ if ( backtracking > 0 )
+ return;
+ ParseTree ruleNode = callStack.Peek();
+ ParseTree elementNode = Create( token );
+ elementNode.hiddenTokens = this.hiddenTokens;
+ this.hiddenTokens = new List<IToken>();
+ ruleNode.AddChild( elementNode );
+ }
+
+ public override void ConsumeHiddenToken( IToken token )
+ {
+ if ( backtracking > 0 )
+ return;
+ hiddenTokens.Add( token );
+ }
+
+ public override void RecognitionException( RecognitionException e )
+ {
+ if ( backtracking > 0 )
+ return;
+ ParseTree ruleNode = callStack.Peek();
+ ParseTree errorNode = Create( e );
+ ruleNode.AddChild( errorNode );
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParserDebugger.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParserDebugger.cs
new file mode 100644
index 0000000..0b60f2b
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/ParserDebugger.cs
@@ -0,0 +1,49 @@
+namespace Antlr.Runtime.Debug
+{
+ using System;
+ using System.Collections.Generic;
+ using System.Linq;
+ using System.Text;
+
+ using IOException = System.IO.IOException;
+ using Antlr.Runtime.Tree;
+
+ public class ParserDebugger
+ {
+ IDebugEventListener dbg;
+
+ public ParserDebugger( Parser parser )
+ : this( parser, DebugEventSocketProxy.DEFAULT_DEBUGGER_PORT )
+ {
+ }
+ public ParserDebugger( Parser parser, int port )
+ {
+ DebugEventSocketProxy proxy = new DebugEventSocketProxy( parser, port, null );
+ DebugListener = proxy;
+ parser.TokenStream = new DebugTokenStream( parser.TokenStream, proxy );
+ try
+ {
+ proxy.handshake();
+ }
+ catch ( IOException e )
+ {
+ reportError( ioe );
+ }
+ ITreeAdaptor adap = new CommonTreeAdaptor();
+ TreeAdaptor = adap;
+ proxy.TreeAdaptor = adap;
+ }
+ public ParserDebugger( Parser parser, IDebugEventListener dbg )
+ {
+ ITreeAdaptor adap = new CommonTreeAdaptor();
+ TreeAdaptor = adap;
+ }
+
+ protected virtual bool EvalPredicate( bool result, string predicate )
+ {
+ dbg.SemanticPredicate( result, predicate );
+ return result;
+ }
+
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Profiler.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Profiler.cs
new file mode 100644
index 0000000..54caac8
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Profiler.cs
@@ -0,0 +1,797 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using System.Collections.Generic;
+ using System.Collections.ObjectModel;
+ using Antlr.Runtime.Debug.Misc;
+
+ using Array = System.Array;
+ using CLSCompliantAttribute = System.CLSCompliantAttribute;
+ using Console = System.Console;
+ using DateTime = System.DateTime;
+ using Environment = System.Environment;
+ using Math = System.Math;
+ using StringBuilder = System.Text.StringBuilder;
+
+ /** <summary>Using the debug event interface, track what is happening in the parser
+ * and record statistics about the runtime.
+ */
+ public class Profiler : BlankDebugEventListener
+ {
+ public static readonly string DataSeparator = "\t";
+ public static readonly string NewLine = Environment.NewLine;
+
+ internal static bool dump = false;
+
+ /** Because I may change the stats, I need to track that for later
+ * computations to be consistent.
+ */
+ public static readonly string Version = "3";
+ public static readonly string RuntimeStatsFilename = "runtime.stats";
+
+ /** Ack, should not store parser; can't do remote stuff. Well, we pass
+ * input stream around too so I guess it's ok.
+ */
+ public DebugParser parser = null;
+
+ // working variables
+
+ [CLSCompliant(false)]
+ protected int ruleLevel = 0;
+ //protected int decisionLevel = 0;
+ protected IToken lastRealTokenTouchedInDecision;
+ protected Dictionary<string, bool> uniqueRules = new Dictionary<string, bool>();
+ protected Stack<string> currentGrammarFileName = new Stack<string>();
+ protected Stack<string> currentRuleName = new Stack<string>();
+ protected Stack<int> currentLine = new Stack<int>();
+ protected Stack<int> currentPos = new Stack<int>();
+
+ // Vector<DecisionStats>
+ //protected Vector decisions = new Vector(200); // need setSize
+ protected DoubleKeyMap<string, int, DecisionDescriptor> decisions = new DoubleKeyMap<string, int, DecisionDescriptor>();
+
+ // Record a DecisionData for each decision we hit while parsing
+ private List<DecisionEvent> decisionEvents = new List<DecisionEvent>();
+ protected Stack<DecisionEvent> decisionStack = new Stack<DecisionEvent>();
+
+ protected int backtrackDepth;
+
+ ProfileStats stats = new ProfileStats();
+
+ public Profiler()
+ {
+ }
+
+ public Profiler(DebugParser parser)
+ {
+ this.parser = parser;
+ }
+
+ public override void EnterRule(string grammarFileName, string ruleName)
+ {
+ //System.out.println("enterRule "+grammarFileName+":"+ruleName);
+ ruleLevel++;
+ stats.numRuleInvocations++;
+ uniqueRules.Add(grammarFileName + ":" + ruleName, true);
+ stats.maxRuleInvocationDepth = Math.Max(stats.maxRuleInvocationDepth, ruleLevel);
+ currentGrammarFileName.Push(grammarFileName);
+ currentRuleName.Push(ruleName);
+ }
+
+ public override void ExitRule(string grammarFileName, string ruleName)
+ {
+ ruleLevel--;
+ currentGrammarFileName.Pop();
+ currentRuleName.Pop();
+ }
+
+ /** Track memoization; this is not part of standard debug interface
+ * but is triggered by profiling. Code gen inserts an override
+ * for this method in the recognizer, which triggers this method.
+ * Called from alreadyParsedRule().
+ */
+ public virtual void ExamineRuleMemoization(IIntStream input,
+ int ruleIndex,
+ int stopIndex, // index or MEMO_RULE_UNKNOWN...
+ string ruleName)
+ {
+ if (dump)
+ Console.WriteLine("examine memo " + ruleName + " at " + input.Index + ": " + stopIndex);
+ if (stopIndex == BaseRecognizer.MemoRuleUnknown)
+ {
+ //System.out.println("rule "+ruleIndex+" missed @ "+input.index());
+ stats.numMemoizationCacheMisses++;
+ stats.numGuessingRuleInvocations++; // we'll have to enter
+ CurrentDecision().numMemoizationCacheMisses++;
+ }
+ else
+ {
+ // regardless of rule success/failure, if in cache, we have a cache hit
+ //System.out.println("rule "+ruleIndex+" hit @ "+input.index());
+ stats.numMemoizationCacheHits++;
+ CurrentDecision().numMemoizationCacheHits++;
+ }
+ }
+
+ /** Warning: doesn't track success/failure, just unique recording event */
+ public virtual void Memoize(IIntStream input,
+ int ruleIndex,
+ int ruleStartIndex,
+ string ruleName)
+ {
+ // count how many entries go into table
+ if (dump)
+ Console.WriteLine("memoize " + ruleName);
+ stats.numMemoizationCacheEntries++;
+ }
+
+ public override void Location(int line, int pos)
+ {
+ currentLine.Push(line);
+ currentPos.Push(pos);
+ }
+
+ public override void EnterDecision(int decisionNumber, bool couldBacktrack)
+ {
+ lastRealTokenTouchedInDecision = null;
+ stats.numDecisionEvents++;
+ int startingLookaheadIndex = parser.TokenStream.Index;
+ ITokenStream input = parser.TokenStream;
+ if (dump)
+ {
+ Console.WriteLine("enterDecision canBacktrack=" + couldBacktrack + " " + decisionNumber +
+ " backtrack depth " + backtrackDepth +
+ " @ " + input.Get(input.Index) +
+ " rule " + LocationDescription());
+ }
+ string g = currentGrammarFileName.Peek();
+ DecisionDescriptor descriptor = decisions.Get(g, decisionNumber);
+ if (descriptor == null)
+ {
+ descriptor = new DecisionDescriptor();
+ decisions.Put(g, decisionNumber, descriptor);
+ descriptor.decision = decisionNumber;
+ descriptor.fileName = currentGrammarFileName.Peek();
+ descriptor.ruleName = currentRuleName.Peek();
+ descriptor.line = currentLine.Peek();
+ descriptor.pos = currentPos.Peek();
+ descriptor.couldBacktrack = couldBacktrack;
+ }
+ descriptor.n++;
+
+ DecisionEvent d = new DecisionEvent();
+ decisionStack.Push(d);
+ d.decision = descriptor;
+ d.startTime = DateTime.Now;
+ d.startIndex = startingLookaheadIndex;
+ }
+
+ public override void ExitDecision(int decisionNumber)
+ {
+ DecisionEvent d = decisionStack.Pop();
+ d.stopTime = DateTime.Now;
+
+ int lastTokenIndex = lastRealTokenTouchedInDecision.TokenIndex;
+ int numHidden = GetNumberOfHiddenTokens(d.startIndex, lastTokenIndex);
+ int depth = lastTokenIndex - d.startIndex - numHidden + 1; // +1 counts consuming start token as 1
+ d.k = depth;
+ d.decision.maxk = Math.Max(d.decision.maxk, depth);
+
+ if (dump)
+ {
+ Console.WriteLine("exitDecision " + decisionNumber + " in " + d.decision.ruleName +
+ " lookahead " + d.k + " max token " + lastRealTokenTouchedInDecision);
+ }
+
+ decisionEvents.Add(d); // done with decision; track all
+ }
+
+ public override void ConsumeToken(IToken token)
+ {
+ if (dump)
+ Console.WriteLine("consume token " + token);
+
+ if (!InDecision)
+ {
+ stats.numTokens++;
+ return;
+ }
+
+ if (lastRealTokenTouchedInDecision == null ||
+ lastRealTokenTouchedInDecision.TokenIndex < token.TokenIndex)
+ {
+ lastRealTokenTouchedInDecision = token;
+ }
+ DecisionEvent d = CurrentDecision();
+ // compute lookahead depth
+ int thisRefIndex = token.TokenIndex;
+ int numHidden = GetNumberOfHiddenTokens(d.startIndex, thisRefIndex);
+ int depth = thisRefIndex - d.startIndex - numHidden + 1; // +1 counts consuming start token as 1
+ //d.maxk = Math.max(d.maxk, depth);
+ if (dump)
+ {
+ Console.WriteLine("consume " + thisRefIndex + " " + depth + " tokens ahead in " +
+ d.decision.ruleName + "-" + d.decision.decision + " start index " + d.startIndex);
+ }
+ }
+
+ /** The parser is in a decision if the decision depth > 0. This
+ * works for backtracking also, which can have nested decisions.
+ */
+ public virtual bool InDecision
+ {
+ get
+ {
+ return decisionStack.Count > 0;
+ }
+ }
+
+ public override void ConsumeHiddenToken(IToken token)
+ {
+ //System.out.println("consume hidden token "+token);
+ if (!InDecision)
+ stats.numHiddenTokens++;
+ }
+
+ /** Track refs to lookahead if in a fixed/nonfixed decision.
+ */
+ public override void LT(int i, IToken t)
+ {
+ if (InDecision && i > 0)
+ {
+ DecisionEvent d = CurrentDecision();
+ if (dump)
+ {
+ Console.WriteLine("LT(" + i + ")=" + t + " index " + t.TokenIndex + " relative to " + d.decision.ruleName + "-" +
+ d.decision.decision + " start index " + d.startIndex);
+ }
+
+ if (lastRealTokenTouchedInDecision == null ||
+ lastRealTokenTouchedInDecision.TokenIndex < t.TokenIndex)
+ {
+ lastRealTokenTouchedInDecision = t;
+ if (dump)
+ Console.WriteLine("set last token " + lastRealTokenTouchedInDecision);
+ }
+ // get starting index off stack
+ // int stackTop = lookaheadStack.size()-1;
+ // Integer startingIndex = (Integer)lookaheadStack.get(stackTop);
+ // // compute lookahead depth
+ // int thisRefIndex = parser.getTokenStream().index();
+ // int numHidden =
+ // getNumberOfHiddenTokens(startingIndex.intValue(), thisRefIndex);
+ // int depth = i + thisRefIndex - startingIndex.intValue() - numHidden;
+ // /*
+ // System.out.println("LT("+i+") @ index "+thisRefIndex+" is depth "+depth+
+ // " max is "+maxLookaheadInCurrentDecision);
+ // */
+ // if ( depth>maxLookaheadInCurrentDecision ) {
+ // maxLookaheadInCurrentDecision = depth;
+ // }
+ // d.maxk = currentDecision()/
+ }
+ }
+
+ /** Track backtracking decisions. You'll see a fixed or cyclic decision
+ * and then a backtrack.
+ *
+ * enter rule
+ * ...
+ * enter decision
+ * LA and possibly consumes (for cyclic DFAs)
+ * begin backtrack level
+ * mark m
+ * rewind m
+ * end backtrack level, success
+ * exit decision
+ * ...
+ * exit rule
+ */
+ public override void BeginBacktrack(int level)
+ {
+ if (dump)
+ Console.WriteLine("enter backtrack " + level);
+ backtrackDepth++;
+ DecisionEvent e = CurrentDecision();
+ if (e.decision.couldBacktrack)
+ {
+ stats.numBacktrackOccurrences++;
+ e.decision.numBacktrackOccurrences++;
+ e.backtracks = true;
+ }
+ }
+
+ /** Successful or not, track how much lookahead synpreds use */
+ public override void EndBacktrack(int level, bool successful)
+ {
+ if (dump)
+ Console.WriteLine("exit backtrack " + level + ": " + successful);
+ backtrackDepth--;
+ }
+
+ public override void Mark(int i)
+ {
+ if (dump)
+ Console.WriteLine("mark " + i);
+ }
+
+ public override void Rewind(int i)
+ {
+ if (dump)
+ Console.WriteLine("rewind " + i);
+ }
+
+ public override void Rewind()
+ {
+ if (dump)
+ Console.WriteLine("rewind");
+ }
+
+ protected virtual DecisionEvent CurrentDecision()
+ {
+ return decisionStack.Peek();
+ }
+
+ public override void RecognitionException(RecognitionException e)
+ {
+ stats.numReportedErrors++;
+ }
+
+ public override void SemanticPredicate(bool result, string predicate)
+ {
+ stats.numSemanticPredicates++;
+ if (InDecision)
+ {
+ DecisionEvent d = CurrentDecision();
+ d.evalSemPred = true;
+ d.decision.numSemPredEvals++;
+ if (dump)
+ {
+ Console.WriteLine("eval " + predicate + " in " + d.decision.ruleName + "-" +
+ d.decision.decision);
+ }
+ }
+ }
+
+ public override void Terminate()
+ {
+ foreach (DecisionEvent e in decisionEvents)
+ {
+ //System.out.println("decision "+e.decision.decision+": k="+e.k);
+ e.decision.avgk += e.k;
+ stats.avgkPerDecisionEvent += e.k;
+ if (e.backtracks)
+ { // doesn't count gated syn preds on DFA edges
+ stats.avgkPerBacktrackingDecisionEvent += e.k;
+ }
+ }
+ stats.averageDecisionPercentBacktracks = 0.0f;
+ foreach (DecisionDescriptor d in decisions.Values())
+ {
+ stats.numDecisionsCovered++;
+ d.avgk /= (float)d.n;
+ if (d.couldBacktrack)
+ {
+ stats.numDecisionsThatPotentiallyBacktrack++;
+ float percentBacktracks = d.numBacktrackOccurrences / (float)d.n;
+ //System.out.println("dec "+d.decision+" backtracks "+percentBacktracks*100+"%");
+ stats.averageDecisionPercentBacktracks += percentBacktracks;
+ }
+ // ignore rules that backtrack along gated DFA edges
+ if (d.numBacktrackOccurrences > 0)
+ {
+ stats.numDecisionsThatDoBacktrack++;
+ }
+ }
+ stats.averageDecisionPercentBacktracks /= stats.numDecisionsThatPotentiallyBacktrack;
+ stats.averageDecisionPercentBacktracks *= 100; // it's a percentage
+ stats.avgkPerDecisionEvent /= stats.numDecisionEvents;
+ stats.avgkPerBacktrackingDecisionEvent /= (float)stats.numBacktrackOccurrences;
+
+ Console.Error.WriteLine(ToString());
+ Console.Error.WriteLine(GetDecisionStatsDump());
+
+ // String stats = toNotifyString();
+ // try {
+ // Stats.writeReport(RUNTIME_STATS_FILENAME,stats);
+ // }
+ // catch (IOException ioe) {
+ // System.err.println(ioe);
+ // ioe.printStackTrace(System.err);
+ // }
+ }
+
+ public virtual void SetParser(DebugParser parser)
+ {
+ this.parser = parser;
+ }
+
+ // R E P O R T I N G
+
+ public virtual string ToNotifyString()
+ {
+ StringBuilder buf = new StringBuilder();
+ buf.Append(Version);
+ buf.Append('\t');
+ buf.Append(parser.GetType().Name);
+ // buf.Append('\t');
+ // buf.Append(numRuleInvocations);
+ // buf.Append('\t');
+ // buf.Append(maxRuleInvocationDepth);
+ // buf.Append('\t');
+ // buf.Append(numFixedDecisions);
+ // buf.Append('\t');
+ // buf.Append(Stats.min(decisionMaxFixedLookaheads));
+ // buf.Append('\t');
+ // buf.Append(Stats.max(decisionMaxFixedLookaheads));
+ // buf.Append('\t');
+ // buf.Append(Stats.avg(decisionMaxFixedLookaheads));
+ // buf.Append('\t');
+ // buf.Append(Stats.stddev(decisionMaxFixedLookaheads));
+ // buf.Append('\t');
+ // buf.Append(numCyclicDecisions);
+ // buf.Append('\t');
+ // buf.Append(Stats.min(decisionMaxCyclicLookaheads));
+ // buf.Append('\t');
+ // buf.Append(Stats.max(decisionMaxCyclicLookaheads));
+ // buf.Append('\t');
+ // buf.Append(Stats.avg(decisionMaxCyclicLookaheads));
+ // buf.Append('\t');
+ // buf.Append(Stats.stddev(decisionMaxCyclicLookaheads));
+ // buf.Append('\t');
+ // buf.Append(numBacktrackDecisions);
+ // buf.Append('\t');
+ // buf.Append(Stats.min(toArray(decisionMaxSynPredLookaheads)));
+ // buf.Append('\t');
+ // buf.Append(Stats.max(toArray(decisionMaxSynPredLookaheads)));
+ // buf.Append('\t');
+ // buf.Append(Stats.avg(toArray(decisionMaxSynPredLookaheads)));
+ // buf.Append('\t');
+ // buf.Append(Stats.stddev(toArray(decisionMaxSynPredLookaheads)));
+ // buf.Append('\t');
+ // buf.Append(numSemanticPredicates);
+ // buf.Append('\t');
+ // buf.Append(parser.getTokenStream().size());
+ // buf.Append('\t');
+ // buf.Append(numHiddenTokens);
+ // buf.Append('\t');
+ // buf.Append(numCharsMatched);
+ // buf.Append('\t');
+ // buf.Append(numHiddenCharsMatched);
+ // buf.Append('\t');
+ // buf.Append(numberReportedErrors);
+ // buf.Append('\t');
+ // buf.Append(numMemoizationCacheHits);
+ // buf.Append('\t');
+ // buf.Append(numMemoizationCacheMisses);
+ // buf.Append('\t');
+ // buf.Append(numGuessingRuleInvocations);
+ // buf.Append('\t');
+ // buf.Append(numMemoizationCacheEntries);
+ return buf.ToString();
+ }
+
+ public override string ToString()
+ {
+ return ToString(GetReport());
+ }
+
+ public virtual ProfileStats GetReport()
+ {
+ //ITokenStream input = parser.TokenStream;
+ //for (int i = 0; i < input.Count && lastRealTokenTouchedInDecision != null && i <= lastRealTokenTouchedInDecision.TokenIndex; i++)
+ //{
+ // IToken t = input.Get(i);
+ // if (t.Channel != TokenChannels.Default)
+ // {
+ // stats.numHiddenTokens++;
+ // stats.numHiddenCharsMatched += t.Text.Length;
+ // }
+ //}
+ stats.Version = Version;
+ stats.name = parser.GetType().Name;
+ stats.numUniqueRulesInvoked = uniqueRules.Count;
+ //stats.numCharsMatched = lastTokenConsumed.getStopIndex() + 1;
+ return stats;
+ }
+
+ public virtual DoubleKeyMap<string, int, DecisionDescriptor> GetDecisionStats()
+ {
+ return decisions;
+ }
+
+ public virtual ReadOnlyCollection<DecisionEvent> DecisionEvents
+ {
+ get
+ {
+ return decisionEvents.AsReadOnly();
+ }
+ }
+
+ public static string ToString(ProfileStats stats)
+ {
+ StringBuilder buf = new StringBuilder();
+ buf.Append("ANTLR Runtime Report; Profile Version ");
+ buf.Append(stats.Version);
+ buf.Append(NewLine);
+ buf.Append("parser name ");
+ buf.Append(stats.name);
+ buf.Append(NewLine);
+ buf.Append("Number of rule invocations ");
+ buf.Append(stats.numRuleInvocations);
+ buf.Append(NewLine);
+ buf.Append("Number of unique rules visited ");
+ buf.Append(stats.numUniqueRulesInvoked);
+ buf.Append(NewLine);
+ buf.Append("Number of decision events ");
+ buf.Append(stats.numDecisionEvents);
+ buf.Append(NewLine);
+ buf.Append("Number of rule invocations while backtracking ");
+ buf.Append(stats.numGuessingRuleInvocations);
+ buf.Append(NewLine);
+ buf.Append("max rule invocation nesting depth ");
+ buf.Append(stats.maxRuleInvocationDepth);
+ buf.Append(NewLine);
+ // buf.Append("number of fixed lookahead decisions ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("min lookahead used in a fixed lookahead decision ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("max lookahead used in a fixed lookahead decision ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("average lookahead depth used in fixed lookahead decisions ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("standard deviation of depth used in fixed lookahead decisions ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("number of arbitrary lookahead decisions ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("min lookahead used in an arbitrary lookahead decision ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("max lookahead used in an arbitrary lookahead decision ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("average lookahead depth used in arbitrary lookahead decisions ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("standard deviation of depth used in arbitrary lookahead decisions ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("number of evaluated syntactic predicates ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("min lookahead used in a syntactic predicate ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("max lookahead used in a syntactic predicate ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("average lookahead depth used in syntactic predicates ");
+ // buf.Append();
+ // buf.Append(newline);
+ // buf.Append("standard deviation of depth used in syntactic predicates ");
+ // buf.Append();
+ // buf.Append(newline);
+ buf.Append("rule memoization cache size ");
+ buf.Append(stats.numMemoizationCacheEntries);
+ buf.Append(NewLine);
+ buf.Append("number of rule memoization cache hits ");
+ buf.Append(stats.numMemoizationCacheHits);
+ buf.Append(NewLine);
+ buf.Append("number of rule memoization cache misses ");
+ buf.Append(stats.numMemoizationCacheMisses);
+ buf.Append(NewLine);
+ // buf.Append("number of evaluated semantic predicates ");
+ // buf.Append();
+ // buf.Append(newline);
+ buf.Append("number of tokens ");
+ buf.Append(stats.numTokens);
+ buf.Append(NewLine);
+ buf.Append("number of hidden tokens ");
+ buf.Append(stats.numHiddenTokens);
+ buf.Append(NewLine);
+ buf.Append("number of char ");
+ buf.Append(stats.numCharsMatched);
+ buf.Append(NewLine);
+ buf.Append("number of hidden char ");
+ buf.Append(stats.numHiddenCharsMatched);
+ buf.Append(NewLine);
+ buf.Append("number of syntax errors ");
+ buf.Append(stats.numReportedErrors);
+ buf.Append(NewLine);
+ return buf.ToString();
+ }
+
+ public virtual string GetDecisionStatsDump()
+ {
+ StringBuilder buf = new StringBuilder();
+ buf.Append("location");
+ buf.Append(DataSeparator);
+ buf.Append("n");
+ buf.Append(DataSeparator);
+ buf.Append("avgk");
+ buf.Append(DataSeparator);
+ buf.Append("maxk");
+ buf.Append(DataSeparator);
+ buf.Append("synpred");
+ buf.Append(DataSeparator);
+ buf.Append("sempred");
+ buf.Append(DataSeparator);
+ buf.Append("canbacktrack");
+ buf.Append("\n");
+ foreach (string fileName in decisions.KeySet())
+ {
+ foreach (int d in decisions.KeySet(fileName))
+ {
+ DecisionDescriptor s = decisions.Get(fileName, d);
+ buf.Append(s.decision);
+ buf.Append("@");
+ buf.Append(LocationDescription(s.fileName, s.ruleName, s.line, s.pos)); // decision number
+ buf.Append(DataSeparator);
+ buf.Append(s.n);
+ buf.Append(DataSeparator);
+ buf.Append(string.Format("{0}", s.avgk));
+ buf.Append(DataSeparator);
+ buf.Append(s.maxk);
+ buf.Append(DataSeparator);
+ buf.Append(s.numBacktrackOccurrences);
+ buf.Append(DataSeparator);
+ buf.Append(s.numSemPredEvals);
+ buf.Append(DataSeparator);
+ buf.Append(s.couldBacktrack ? "1" : "0");
+ buf.Append(NewLine);
+ }
+ }
+ return buf.ToString();
+ }
+
+ protected virtual int[] Trim(int[] X, int n)
+ {
+ if (n < X.Length)
+ {
+ int[] trimmed = new int[n];
+ Array.Copy(X, 0, trimmed, 0, n);
+ X = trimmed;
+ }
+ return X;
+ }
+
+ /** Get num hidden tokens between i..j inclusive */
+ public virtual int GetNumberOfHiddenTokens(int i, int j)
+ {
+ int n = 0;
+ ITokenStream input = parser.TokenStream;
+ for (int ti = i; ti < input.Count && ti <= j; ti++)
+ {
+ IToken t = input.Get(ti);
+ if (t.Channel != TokenChannels.Default)
+ {
+ n++;
+ }
+ }
+ return n;
+ }
+
+ protected virtual string LocationDescription()
+ {
+ return LocationDescription(
+ currentGrammarFileName.Peek(),
+ currentRuleName.Peek(),
+ currentLine.Peek(),
+ currentPos.Peek());
+ }
+
+ protected virtual string LocationDescription(string file, string rule, int line, int pos)
+ {
+ return file + ":" + line + ":" + pos + "(" + rule + ")";
+ }
+
+ public class ProfileStats
+ {
+ public string Version;
+ public string name;
+ public int numRuleInvocations;
+ public int numUniqueRulesInvoked;
+ public int numDecisionEvents;
+ public int numDecisionsCovered;
+ public int numDecisionsThatPotentiallyBacktrack;
+ public int numDecisionsThatDoBacktrack;
+ public int maxRuleInvocationDepth;
+ public float avgkPerDecisionEvent;
+ public float avgkPerBacktrackingDecisionEvent;
+ public float averageDecisionPercentBacktracks;
+ public int numBacktrackOccurrences; // doesn't count gated DFA edges
+
+ public int numFixedDecisions;
+ public int minDecisionMaxFixedLookaheads;
+ public int maxDecisionMaxFixedLookaheads;
+ public int avgDecisionMaxFixedLookaheads;
+ public int stddevDecisionMaxFixedLookaheads;
+ public int numCyclicDecisions;
+ public int minDecisionMaxCyclicLookaheads;
+ public int maxDecisionMaxCyclicLookaheads;
+ public int avgDecisionMaxCyclicLookaheads;
+ public int stddevDecisionMaxCyclicLookaheads;
+ // int Stats.min(toArray(decisionMaxSynPredLookaheads);
+ // int Stats.max(toArray(decisionMaxSynPredLookaheads);
+ // int Stats.avg(toArray(decisionMaxSynPredLookaheads);
+ // int Stats.stddev(toArray(decisionMaxSynPredLookaheads);
+ public int numSemanticPredicates;
+ public int numTokens;
+ public int numHiddenTokens;
+ public int numCharsMatched;
+ public int numHiddenCharsMatched;
+ public int numReportedErrors;
+ public int numMemoizationCacheHits;
+ public int numMemoizationCacheMisses;
+ public int numGuessingRuleInvocations;
+ public int numMemoizationCacheEntries;
+ }
+
+ public class DecisionDescriptor
+ {
+ public int decision;
+ public string fileName;
+ public string ruleName;
+ public int line;
+ public int pos;
+ public bool couldBacktrack;
+
+ public int n;
+ public float avgk; // avg across all decision events
+ public int maxk;
+ public int numBacktrackOccurrences;
+ public int numSemPredEvals;
+ }
+
+ // all about a specific exec of a single decision
+ public class DecisionEvent
+ {
+ public DecisionDescriptor decision;
+ public int startIndex;
+ public int k;
+ public bool backtracks; // doesn't count gated DFA edges
+ public bool evalSemPred;
+ public DateTime startTime;
+ public DateTime stopTime;
+ public int numMemoizationCacheHits;
+ public int numMemoizationCacheMisses;
+ }
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Properties/AssemblyInfo.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..b8c988f
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Properties/AssemblyInfo.cs
@@ -0,0 +1,70 @@
+/*
+ * [The "BSD license"]
+ * Copyright (c) 2011 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2011 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Reflection;
+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( "Antlr3.Runtime.Debug" )]
+[assembly: AssemblyDescription( "" )]
+[assembly: AssemblyConfiguration( "" )]
+[assembly: AssemblyCompany( "Pixel Mine, Inc." )]
+[assembly: AssemblyProduct( "Antlr3.Runtime.Debug" )]
+[assembly: AssemblyCopyright( "Copyright © Pixel Mine 2010" )]
+[assembly: AssemblyTrademark( "" )]
+[assembly: AssemblyCulture( "" )]
+[assembly: CLSCompliant( true )]
+
+// 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( "9f8fa018-6766-404c-9e72-551407e1b173" )]
+
+/* Version information for an assembly consists of four values in the following order:
+ *
+ * Major.Minor.Build.Revision
+ *
+ * These values are updated according to the following:
+ * 1. Major.Minor follows the ANTLR release schedule
+ * 2. Build is incremented each time the C# port is packaged for release (regardless
+ * of whether it's an incremental or nightly). The value resets to zero whenever
+ * the Major or Minor version is incremented.
+ * 3. Revision is the Perforce changelist number associated with the release.
+ */
+[assembly: AssemblyVersion("3.3.4.8517")]
+[assembly: AssemblyFileVersion("3.3.4.8517")]
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs
new file mode 100644
index 0000000..e390065
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/RemoteDebugEventSocketListener.cs
@@ -0,0 +1,744 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using Antlr.Runtime.JavaExtensions;
+
+ using Array = System.Array;
+ using BaseTree = Antlr.Runtime.Tree.BaseTree;
+ using Console = System.Console;
+ using Exception = System.Exception;
+ using IOException = System.IO.IOException;
+ using ITree = Antlr.Runtime.Tree.ITree;
+ using Math = System.Math;
+ using Socket = System.Net.Sockets.Socket;
+ using SocketException = System.Net.Sockets.SocketException;
+ using TextReader = System.IO.TextReader;
+ using TextWriter = System.IO.TextWriter;
+
+ public class RemoteDebugEventSocketListener
+ {
+ const int MAX_EVENT_ELEMENTS = 8;
+ IDebugEventListener listener;
+ string machine;
+ int port;
+ Socket channel = null;
+ TextWriter @out;
+ TextReader @in;
+ string @event;
+ /** <summary>Version of ANTLR (dictates events)</summary> */
+ public string version;
+ public string grammarFileName;
+ /** <summary>
+ * Track the last token index we saw during a consume. If same, then
+ * set a flag that we have a problem.
+ * </summary>
+ */
+ int previousTokenIndex = -1;
+ bool tokenIndexesInvalid = false;
+
+ public class ProxyToken : IToken
+ {
+ int index;
+ int type;
+ int channel;
+ int line;
+ int charPos;
+ string text;
+ public ProxyToken( int index )
+ {
+ this.index = index;
+ }
+ public ProxyToken( int index, int type, int channel,
+ int line, int charPos, string text )
+ {
+ this.index = index;
+ this.type = type;
+ this.channel = channel;
+ this.line = line;
+ this.charPos = charPos;
+ this.text = text;
+ }
+
+ #region IToken Members
+ public string Text
+ {
+ get
+ {
+ return text;
+ }
+ set
+ {
+ text = value;
+ }
+ }
+
+ public int Type
+ {
+ get
+ {
+ return type;
+ }
+ set
+ {
+ type = value;
+ }
+ }
+
+ public int Line
+ {
+ get
+ {
+ return line;
+ }
+ set
+ {
+ line = value;
+ }
+ }
+
+ public int CharPositionInLine
+ {
+ get
+ {
+ return charPos;
+ }
+ set
+ {
+ charPos = value;
+ }
+ }
+
+ public int Channel
+ {
+ get
+ {
+ return channel;
+ }
+ set
+ {
+ channel = value;
+ }
+ }
+
+ public int StartIndex
+ {
+ get
+ {
+ return -1;
+ }
+ set
+ {
+ }
+ }
+
+ public int StopIndex
+ {
+ get
+ {
+ return -1;
+ }
+ set
+ {
+ }
+ }
+
+ public int TokenIndex
+ {
+ get
+ {
+ return index;
+ }
+ set
+ {
+ index = value;
+ }
+ }
+
+ public ICharStream InputStream
+ {
+ get
+ {
+ return null;
+ }
+ set
+ {
+ }
+ }
+
+ #endregion
+
+ public override string ToString()
+ {
+ string channelStr = "";
+ if ( channel != TokenChannels.Default )
+ {
+ channelStr = ",channel=" + channel;
+ }
+ return "[" + Text + "/<" + type + ">" + channelStr + "," + line + ":" + CharPositionInLine + ",@" + index + "]";
+ }
+ }
+
+ public class ProxyTree : BaseTree
+ {
+ public int ID;
+ int type;
+ int line = 0;
+ public int charPos = -1;
+ public int tokenIndex = -1;
+ string text;
+
+ public ProxyTree( int ID, int type, int line, int charPos, int tokenIndex, string text )
+ {
+ this.ID = ID;
+ this.type = type;
+ this.line = line;
+ this.charPos = charPos;
+ this.tokenIndex = tokenIndex;
+ this.text = text;
+ }
+
+ public ProxyTree( int ID )
+ {
+ this.ID = ID;
+ }
+
+ #region Properties
+ public override string Text
+ {
+ get
+ {
+ return text;
+ }
+ set
+ {
+ }
+ }
+ public override int TokenStartIndex
+ {
+ get
+ {
+ return tokenIndex;
+ }
+ set
+ {
+ }
+ }
+ public override int TokenStopIndex
+ {
+ get
+ {
+ return 0;
+ }
+ set
+ {
+ }
+ }
+ public override int Type
+ {
+ get
+ {
+ return type;
+ }
+ set
+ {
+ }
+ }
+ #endregion
+
+ public override ITree DupNode()
+ {
+ return null;
+ }
+
+ public override string ToString()
+ {
+ return "fix this";
+ }
+ }
+
+ public RemoteDebugEventSocketListener( IDebugEventListener listener,
+ string machine,
+ int port )
+ {
+ this.listener = listener;
+ this.machine = machine;
+ this.port = port;
+
+ if ( !OpenConnection() )
+ {
+ throw new SocketException();
+ }
+ }
+
+ protected virtual void EventHandler()
+ {
+ try
+ {
+ Handshake();
+ @event = @in.ReadLine();
+ while ( @event != null )
+ {
+ Dispatch( @event );
+ Ack();
+ @event = @in.ReadLine();
+ }
+ }
+ catch ( Exception e )
+ {
+ Console.Error.WriteLine( e );
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+ finally
+ {
+ CloseConnection();
+ }
+ }
+
+ protected virtual bool OpenConnection()
+ {
+ bool success = false;
+ try
+ {
+ throw new System.NotImplementedException();
+ //channel = new Socket( machine, port );
+ //channel.setTcpNoDelay( true );
+ //OutputStream os = channel.getOutputStream();
+ //OutputStreamWriter osw = new OutputStreamWriter( os, "UTF8" );
+ //@out = new PrintWriter( new BufferedWriter( osw ) );
+ //InputStream @is = channel.getInputStream();
+ //InputStreamReader isr = new InputStreamReader( @is, "UTF8" );
+ //@in = new BufferedReader( isr );
+ //success = true;
+ }
+ catch ( Exception e )
+ {
+ Console.Error.WriteLine( e );
+ }
+ return success;
+ }
+
+ protected virtual void CloseConnection()
+ {
+ try
+ {
+ @in.Close();
+ @in = null;
+ @out.Close();
+ @out = null;
+ channel.Close();
+ channel = null;
+ }
+ catch ( Exception e )
+ {
+ Console.Error.WriteLine( e );
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+ finally
+ {
+ if ( @in != null )
+ {
+ try
+ {
+ @in.Close();
+ }
+ catch ( IOException ioe )
+ {
+ Console.Error.WriteLine( ioe );
+ }
+ }
+ if ( @out != null )
+ {
+ @out.Close();
+ }
+ if ( channel != null )
+ {
+ try
+ {
+ channel.Close();
+ }
+ catch ( IOException ioe )
+ {
+ Console.Error.WriteLine( ioe );
+ }
+ }
+ }
+
+ }
+
+ protected virtual void Handshake()
+ {
+ string antlrLine = @in.ReadLine();
+ string[] antlrElements = GetEventElements( antlrLine );
+ version = antlrElements[1];
+ string grammarLine = @in.ReadLine();
+ string[] grammarElements = GetEventElements( grammarLine );
+ grammarFileName = grammarElements[1];
+ Ack();
+ listener.Commence(); // inform listener after handshake
+ }
+
+ protected virtual void Ack()
+ {
+ @out.WriteLine( "ack" );
+ @out.Flush();
+ }
+
+ protected virtual void Dispatch( string line )
+ {
+ //JSystem.@out.println( "event: " + line );
+ string[] elements = GetEventElements( line );
+ if ( elements == null || elements[0] == null )
+ {
+ Console.Error.WriteLine( "unknown debug event: " + line );
+ return;
+ }
+ if ( elements[0].Equals( "enterRule" ) )
+ {
+ listener.EnterRule( elements[1], elements[2] );
+ }
+ else if ( elements[0].Equals( "exitRule" ) )
+ {
+ listener.ExitRule( elements[1], elements[2] );
+ }
+ else if ( elements[0].Equals( "enterAlt" ) )
+ {
+ listener.EnterAlt( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "enterSubRule" ) )
+ {
+ listener.EnterSubRule( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "exitSubRule" ) )
+ {
+ listener.ExitSubRule( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "enterDecision" ) )
+ {
+ listener.EnterDecision(int.Parse(elements[1]), elements[2].Equals("true"));
+ }
+ else if ( elements[0].Equals( "exitDecision" ) )
+ {
+ listener.ExitDecision( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "location" ) )
+ {
+ listener.Location( int.Parse( elements[1] ),
+ int.Parse( elements[2] ) );
+ }
+ else if ( elements[0].Equals( "consumeToken" ) )
+ {
+ ProxyToken t = DeserializeToken( elements, 1 );
+ if ( t.TokenIndex == previousTokenIndex )
+ {
+ tokenIndexesInvalid = true;
+ }
+ previousTokenIndex = t.TokenIndex;
+ listener.ConsumeToken( t );
+ }
+ else if ( elements[0].Equals( "consumeHiddenToken" ) )
+ {
+ ProxyToken t = DeserializeToken( elements, 1 );
+ if ( t.TokenIndex == previousTokenIndex )
+ {
+ tokenIndexesInvalid = true;
+ }
+ previousTokenIndex = t.TokenIndex;
+ listener.ConsumeHiddenToken( t );
+ }
+ else if ( elements[0].Equals( "LT" ) )
+ {
+ IToken t = DeserializeToken( elements, 2 );
+ listener.LT( int.Parse( elements[1] ), t );
+ }
+ else if ( elements[0].Equals( "mark" ) )
+ {
+ listener.Mark( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "rewind" ) )
+ {
+ if ( elements[1] != null )
+ {
+ listener.Rewind( int.Parse( elements[1] ) );
+ }
+ else
+ {
+ listener.Rewind();
+ }
+ }
+ else if ( elements[0].Equals( "beginBacktrack" ) )
+ {
+ listener.BeginBacktrack( int.Parse( elements[1] ) );
+ }
+ else if ( elements[0].Equals( "endBacktrack" ) )
+ {
+ int level = int.Parse( elements[1] );
+ int successI = int.Parse( elements[2] );
+ listener.EndBacktrack( level, successI == DebugEventListenerConstants.True );
+ }
+ else if ( elements[0].Equals( "exception" ) )
+ {
+#if true
+ throw new System.NotImplementedException();
+#else
+ string excName = elements[1];
+ string indexS = elements[2];
+ string lineS = elements[3];
+ string posS = elements[4];
+ Class excClass = null;
+ try
+ {
+ excClass = Class.forName( excName );
+ RecognitionException e =
+ (RecognitionException)excClass.newInstance();
+ e.index = int.Parse( indexS );
+ e.line = int.Parse( lineS );
+ e.charPositionInLine = int.Parse( posS );
+ listener.recognitionException( e );
+ }
+ catch ( ClassNotFoundException cnfe )
+ {
+ Console.Error.println( "can't find class " + cnfe );
+ cnfe.printStackTrace( Console.Error );
+ }
+ catch ( InstantiationException ie )
+ {
+ Console.Error.println( "can't instantiate class " + ie );
+ ie.printStackTrace( Console.Error );
+ }
+ catch ( IllegalAccessException iae )
+ {
+ Console.Error.println( "can't access class " + iae );
+ iae.printStackTrace( Console.Error );
+ }
+#endif
+ }
+ else if ( elements[0].Equals( "beginResync" ) )
+ {
+ listener.BeginResync();
+ }
+ else if ( elements[0].Equals( "endResync" ) )
+ {
+ listener.EndResync();
+ }
+ else if ( elements[0].Equals( "terminate" ) )
+ {
+ listener.Terminate();
+ }
+ else if ( elements[0].Equals( "semanticPredicate" ) )
+ {
+ bool result = bool.Parse( elements[1] );
+ string predicateText = elements[2];
+ predicateText = UnEscapeNewlines( predicateText );
+ listener.SemanticPredicate( result,
+ predicateText );
+ }
+ else if ( elements[0].Equals( "consumeNode" ) )
+ {
+ ProxyTree node = DeserializeNode( elements, 1 );
+ listener.ConsumeNode( node );
+ }
+ else if ( elements[0].Equals( "LN" ) )
+ {
+ int i = int.Parse( elements[1] );
+ ProxyTree node = DeserializeNode( elements, 2 );
+ listener.LT( i, node );
+ }
+ else if ( elements[0].Equals( "createNodeFromTokenElements" ) )
+ {
+ int ID = int.Parse( elements[1] );
+ int type = int.Parse( elements[2] );
+ string text = elements[3];
+ text = UnEscapeNewlines( text );
+ ProxyTree node = new ProxyTree( ID, type, -1, -1, -1, text );
+ listener.CreateNode( node );
+ }
+ else if ( elements[0].Equals( "createNode" ) )
+ {
+ int ID = int.Parse( elements[1] );
+ int tokenIndex = int.Parse( elements[2] );
+ // create dummy node/token filled with ID, tokenIndex
+ ProxyTree node = new ProxyTree( ID );
+ ProxyToken token = new ProxyToken( tokenIndex );
+ listener.CreateNode( node, token );
+ }
+ else if ( elements[0].Equals( "nilNode" ) )
+ {
+ int ID = int.Parse( elements[1] );
+ ProxyTree node = new ProxyTree( ID );
+ listener.NilNode( node );
+ }
+ else if ( elements[0].Equals( "errorNode" ) )
+ {
+ // TODO: do we need a special tree here?
+ int ID = int.Parse( elements[1] );
+ int type = int.Parse( elements[2] );
+ string text = elements[3];
+ text = UnEscapeNewlines( text );
+ ProxyTree node = new ProxyTree( ID, type, -1, -1, -1, text );
+ listener.ErrorNode( node );
+ }
+ else if ( elements[0].Equals( "becomeRoot" ) )
+ {
+ int newRootID = int.Parse( elements[1] );
+ int oldRootID = int.Parse( elements[2] );
+ ProxyTree newRoot = new ProxyTree( newRootID );
+ ProxyTree oldRoot = new ProxyTree( oldRootID );
+ listener.BecomeRoot( newRoot, oldRoot );
+ }
+ else if ( elements[0].Equals( "addChild" ) )
+ {
+ int rootID = int.Parse( elements[1] );
+ int childID = int.Parse( elements[2] );
+ ProxyTree root = new ProxyTree( rootID );
+ ProxyTree child = new ProxyTree( childID );
+ listener.AddChild( root, child );
+ }
+ else if ( elements[0].Equals( "setTokenBoundaries" ) )
+ {
+ int ID = int.Parse( elements[1] );
+ ProxyTree node = new ProxyTree( ID );
+ listener.SetTokenBoundaries(
+ node,
+ int.Parse( elements[2] ),
+ int.Parse( elements[3] ) );
+ }
+ else
+ {
+ Console.Error.WriteLine( "unknown debug event: " + line );
+ }
+ }
+
+ protected virtual ProxyTree DeserializeNode( string[] elements, int offset )
+ {
+ int ID = int.Parse( elements[offset + 0] );
+ int type = int.Parse( elements[offset + 1] );
+ int tokenLine = int.Parse( elements[offset + 2] );
+ int charPositionInLine = int.Parse( elements[offset + 3] );
+ int tokenIndex = int.Parse( elements[offset + 4] );
+ string text = elements[offset + 5];
+ text = UnEscapeNewlines( text );
+ return new ProxyTree( ID, type, tokenLine, charPositionInLine, tokenIndex, text );
+ }
+
+ protected virtual ProxyToken DeserializeToken( string[] elements,
+ int offset )
+ {
+ string indexS = elements[offset + 0];
+ string typeS = elements[offset + 1];
+ string channelS = elements[offset + 2];
+ string lineS = elements[offset + 3];
+ string posS = elements[offset + 4];
+ string text = elements[offset + 5];
+ text = UnEscapeNewlines( text );
+ int index = int.Parse( indexS );
+ ProxyToken t =
+ new ProxyToken( index,
+ int.Parse( typeS ),
+ int.Parse( channelS ),
+ int.Parse( lineS ),
+ int.Parse( posS ),
+ text );
+ return t;
+ }
+
+ /** <summary>Create a thread to listen to the remote running recognizer</summary> */
+ public virtual void Start()
+ {
+ System.Threading.Thread t = new System.Threading.Thread( Run );
+ t.Start();
+ }
+
+ public virtual void Run()
+ {
+ EventHandler();
+ }
+
+ #region Misc
+
+ public virtual string[] GetEventElements( string @event )
+ {
+ if ( @event == null )
+ {
+ return null;
+ }
+ string[] elements = new string[MAX_EVENT_ELEMENTS];
+ string str = null; // a string element if present (must be last)
+ try
+ {
+ int firstQuoteIndex = @event.IndexOf( '"' );
+ if ( firstQuoteIndex >= 0 )
+ {
+ // treat specially; has a string argument like "a comment\n
+ // Note that the string is terminated by \n not end quote.
+ // Easier to parse that way.
+ string eventWithoutString = @event.Substring( 0, firstQuoteIndex );
+ str = @event.Substring( firstQuoteIndex + 1 );
+ @event = eventWithoutString;
+ }
+
+ string[] tokens = @event.Split('\t');
+ Array.Copy(tokens, elements, Math.Min(tokens.Length, MAX_EVENT_ELEMENTS));
+ if (tokens.Length >= MAX_EVENT_ELEMENTS)
+ return elements;
+
+ if ( str != null )
+ {
+ elements[tokens.Length] = str;
+ }
+ }
+ catch ( Exception e )
+ {
+ ExceptionExtensions.PrintStackTrace( e, Console.Error );
+ }
+ return elements;
+ }
+
+ protected virtual string UnEscapeNewlines( string txt )
+ {
+ // this unescape is slow but easy to understand
+ txt = txt.Replace( "%0A", "\n" ); // unescape \n
+ txt = txt.Replace( "%0D", "\r" ); // unescape \r
+ txt = txt.Replace( "%25", "%" ); // undo escaped escape chars
+ return txt;
+ }
+
+ public virtual bool TokenIndexesAreInvalid()
+ {
+ return tokenIndexesInvalid;
+ }
+
+ #endregion
+
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/TraceDebugEventListener.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/TraceDebugEventListener.cs
new file mode 100644
index 0000000..c71da4f
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/TraceDebugEventListener.cs
@@ -0,0 +1,135 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using Antlr.Runtime.JavaExtensions;
+
+ using Console = System.Console;
+ using ITreeAdaptor = Antlr.Runtime.Tree.ITreeAdaptor;
+
+ /** <summary>Print out (most of) the events... Useful for debugging, testing...</summary> */
+ public class TraceDebugEventListener : BlankDebugEventListener
+ {
+ ITreeAdaptor adaptor;
+
+ public TraceDebugEventListener( ITreeAdaptor adaptor )
+ {
+ this.adaptor = adaptor;
+ }
+
+ public void EnterRule( string ruleName )
+ {
+ Console.Out.WriteLine( "enterRule " + ruleName );
+ }
+ public void ExitRule( string ruleName )
+ {
+ Console.Out.WriteLine( "exitRule " + ruleName );
+ }
+ public override void EnterSubRule( int decisionNumber )
+ {
+ Console.Out.WriteLine( "enterSubRule" );
+ }
+ public override void ExitSubRule( int decisionNumber )
+ {
+ Console.Out.WriteLine( "exitSubRule" );
+ }
+ public override void Location( int line, int pos )
+ {
+ Console.Out.WriteLine( "location " + line + ":" + pos );
+ }
+
+ #region Tree parsing stuff
+
+ public override void ConsumeNode( object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ string text = adaptor.GetText( t );
+ int type = adaptor.GetType( t );
+ Console.Out.WriteLine( "consumeNode " + ID + " " + text + " " + type );
+ }
+
+ public override void LT( int i, object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ string text = adaptor.GetText( t );
+ int type = adaptor.GetType( t );
+ Console.Out.WriteLine( "LT " + i + " " + ID + " " + text + " " + type );
+ }
+
+ #endregion
+
+
+ #region AST stuff
+
+ public override void NilNode( object t )
+ {
+ Console.Out.WriteLine( "nilNode " + adaptor.GetUniqueID( t ) );
+ }
+
+ public override void CreateNode( object t )
+ {
+ int ID = adaptor.GetUniqueID( t );
+ string text = adaptor.GetText( t );
+ int type = adaptor.GetType( t );
+ Console.Out.WriteLine( "create " + ID + ": " + text + ", " + type );
+ }
+
+ public override void CreateNode( object node, IToken token )
+ {
+ int ID = adaptor.GetUniqueID( node );
+ string text = adaptor.GetText( node );
+ int tokenIndex = token.TokenIndex;
+ Console.Out.WriteLine( "create " + ID + ": " + tokenIndex );
+ }
+
+ public override void BecomeRoot( object newRoot, object oldRoot )
+ {
+ Console.Out.WriteLine( "becomeRoot " + adaptor.GetUniqueID( newRoot ) + ", " +
+ adaptor.GetUniqueID( oldRoot ) );
+ }
+
+ public override void AddChild( object root, object child )
+ {
+ Console.Out.WriteLine( "addChild " + adaptor.GetUniqueID( root ) + ", " +
+ adaptor.GetUniqueID( child ) );
+ }
+
+ public override void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex )
+ {
+ Console.Out.WriteLine( "setTokenBoundaries " + adaptor.GetUniqueID( t ) + ", " +
+ tokenStartIndex + ", " + tokenStopIndex );
+ }
+
+ #endregion
+ }
+}
diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Tracer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Tracer.cs
new file mode 100644
index 0000000..c99d4f7
--- /dev/null
+++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/Tracer.cs
@@ -0,0 +1,85 @@
+/*
+ * [The "BSD licence"]
+ * Copyright (c) 2005-2008 Terence Parr
+ * All rights reserved.
+ *
+ * Conversion to C#:
+ * Copyright (c) 2008-2009 Sam Harwell, Pixel Mine, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+namespace Antlr.Runtime.Debug
+{
+ using Antlr.Runtime.JavaExtensions;
+
+ using Console = System.Console;
+
+ /** <summary>
+ * The default tracer mimics the traceParser behavior of ANTLR 2.x.
+ * This listens for debugging events from the parser and implies
+ * that you cannot debug and trace at the same time.
+ * </summary>
+ */
+ public class Tracer : BlankDebugEventListener
+ {
+ public IIntStream input;
+ protected int level = 0;
+
+ public Tracer( IIntStream input )
+ {
+ this.input = input;
+ }
+
+ public virtual void EnterRule( string ruleName )
+ {
+ for ( int i = 1; i <= level; i++ )
+ {
+ Console.Out.Write( " " );
+ }
+ Console.Out.WriteLine( "> " + ruleName + " lookahead(1)=" + GetInputSymbol( 1 ) );
+ level++;
+ }
+
+ public virtual void ExitRule( string ruleName )
+ {
+ level--;
+ for ( int i = 1; i <= level; i++ )
+ {
+ Console.Out.Write( " " );
+ }
+ Console.Out.WriteLine( "< " + ruleName + " lookahead(1)=" + GetInputSymbol( 1 ) );
+ }
+
+ public virtual object GetInputSymbol( int k )
+ {
+ if ( input is ITokenStream )
+ {
+ return ( (ITokenStream)input ).LT( k );
+ }
+ return (char)input.LA( k );
+ }
+ }
+}
+