diff options
Diffstat (limited to 'runtime/CSharp3/Sources/Antlr3.Runtime.Debug')
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 "-> ^(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 <unknown> 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 ); + } + } +} + |