diff options
Diffstat (limited to 'runtime/CSharp3/Sources')
186 files changed, 33333 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 ); + } + } +} + diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Antlr3.Runtime.JavaExtensions.csproj b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Antlr3.Runtime.JavaExtensions.csproj new file mode 100644 index 0000000..959a9f9 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Antlr3.Runtime.JavaExtensions.csproj @@ -0,0 +1,95 @@ +<?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>{A7EEC557-EB14-451C-9616-B7A61F4ECE69}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Antlr3.Runtime.JavaExtensions</RootNamespace> + <AssemblyName>Antlr3.Runtime.JavaExtensions</AssemblyName> + <TargetFrameworkVersion>v3.5</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <SccProjectName>SAK</SccProjectName> + <SccLocalPath>SAK</SccLocalPath> + <SccAuxPath>SAK</SccAuxPath> + <SccProvider>SAK</SccProvider> + <TargetFrameworkProfile>Client</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> + <PropertyGroup> + <SignAssembly>true</SignAssembly> + </PropertyGroup> + <PropertyGroup> + <AssemblyOriginatorKeyFile>..\..\..\..\..\..\..\keys\antlr\Key.snk</AssemblyOriginatorKeyFile> + </PropertyGroup> + <ItemGroup> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Xml.Linq"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data.DataSetExtensions"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="System.Data" /> + <Reference Include="System.Xml" /> + </ItemGroup> + <ItemGroup> + <Compile Include="DictionaryExtensions.cs" /> + <Compile Include="ExceptionExtensions.cs" /> + <Compile Include="IOExtensions.cs" /> + <Compile Include="LexerExtensions.cs" /> + <Compile Include="JSystem.cs" /> + <Compile Include="ListExtensions.cs" /> + <Compile Include="ObjectExtensions.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="SetExtensions.cs" /> + <Compile Include="StackExtensions.cs" /> + <Compile Include="StringBuilderExtensions.cs" /> + <Compile Include="StringExtensions.cs" /> + <Compile Include="StringTokenizer.cs" /> + <Compile Include="SubList.cs" /> + <Compile Include="TreeExtensions.cs" /> + <Compile Include="TypeExtensions.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\Antlr3.Runtime\Antlr3.Runtime.csproj"> + <Project>{8FDC0A87-9005-4D5A-AB75-E55CEB575559}</Project> + <Name>Antlr3.Runtime</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <None Include="..\..\..\..\..\..\..\keys\antlr\Key.snk"> + <Link>Key.snk</Link> + </None> + </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.JavaExtensions/Antlr3.Runtime.JavaExtensions.csproj.vspscc b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Antlr3.Runtime.JavaExtensions.csproj.vspscc new file mode 100644 index 0000000..b27adcc --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Antlr3.Runtime.JavaExtensions.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "relative:antlr\\main\\runtime\\CSharp3\\Sources\\Antlr3.Runtime.JavaExtensions" +"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.JavaExtensions/DictionaryExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/DictionaryExtensions.cs new file mode 100644 index 0000000..cd32ce9 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/DictionaryExtensions.cs @@ -0,0 +1,135 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 System.Collections.Generic; + using System.Linq; + + using IDictionary = System.Collections.IDictionary; + using ObsoleteAttribute = System.ObsoleteAttribute; + + public static class DictionaryExtensions + { + [Obsolete] + public static bool containsKey( this IDictionary map, object key ) + { + return map.Contains( key ); + } + + [Obsolete] + public static object get( this IDictionary map, object key ) + { + return map[key]; + } + + public static TValue get<TKey, TValue>( this IDictionary<TKey, TValue> map, TKey key ) + { + TValue value; + if ( map.TryGetValue( key, out value ) ) + return value; + + if ( typeof( TValue ).IsValueType ) + throw new KeyNotFoundException(); + + return default( TValue ); + } + + // disambiguates + public static TValue get<TKey, TValue>( this Dictionary<TKey, TValue> map, TKey key ) + { + TValue value; + if ( map.TryGetValue( key, out value ) ) + return value; + + if ( typeof( TValue ).IsValueType ) + throw new KeyNotFoundException(); + + return default( TValue ); + } + + public static TValue get<TKey, TValue>( this SortedList<TKey, TValue> map, TKey key ) + { + TValue value; + if ( map.TryGetValue( key, out value ) ) + return value; + + if ( typeof( TValue ).IsValueType ) + throw new KeyNotFoundException(); + + return default( TValue ); + } + + [Obsolete] + public static void put( this IDictionary map, object key, object value ) + { + map[key] = value; + } + + [Obsolete] + public static void put<TKey, TValue>( this IDictionary<TKey, TValue> map, TKey key, TValue value ) + { + map[key] = value; + } + + [Obsolete] + public static void put<TKey, TValue>( this Dictionary<TKey, TValue> map, TKey key, TValue value ) + { + map[key] = value; + } + + [Obsolete] + public static HashSet<object> keySet( this IDictionary map ) + { + return new HashSet<object>( map.Keys.Cast<object>() ); + } + + [Obsolete] + public static HashSet<TKey> keySet<TKey, TValue>( this IDictionary<TKey, TValue> map ) + { + return new HashSet<TKey>( map.Keys ); + } + + // disambiguates for Dictionary, which implements both IDictionary<T,K> and IDictionary + [Obsolete] + public static HashSet<TKey> keySet<TKey, TValue>( this Dictionary<TKey, TValue> map ) + { + return new HashSet<TKey>( map.Keys ); + } + + [Obsolete] + public static HashSet<object> keySet<TKey, TValue>( this SortedList<TKey, TValue> map ) + { + return new HashSet<object>( map.Keys.Cast<object>() ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ExceptionExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ExceptionExtensions.cs new file mode 100644 index 0000000..65696c8 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ExceptionExtensions.cs @@ -0,0 +1,100 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Diagnostics; +using System.Linq; + +using TargetInvocationException = System.Reflection.TargetInvocationException; + +namespace Antlr.Runtime.JavaExtensions +{ + public static class ExceptionExtensions + { +#if DEBUG + [Obsolete] + public static string getMessage( this Exception e ) + { + return e.Message; + } +#endif + + public static StackFrame[] getStackTrace( this Exception e ) + { + StackTrace trace = new StackTrace( e, true ); + StackFrame[] frames = trace.GetFrames(); + if ( frames == null ) + { + // don't include this helper function in the trace + frames = new StackTrace( true ).GetFrames().Skip( 1 ).ToArray(); + } + return frames; + } + +#if DEBUG + [Obsolete] + public static string getMethodName( this StackFrame frame ) + { + return frame.GetMethod().Name; + } + + [Obsolete] + public static string getClassName( this StackFrame frame ) + { + return frame.GetMethod().DeclaringType.Name; + } +#endif + + public static void PrintStackTrace( this Exception e ) + { + e.PrintStackTrace( Console.Out ); + } + public static void PrintStackTrace( this Exception e, System.IO.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 ); + } + } + +#if DEBUG + [Obsolete] + public static Exception getTargetException( this TargetInvocationException e ) + { + return e.InnerException ?? e; + } +#endif + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/IOExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/IOExtensions.cs new file mode 100644 index 0000000..52b529c --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/IOExtensions.cs @@ -0,0 +1,90 @@ +/* + * [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.JavaExtensions +{ + using System; + + using TextReader = System.IO.TextReader; + using TextWriter = System.IO.TextWriter; + + public static class IOExtensions + { + [Obsolete] + public static void close( this TextReader reader ) + { + reader.Close(); + } + + [Obsolete] + public static void close( this TextWriter writer ) + { + writer.Close(); + } + + [Obsolete] + public static void print<T>( this TextWriter writer, T value ) + { + writer.Write( value ); + } + + [Obsolete] + public static void println( this TextWriter writer ) + { + writer.WriteLine(); + } + + [Obsolete] + public static void println<T>( this TextWriter writer, T value ) + { + writer.WriteLine( value ); + } + + [Obsolete] + public static void write<T>( this TextWriter writer, T value ) + { + writer.Write( value ); + } + + [Obsolete] + public static int read( this TextReader reader, char[] buffer, int index, int count ) + { + return reader.Read( buffer, index, count ); + } + + [Obsolete] + public static string readLine( this TextReader reader ) + { + return reader.ReadLine(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/JSystem.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/JSystem.cs new file mode 100644 index 0000000..1574937 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/JSystem.cs @@ -0,0 +1,87 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 System; + using System.IO; + + public static class JSystem + { + [Obsolete] + public static TextWriter err + { + get + { + return Console.Error; + } + } + + [Obsolete] + public static TextWriter @out + { + get + { + return Console.Out; + } + } + + [Obsolete] + public static void arraycopy<T>( T[] sourceArray, int sourceIndex, T[] destinationArray, int destinationIndex, int length ) + { + Array.Copy( sourceArray, sourceIndex, destinationArray, destinationIndex, length ); + } + + [Obsolete] + public static string getProperty( string name ) + { + switch ( name ) + { + case "file.encoding": + return System.Text.Encoding.Default.WebName; + + case "line.separator": + return Environment.NewLine; + + case "java.io.tmpdir": + return System.IO.Path.GetTempPath(); + + case "user.home": + return Environment.GetFolderPath( Environment.SpecialFolder.Personal ); + + default: + throw new ArgumentException( string.Format( "Unknown system property: '{0}'", name ) ); + } + } + + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/LexerExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/LexerExtensions.cs new file mode 100644 index 0000000..4300b38 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/LexerExtensions.cs @@ -0,0 +1,42 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + public static class LexerExtensions + { + public static void skip( this Lexer lexer ) + { + lexer.Skip(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ListExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ListExtensions.cs new file mode 100644 index 0000000..51c16bc --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ListExtensions.cs @@ -0,0 +1,237 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Collections.Generic; +using System.Linq; + +using ICollection = System.Collections.ICollection; +using IEnumerable = System.Collections.IEnumerable; +using IList = System.Collections.IList; + +namespace Antlr.Runtime.JavaExtensions +{ + public static class ListExtensions + { +#if DEBUG + [Obsolete] + public static bool add( this IList list, object value ) + { + int count = list.Count; + list.Add( value ); + return list.Count == count + 1; + } + + [Obsolete] + public static void add<T>( this ICollection<T> list, T value ) + { + list.Add( value ); + } + + [Obsolete] + public static void add<T>( this List<T> list, T value ) + { + list.Add( value ); + } + + [Obsolete] + public static void add( this IList list, int index, object value ) + { + list.Insert( index, value ); + } + + [Obsolete] + public static void addAll( this List<object> list, IEnumerable items ) + { + list.AddRange( items.Cast<object>() ); + } +#endif + + public static void addAll( this IList list, IEnumerable items ) + { + foreach ( object item in items ) + list.Add( item ); + } + + public static void addAll<T>( this ICollection<T> list, IEnumerable<T> items ) + { + foreach ( T item in items ) + list.Add( item ); + } + +#if DEBUG + [Obsolete] + public static void addElement( this List<object> list, object value ) + { + list.Add( value ); + } + + [Obsolete] + public static void clear( this IList list ) + { + list.Clear(); + } + + [Obsolete] + public static bool contains( this IList list, object value ) + { + return list.Contains( value ); + } + + [Obsolete] + public static bool contains<T>( this ICollection<T> list, T value ) + { + return list.Contains( value ); + } + + [Obsolete] + public static T elementAt<T>( this IList<T> list, int index ) + { + return list[index]; + } + + [Obsolete] + public static object get( this IList list, int index ) + { + return list[index]; + } + + [Obsolete] + public static T get<T>( this IList<T> list, int index ) + { + return list[index]; + } + + // disambiguate + [Obsolete] + public static T get<T>( this List<T> list, int index ) + { + return list[index]; + } + + [Obsolete] + public static object remove( this IList list, int index ) + { + object o = list[index]; + list.RemoveAt( index ); + return o; + } + + [Obsolete] + public static void remove<T>( this IList<T> list, T item ) + { + list.Remove( item ); + } + + [Obsolete] + public static void set( this IList list, int index, object value ) + { + list[index] = value; + } + + [Obsolete] + public static void set<T>( this IList<T> list, int index, T value ) + { + list[index] = value; + } + + [Obsolete] + public static void set<T>( this List<T> list, int index, T value ) + { + list[index] = value; + } +#endif + + public static void setSize<T>( this List<T> list, int size ) + { + if ( list.Count < size ) + { + list.AddRange( Enumerable.Repeat( default( T ), size - list.Count ) ); + } + else if ( list.Count > size ) + { + list.RemoveRange(size, list.Count - size); + } + } + +#if DEBUG + [Obsolete] + public static int size( this ICollection collection ) + { + return collection.Count; + } + + [Obsolete] + public static int size<T>( this ICollection<T> collection ) + { + return collection.Count; + } + + [Obsolete] + public static int size<T>( this List<T> list ) + { + return list.Count; + } +#endif + + public static IList subList( this IList list, int fromIndex, int toIndex ) + { + return new SubList( list, fromIndex, toIndex ); + //return + // list + // .Cast<object>() + // .Skip( fromIndex ) + // .Take( toIndex - fromIndex + 1 ) + // .ToList(); + } + + public static IList<T> subList<T>( this IList<T> list, int fromIndex, int toIndex ) + { + return new SubList<T>( list, fromIndex, toIndex ); + //return + // list + // .Skip( fromIndex ) + // .Take( toIndex - fromIndex + 1 ) + // .ToList(); + } + + public static IList<T> subList<T>( this List<T> list, int fromIndex, int toIndex ) + { + return new SubList<T>( list, fromIndex, toIndex ); + //return + // list + // .Skip( fromIndex ) + // .Take( toIndex - fromIndex + 1 ) + // .ToList(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ObjectExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ObjectExtensions.cs new file mode 100644 index 0000000..fe6a274 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/ObjectExtensions.cs @@ -0,0 +1,123 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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; + +namespace Antlr.Runtime.JavaExtensions +{ + public static class ObjectExtensions + { +#if DEBUG + [Obsolete] + public static bool booleanValue( this bool value ) + { + return value; + } + + [Obsolete] + public static Type getClass( this object o ) + { + return o.GetType(); + } +#endif + + public static int ShiftPrimeXOR( int a, int b ) + { + int hash = 23; + hash = ( ( hash << 5 ) * 37 ) ^ a; + hash = ( ( hash << 5 ) * 37 ) ^ b; + return hash; + } + + public static int ShiftPrimeXOR( int a, int b, int c ) + { + int hash = 23; + hash = ( ( hash << 5 ) * 37 ) ^ a; + hash = ( ( hash << 5 ) * 37 ) ^ b; + hash = ( ( hash << 5 ) * 37 ) ^ c; + return hash; + } + + public static int ShiftPrimeXOR( int a, int b, int c, int d ) + { + int hash = 23; + hash = ( ( hash << 5 ) * 37 ) ^ a; + hash = ( ( hash << 5 ) * 37 ) ^ b; + hash = ( ( hash << 5 ) * 37 ) ^ c; + hash = ( ( hash << 5 ) * 37 ) ^ d; + return hash; + } + + public static int ShiftPrimeXOR( params int[] a ) + { + int hash = 23; + foreach ( int i in a ) + hash = ( ( hash << 5 ) * 37 ) ^ i; + return hash; + } + + public static int ShiftPrimeAdd( int a, int b ) + { + int hash = 23; + hash = ( ( hash << 5 ) * 37 ) + a; + hash = ( ( hash << 5 ) * 37 ) + b; + return hash; + } + + public static int ShiftPrimeAdd( int a, int b, int c ) + { + int hash = 23; + hash = ( ( hash << 5 ) * 37 ) + a; + hash = ( ( hash << 5 ) * 37 ) + b; + hash = ( ( hash << 5 ) * 37 ) + c; + return hash; + } + + public static int ShiftPrimeAdd( int a, int b, int c, int d ) + { + int hash = 23; + hash = ( ( hash << 5 ) * 37 ) + a; + hash = ( ( hash << 5 ) * 37 ) + b; + hash = ( ( hash << 5 ) * 37 ) + c; + hash = ( ( hash << 5 ) * 37 ) + d; + return hash; + } + + public static int ShiftPrimeAdd( params int[] a ) + { + int hash = 23; + foreach ( int i in a ) + hash = ( ( hash << 5 ) * 37 ) + i; + return hash; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Properties/AssemblyInfo.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..8aa2671 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/Properties/AssemblyInfo.cs @@ -0,0 +1,70 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008-2010 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.JavaExtensions" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "Pixel Mine, Inc." )] +[assembly: AssemblyProduct( "Antlr3.Runtime.JavaExtensions" )] +[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( "ad48c7f7-0b1d-4b1e-9602-83425cb5699f" )] + +/* 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.JavaExtensions/SetExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/SetExtensions.cs new file mode 100644 index 0000000..881326e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/SetExtensions.cs @@ -0,0 +1,89 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Collections.Generic; +#if DEBUG +using System.Linq; +#endif + +namespace Antlr.Runtime.JavaExtensions +{ + public static class SetExtensions + { +#if DEBUG + [Obsolete] + public static bool add<T>( this HashSet<T> set, T item ) + { + return set.Add( item ); + } +#endif + + public static void addAll<T>( this HashSet<T> set, IEnumerable<T> items ) + { + foreach ( T item in items ) + set.Add( item ); + } + +#if DEBUG + [Obsolete] + public static void clear<T>( this HashSet<T> set ) + { + set.Clear(); + } + + [Obsolete] + public static bool contains<T>( this HashSet<T> set, T value ) + { + return set.Contains( value ); + } + + [Obsolete] + public static bool remove<T>( this HashSet<T> set, T item ) + { + return set.Remove( item ); + } + + [Obsolete] + public static int size<T>( this HashSet<T> set ) + { + return set.Count; + } + + [Obsolete] + public static T[] toArray<T>( this HashSet<T> set ) + { + return set.ToArray(); + } +#endif + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StackExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StackExtensions.cs new file mode 100644 index 0000000..ab9ec71 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StackExtensions.cs @@ -0,0 +1,84 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Collections.Generic; +#if DEBUG +using System.Linq; +#endif + +namespace Antlr.Runtime.JavaExtensions +{ + public static class StackExtensions + { +#if DEBUG + [Obsolete] + public static T elementAt<T>( this Stack<T> stack, int index ) + { + return stack.ElementAt( index ); + } + + [Obsolete] + public static T peek<T>( this Stack<T> stack ) + { + return stack.Peek(); + } + + [Obsolete] + public static T pop<T>( this Stack<T> stack ) + { + return stack.Pop(); + } + + [Obsolete] + public static void push<T>( this Stack<T> stack, T obj ) + { + stack.Push( obj ); + } + + [Obsolete] + public static int size<T>( this Stack<T> stack ) + { + return stack.Count; + } +#endif + + public static void setSize<T>( this Stack<T> stack, int size ) + { + if ( size > stack.Count ) + throw new ArgumentException(); + + while ( stack.Count > size ) + stack.Pop(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringBuilderExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringBuilderExtensions.cs new file mode 100644 index 0000000..6ef6f27 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringBuilderExtensions.cs @@ -0,0 +1,75 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 StringBuilder = System.Text.StringBuilder; + +#if DEBUG + +namespace Antlr.Runtime.JavaExtensions +{ + public static class StringBuilderExtensions + { + [Obsolete] + public static void append<T>( this StringBuilder buffer, T value ) + { + buffer.Append( value ); + } + + [Obsolete] + public static char charAt( this StringBuilder buffer, int index ) + { + return buffer[index]; + } + + [Obsolete] + public static int length( this StringBuilder buffer ) + { + return buffer.Length; + } + + [Obsolete] + public static void setCharAt( this StringBuilder buffer, int index, char c ) + { + buffer[index] = c; + } + + [Obsolete] + public static void setLength( this StringBuilder buffer, int length ) + { + buffer.Length = length; + } + } +} + +#endif diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringExtensions.cs new file mode 100644 index 0000000..8432512 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringExtensions.cs @@ -0,0 +1,151 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 ObsoleteAttribute = System.ObsoleteAttribute; + using Regex = System.Text.RegularExpressions.Regex; + using StringBuilder = System.Text.StringBuilder; + + public static class StringExtensions + { +#if DEBUG + [Obsolete] + public static char charAt( this string str, int index ) + { + return str[index]; + } + + [Obsolete] + public static bool endsWith( this string str, string value ) + { + return str.EndsWith( value ); + } + + [Obsolete] + public static int indexOf( this string str, char value ) + { + return str.IndexOf( value ); + } + + [Obsolete] + public static int indexOf( this string str, char value, int startIndex ) + { + return str.IndexOf( value, startIndex ); + } + + [Obsolete] + public static int indexOf( this string str, string value ) + { + return str.IndexOf( value ); + } + + [Obsolete] + public static int indexOf( this string str, string value, int startIndex ) + { + return str.IndexOf( value, startIndex ); + } + + [Obsolete] + public static int lastIndexOf( this string str, char value ) + { + return str.LastIndexOf( value ); + } + + [Obsolete] + public static int lastIndexOf( this string str, string value ) + { + return str.LastIndexOf( value ); + } + + [Obsolete] + public static int length( this string str ) + { + return str.Length; + } + + [Obsolete] + public static string replace(this string str, char oldValue, char newValue) + { + return str.Replace(oldValue, newValue); + } +#endif + + public static string replaceAll( this string str, string regex, string newValue ) + { + return Regex.Replace( str, regex, newValue ); + } + + public static string replaceFirst( this string str, string regex, string replacement ) + { + return Regex.Replace( str, regex, replacement ); + } + +#if DEBUG + [Obsolete] + public static bool startsWith( this string str, string value ) + { + return str.StartsWith( value ); + } + + [Obsolete] + public static string substring( this string str, int startOffset ) + { + return str.Substring( startOffset ); + } + + [Obsolete] + public static string substring(this string str, int startOffset, int endOffset) + { + return str.Substring( startOffset, endOffset - startOffset ); + } + + [Obsolete] + public static char[] toCharArray( this string str ) + { + return str.ToCharArray(); + } + + [Obsolete] + public static string toUpperCase( this string str ) + { + return str.ToUpperInvariant(); + } + + [Obsolete] + public static string trim( this string str ) + { + return str.Trim(); + } +#endif + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringTokenizer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringTokenizer.cs new file mode 100644 index 0000000..0145df5 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/StringTokenizer.cs @@ -0,0 +1,87 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Linq; + +namespace Antlr.Runtime.JavaExtensions +{ + public class StringTokenizer + { + string[] _tokens; + int _current; + + public StringTokenizer( string str, string separator ) + : this( str, separator, false ) + { + } + public StringTokenizer( string str, string separator, bool returnDelims ) + { + _tokens = str.Split( separator.ToCharArray(), StringSplitOptions.None ); + if ( returnDelims ) + { + char[] delims = separator.ToCharArray(); + _tokens = _tokens.SelectMany( ( token, i ) => + { + if ( i == _tokens.Length - 1 ) + { + if ( delims.Contains( str[str.Length - 1] ) ) + return new string[0]; + else + return new string[] { token }; + } + else if ( i == 0 ) + { + if ( delims.Contains( str[0] ) ) + return new string[] { str[0].ToString() }; + else + return new string[] { token }; + } + else + { + return new string[] { token, str[_tokens.Take( i + 1 ).Select( t => t.Length + 1 ).Sum() - 1].ToString() }; + } + } ).ToArray(); + } + } + + public bool hasMoreTokens() + { + return _current < _tokens.Length; + } + + public string nextToken() + { + return _tokens[_current++]; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/SubList.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/SubList.cs new file mode 100644 index 0000000..97025bf --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/SubList.cs @@ -0,0 +1,423 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Collections; + +namespace Antlr.Runtime.JavaExtensions +{ + public class SubList + : IList + { + IList _source; + int _startIndex; + int _endIndex; + + public SubList( IList source, int startIndex, int endIndex ) + { + if ( source == null ) + throw new ArgumentNullException( "source" ); + if ( startIndex < 0 || endIndex < 0 ) + throw new ArgumentOutOfRangeException(); + if ( startIndex > endIndex || endIndex >= source.Count ) + throw new ArgumentException(); + + _source = source; + _startIndex = startIndex; + _endIndex = endIndex; + } + + #region IList Members + + public int Add( object value ) + { + throw new NotSupportedException(); + } + + public void Clear() + { + throw new NotSupportedException(); + } + + public bool Contains( object value ) + { + return _source + .Cast<object>() + .Skip( _startIndex ) + .Take( _endIndex - _startIndex + 1 ) + .Contains( value ); + } + + public int IndexOf( object value ) + { + for ( int i = 0; i < Count; i++ ) + { + if ( object.Equals( this[i], value ) ) + return i; + } + + return -1; + } + + public void Insert( int index, object value ) + { + throw new NotSupportedException(); + } + + public bool IsFixedSize + { + get + { + return true; + } + } + + public bool IsReadOnly + { + get + { + return true; + } + } + + public void Remove( object value ) + { + throw new NotSupportedException(); + } + + public void RemoveAt( int index ) + { + throw new NotSupportedException(); + } + + public object this[int index] + { + get + { + if ( index < 0 || index >= Count ) + throw new ArgumentOutOfRangeException(); + + return _source[index + _startIndex]; + } + set + { + if ( index < 0 || index >= Count ) + throw new ArgumentOutOfRangeException(); + + _source[index + _startIndex] = value; + } + } + + #endregion + + #region ICollection Members + + public void CopyTo( Array array, int index ) + { + if ( array == null ) + throw new ArgumentNullException( "array" ); + + if ( index < 0 ) + throw new ArgumentOutOfRangeException(); + + if ( index + Count > array.Length ) + throw new ArgumentException(); + + for ( int i = 0; i < Count; i++ ) + { + array.SetValue( this[i], index + i ); + } + } + + public int Count + { + get + { + return _endIndex - _startIndex + 1; + } + } + + public bool IsSynchronized + { + get + { + return false; + } + } + + public object SyncRoot + { + get + { + return _source.SyncRoot; + } + } + + #endregion + + #region IEnumerable Members + + public System.Collections.IEnumerator GetEnumerator() + { + return _source.Cast<object>() + .Skip( _startIndex ) + .Take( _endIndex - _startIndex + 1 ) + .GetEnumerator(); + } + + #endregion + } + + public class SubList<T> : IList<T>, ICollection<T>, IEnumerable<T>, IList, ICollection, IEnumerable + { + IList<T> _source; + int _startIndex; + int _endIndex; + + public SubList( IList<T> source, int startIndex, int endIndex ) + { + if ( source == null ) + throw new ArgumentNullException( "source" ); + if ( startIndex < 0 || endIndex < 0 ) + throw new ArgumentOutOfRangeException(); + if ( startIndex > endIndex || endIndex >= source.Count ) + throw new ArgumentException(); + + _source = source; + _startIndex = startIndex; + _endIndex = endIndex; + } + + #region IEnumerable Members + + IEnumerator IEnumerable.GetEnumerator() + { + return GetEnumerator(); + } + + #endregion + + #region ICollection Members + + void ICollection.CopyTo( Array array, int index ) + { + if ( array == null ) + throw new ArgumentNullException( "array" ); + + if ( index < 0 ) + throw new ArgumentOutOfRangeException(); + + if ( index + Count > array.Length ) + throw new ArgumentException(); + + for ( int i = 0; i < Count; i++ ) + { + array.SetValue( this[i], index + i ); + } + } + + public int Count + { + get + { + return _endIndex - _startIndex + 1; + } + } + + public bool IsSynchronized + { + get + { + ICollection sourceCollection = _source as ICollection; + if ( sourceCollection != null ) + return sourceCollection.IsSynchronized; + + return false; + } + } + + public object SyncRoot + { + get + { + ICollection sourceCollection = _source as ICollection; + if ( sourceCollection != null ) + return sourceCollection.SyncRoot; + + return _source; + } + } + + #endregion + + #region IList Members + + int IList.Add( object value ) + { + throw new NotSupportedException(); + } + + void IList.Clear() + { + throw new NotSupportedException(); + } + + public bool Contains( object value ) + { + return _source.Cast<object>().Skip( _startIndex ).Take( Count ).Contains( value ); + } + + public int IndexOf( object value ) + { + for ( int i = _startIndex; i <= _endIndex; i++ ) + { + if ( object.Equals( _source[i], value ) ) + return i - _startIndex; + } + + return -1; + } + + void IList.Insert( int index, object value ) + { + throw new NotSupportedException(); + } + + public bool IsFixedSize + { + get + { + var sourceCollection = _source as IList; + if ( sourceCollection != null ) + return sourceCollection.IsFixedSize; + + return false; + } + } + + public bool IsReadOnly + { + get + { + return true; + } + } + + void IList.Remove( object value ) + { + throw new NotSupportedException(); + } + + void IList.RemoveAt( int index ) + { + throw new NotSupportedException(); + } + + object IList.this[int index] + { + get + { + return this[index]; + } + set + { + this[index] = (T)value; + } + } + + #endregion + + #region IEnumerable<T> Members + + public IEnumerator<T> GetEnumerator() + { + return _source.Skip( _startIndex ).Take( Count ).GetEnumerator(); + } + + #endregion + + #region ICollection<T> Members + + void ICollection<T>.Add( T item ) + { + throw new NotSupportedException(); + } + + void ICollection<T>.Clear() + { + throw new NotSupportedException(); + } + + public bool Contains( T item ) + { + return _source.Skip( _startIndex ).Take( Count ).Contains( item ); + } + + public void CopyTo( T[] array, int arrayIndex ) + { + if ( array == null ) + throw new ArgumentNullException( "array" ); + + if ( arrayIndex < 0 ) + throw new ArgumentOutOfRangeException(); + + if ( arrayIndex + Count > array.Length ) + throw new ArgumentException(); + + for ( int i = 0; i < Count; i++ ) + { + array[arrayIndex + i] = this[i]; + } + } + + bool ICollection<T>.Remove( T item ) + { + throw new NotSupportedException(); + } + + #endregion + + #region IList<T> Members + + public int IndexOf( T item ) + { + for ( int i = 0; i < Count; i++ ) + { + if ( object.Equals( this[i], item ) ) + return i; + } + + return -1; + } + + void IList<T>.Insert( int index, T item ) + { + throw new NotSupportedException(); + } + + void IList<T>.RemoveAt( int index ) + { + throw new NotSupportedException(); + } + + public T this[int index] + { + get + { + if ( index < 0 || index >= Count ) + throw new ArgumentOutOfRangeException(); + + return _source[index + _startIndex]; + } + set + { + if ( index < 0 || index >= Count ) + throw new ArgumentOutOfRangeException(); + + _source[index + _startIndex] = value; + } + } + + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/TreeExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/TreeExtensions.cs new file mode 100644 index 0000000..6f7182f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/TreeExtensions.cs @@ -0,0 +1,53 @@ +/* + * [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. + */ + +using ITree = Antlr.Runtime.Tree.ITree; + +namespace Antlr.Runtime.JavaExtensions +{ + public static class TreeExtensions + { + public static ITree getNextSibling( this ITree tree ) + { + return tree.Parent.GetChild( tree.ChildIndex + 1 ); + //throw new NotImplementedException(); + } + + public static void setFirstChild( this ITree tree, ITree child ) + { + if ( tree.ChildCount == 0 ) + tree.AddChild( child ); + else + tree.SetChild( 0, child ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/TypeExtensions.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/TypeExtensions.cs new file mode 100644 index 0000000..42c0368 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/TypeExtensions.cs @@ -0,0 +1,102 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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; + +#if DEBUG + +namespace Antlr.Runtime.JavaExtensions +{ + public static class TypeExtensions + { + [Obsolete] + public static object get( this FieldInfo field, object obj ) + { + return field.GetValue( obj ); + } + + [Obsolete] + public static Type getComponentType( this Type type ) + { + return type.GetElementType(); + } + + [Obsolete] + public static ConstructorInfo getConstructor( this Type type, Type[] argumentTypes ) + { + return type.GetConstructor( argumentTypes ); + } + + [Obsolete] + public static FieldInfo getField( this Type type, string name ) + { + FieldInfo field = type.GetField( name ); + if ( field == null ) + throw new TargetException(); + + return field; + } + + [Obsolete] + public static string getName( this Type type ) + { + return type.Name; + } + + [Obsolete] + public static object invoke( this MethodInfo method, object obj, params object[] parameters ) + { + return method.Invoke( obj, parameters ); + } + + [Obsolete] + public static bool isArray( this Type type ) + { + return type.IsArray; + } + + [Obsolete] + public static bool isPrimitive( this Type type ) + { + return type.IsPrimitive; + } + + [Obsolete] + public static object newInstance( this Type type ) + { + return type.GetConstructor( new Type[0] ).Invoke( new object[0] ); + } + } +} + +#endif diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Antlr3.Runtime.Test.csproj b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Antlr3.Runtime.Test.csproj new file mode 100644 index 0000000..11206dc --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Antlr3.Runtime.Test.csproj @@ -0,0 +1,206 @@ +<?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>{19B965DE-5100-4064-A580-159644F6980E}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Antlr3.Runtime.Test</RootNamespace> + <AssemblyName>Antlr3.Runtime.Test</AssemblyName> + <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <SccProjectName>SAK</SccProjectName> + <SccLocalPath>SAK</SccLocalPath> + <SccAuxPath>SAK</SccAuxPath> + <SccProvider>SAK</SccProvider> + </PropertyGroup> + <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> + <DebugSymbols>true</DebugSymbols> + <DebugType>full</DebugType> + <Optimize>false</Optimize> + <OutputPath>bin\Debug\</OutputPath> + <DefineConstants>DEBUG;TRACE</DefineConstants> + <ErrorReport>prompt</ErrorReport> + <WarningLevel>4</WarningLevel> + </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="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" /> + <Reference Include="System" /> + <Reference Include="System.Core"> + <RequiredTargetFramework>3.5</RequiredTargetFramework> + </Reference> + <Reference Include="vjslib" /> + </ItemGroup> + <ItemGroup> + <Compile Include="Composition\Program.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\..\..\..\antlrcs\main\Antlr3.StringTemplate\Antlr3.StringTemplate.csproj"> + <Project>{B5910BE2-DE21-4AA9-95C1-486F42B9E794}</Project> + <Name>Antlr3.StringTemplate</Name> + </ProjectReference> + <ProjectReference Include="..\Antlr3.Runtime.Debug\Antlr3.Runtime.Debug.csproj"> + <Project>{5EE27A90-B023-42C9-AAF1-52B0424C5D0B}</Project> + <Name>Antlr3.Runtime.Debug</Name> + </ProjectReference> + <ProjectReference Include="..\Antlr3.Runtime.JavaExtensions\Antlr3.Runtime.JavaExtensions.csproj"> + <Project>{A7EEC557-EB14-451C-9616-B7A61F4ECE69}</Project> + <Name>Antlr3.Runtime.JavaExtensions</Name> + </ProjectReference> + <ProjectReference Include="..\Antlr3.Runtime\Antlr3.Runtime.csproj"> + <Project>{8FDC0A87-9005-4D5A-AB75-E55CEB575559}</Project> + <Name>Antlr3.Runtime</Name> + </ProjectReference> + </ItemGroup> + <ItemGroup> + <Antlr3 Include="SimpleExpression.g3"> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + </ItemGroup> + <ItemGroup> + <Compile Include="SemanticPredicateReduction.g3.lexer.cs"> + <DependentUpon>SemanticPredicateReduction.g3</DependentUpon> + </Compile> + <Compile Include="SemanticPredicateReduction.g3.parser.cs"> + <DependentUpon>SemanticPredicateReduction.g3</DependentUpon> + </Compile> + <Compile Include="SimpleExpressionLexerHelper.cs"> + <DependentUpon>SimpleExpression.g3</DependentUpon> + </Compile> + <Compile Include="SimpleExpressionParserHelper.cs"> + <DependentUpon>SimpleExpression.g3</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <Antlr3 Include="FastSimpleExpression.g3"> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + <Compile Include="FastSimpleExpressionLexerHelper.cs"> + <DependentUpon>FastSimpleExpression.g3</DependentUpon> + </Compile> + <Compile Include="FastSimpleExpressionParserHelper.cs"> + <DependentUpon>FastSimpleExpression.g3</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <Antlr3 Include="JavaCompat\Expr.g3"> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + </ItemGroup> + <ItemGroup> + <Antlr3 Include="BuildOptions\DebugGrammar.g3"> + <!--<GrammarOptions>-debug</GrammarOptions>--> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + <Compile Include="BuildOptions\DebugGrammarLexerHelper.cs"> + <DependentUpon>DebugGrammar.g3</DependentUpon> + </Compile> + <Compile Include="BuildOptions\DebugGrammarParserHelper.cs"> + <DependentUpon>DebugGrammar.g3</DependentUpon> + </Compile> + </ItemGroup> + <ItemGroup> + <Antlr3 Include="BuildOptions\DebugTreeGrammar.g3"> + <!--<GrammarOptions>-debug</GrammarOptions>--> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + <Compile Include="BuildOptions\DebugTreeGrammarHelper.cs"> + <DependentUpon>DebugTreeGrammar.g3</DependentUpon> + </Compile> + <Compile Include="SlimParsing\ITokenSource`1.cs" /> + <Compile Include="SlimParsing\ITokenStream`1.cs" /> + <Compile Include="SlimParsing\SlimLexer.cs" /> + <Compile Include="SlimParsing\SlimStringStream.cs" /> + <Compile Include="SlimParsing\SlimToken.cs" /> + <Compile Include="SlimParsing\SlimTokenStream.cs" /> + <Compile Include="SlimParsing\Tree\ITreeAdaptor`1.cs" /> + <Compile Include="SlimParsing\Tree\ITreeFactory.cs" /> + <Compile Include="SlimParsing\Tree\ITreeNodeStream`1.cs" /> + <Compile Include="StringTemplateOutput.g3.lexer.cs"> + <DependentUpon>StringTemplateOutput.g3</DependentUpon> + </Compile> + <Compile Include="StringTemplateOutput.g3.parser.cs"> + <DependentUpon>StringTemplateOutput.g3</DependentUpon> + </Compile> + <Compile Include="TestActionFeatures.g3.lexer.cs"> + <DependentUpon>TestActionFeatures.g3</DependentUpon> + </Compile> + <Compile Include="TestActionFeatures.g3.parser.cs"> + <DependentUpon>TestActionFeatures.g3</DependentUpon> + </Compile> + <Compile Include="TestDotTreeGenerator.cs" /> + <Compile Include="TestExpressionFeatures.g3.lexer.cs"> + <DependentUpon>TestExpressionFeatures.g3</DependentUpon> + </Compile> + <Compile Include="TestExpressionFeatures.g3.parser.cs"> + <DependentUpon>TestExpressionFeatures.g3</DependentUpon> + </Compile> + <Compile Include="TestFastLexer.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="BuildOptions\ProfileGrammar.g3"> + <!--<GrammarOptions>-profile</GrammarOptions>--> + <Generator>MSBuild:Compile</Generator> + </None> + <None Include="BuildOptions\ProfileGrammarLexerHelper.cs"> + <DependentUpon>ProfileGrammar.g3</DependentUpon> + </None> + <None Include="BuildOptions\ProfileGrammarParserHelper.cs"> + <DependentUpon>ProfileGrammar.g3</DependentUpon> + </None> + <Antlr3 Include="StringTemplateOutput.g3"> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + <Antlr3 Include="TestActionFeatures.g3"> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + <Antlr3 Include="SemanticPredicateReduction.g3"> + <Generator>MSBuild:Compile</Generator> + </Antlr3> + <Antlr3 Include="Composition\Reduce.g3" /> + <Antlr3 Include="Composition\Simplify.g3" /> + <Antlr3 Include="Composition\VecMath.g3" /> + <None Include="Composition\VecMath_Lexer.g3" /> + <None Include="Composition\VecMath_Parser.g3" /> + <None Include="TestExpressionFeatures.g3"> + <Generator>MSBuild:Compile</Generator> + </None> + </ItemGroup> + <ItemGroup> + <None Include="BuildOptions\ProfileTreeGrammar.g3"> + <!--<GrammarOptions>-profile</GrammarOptions>--> + <Generator>MSBuild:Compile</Generator> + </None> + <None Include="BuildOptions\ProfileTreeGrammarHelper.cs"> + <DependentUpon>ProfileTreeGrammar.g3</DependentUpon> + </None> + </ItemGroup> + <PropertyGroup> + <!-- Folder containing AntlrBuildTask.dll --> + <AntlrBuildTaskPath>$(SolutionDir)bin\Bootstrap</AntlrBuildTaskPath> + <!-- Path to the ANTLR Tool itself. --> + <AntlrToolPath>$(SolutionDir)bin\Bootstrap\Antlr3.exe</AntlrToolPath> + </PropertyGroup> + <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> + <Import Project="$(ProjectDir)..\..\..\..\..\..\antlrcs\main\bin\Bootstrap\Antlr3.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.Test/Antlr3.Runtime.Test.csproj.vspscc b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Antlr3.Runtime.Test.csproj.vspscc new file mode 100644 index 0000000..162a4c7 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Antlr3.Runtime.Test.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "relative:antlr\\main\\runtime\\CSharp3\\Sources\\Antlr3.Runtime.Test" +"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.Test/BuildOptions/DebugGrammar.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammar.g3 new file mode 100644 index 0000000..36b1884 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammar.g3 @@ -0,0 +1,100 @@ +/* + * [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. + */ + +grammar DebugGrammar; + +options +{ + language=CSharp3; + output=AST; + ASTLabelType=CommonTree; +} + +tokens +{ + // define pseudo-operations + FUNC; + CALL; +} + +// START:stat +prog: ( stat )* + ; + +stat: expr NEWLINE -> expr + | ID '=' expr NEWLINE -> ^('=' ID expr) + | func NEWLINE -> func + | NEWLINE -> // ignore + ; + +func: ID '(' formalPar ')' '=' expr -> ^(FUNC ID formalPar expr) + ; + finally { + functionDefinitions.Add($func.tree); + } + +formalPar + : ID + | INT + ; + +// END:stat + +// START:expr +expr: multExpr (('+'^|'-'^) multExpr)* + ; + +multExpr + : atom (('*'|'/'|'%')^ atom)* + ; + +atom: INT + | ID + | '(' expr ')' -> expr + | ID '(' expr ')' -> ^(CALL ID expr) + ; +// END:expr + +// START:tokens +ID : ('a'..'z'|'A'..'Z')+ + ; + +INT : '0'..'9'+ + ; + +NEWLINE + : '\r'? '\n' + ; + +WS : (' '|'\t')+ { Skip(); } + ; +// END:tokens diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarLexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarLexer.cs new file mode 100644 index 0000000..ab2235e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarLexer.cs @@ -0,0 +1,693 @@ +// $ANTLR 3.1.2 BuildOptions\\DebugGrammar.g3 2009-09-30 13:18:14 + +// The variable 'variable' is assigned but its value is never used. +#pragma warning disable 219 +// Unreachable code detected. +#pragma warning disable 162 + + +using System.Collections.Generic; +using Antlr.Runtime; +using Stack = System.Collections.Generic.Stack<object>; +using List = System.Collections.IList; +using ArrayList = System.Collections.Generic.List<object>; + +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "3.1.2")] +[System.CLSCompliant(false)] +public partial class DebugGrammarLexer : Lexer +{ + public const int EOF=-1; + public const int T__10=10; + public const int T__11=11; + public const int T__12=12; + public const int T__13=13; + public const int T__14=14; + public const int T__15=15; + public const int T__16=16; + public const int T__17=17; + public const int CALL=4; + public const int FUNC=5; + public const int ID=6; + public const int INT=7; + public const int NEWLINE=8; + public const int WS=9; + + // delegates + // delegators + + public DebugGrammarLexer() {} + public DebugGrammarLexer( ICharStream input ) + : this( input, new RecognizerSharedState() ) + { + } + public DebugGrammarLexer( ICharStream input, RecognizerSharedState state ) + : base( input, state ) + { + + } + public override string GrammarFileName { get { return "BuildOptions\\DebugGrammar.g3"; } } + + // $ANTLR start "T__10" + private void mT__10() + { + try + { + int _type = T__10; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:7:9: ( '-' ) + // BuildOptions\\DebugGrammar.g3:7:9: '-' + { + Match('-'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__10" + + // $ANTLR start "T__11" + private void mT__11() + { + try + { + int _type = T__11; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:8:9: ( '%' ) + // BuildOptions\\DebugGrammar.g3:8:9: '%' + { + Match('%'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__11" + + // $ANTLR start "T__12" + private void mT__12() + { + try + { + int _type = T__12; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:9:9: ( '(' ) + // BuildOptions\\DebugGrammar.g3:9:9: '(' + { + Match('('); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__12" + + // $ANTLR start "T__13" + private void mT__13() + { + try + { + int _type = T__13; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:10:9: ( ')' ) + // BuildOptions\\DebugGrammar.g3:10:9: ')' + { + Match(')'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__13" + + // $ANTLR start "T__14" + private void mT__14() + { + try + { + int _type = T__14; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:11:9: ( '*' ) + // BuildOptions\\DebugGrammar.g3:11:9: '*' + { + Match('*'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__14" + + // $ANTLR start "T__15" + private void mT__15() + { + try + { + int _type = T__15; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:12:9: ( '/' ) + // BuildOptions\\DebugGrammar.g3:12:9: '/' + { + Match('/'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__15" + + // $ANTLR start "T__16" + private void mT__16() + { + try + { + int _type = T__16; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:13:9: ( '+' ) + // BuildOptions\\DebugGrammar.g3:13:9: '+' + { + Match('+'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__16" + + // $ANTLR start "T__17" + private void mT__17() + { + try + { + int _type = T__17; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:14:9: ( '=' ) + // BuildOptions\\DebugGrammar.g3:14:9: '=' + { + Match('='); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__17" + + // $ANTLR start "ID" + private void mID() + { + try + { + int _type = ID; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:88:9: ( ( 'a' .. 'z' | 'A' .. 'Z' )+ ) + // BuildOptions\\DebugGrammar.g3:88:9: ( 'a' .. 'z' | 'A' .. 'Z' )+ + { + // BuildOptions\\DebugGrammar.g3:88:9: ( 'a' .. 'z' | 'A' .. 'Z' )+ + int cnt1=0; + for ( ; ; ) + { + int alt1=2; + int LA1_0 = input.LA(1); + + if ( ((LA1_0>='A' && LA1_0<='Z')||(LA1_0>='a' && LA1_0<='z')) ) + { + alt1=1; + } + + + switch ( alt1 ) + { + case 1: + // BuildOptions\\DebugGrammar.g3: + { + input.Consume(); + + + } + break; + + default: + if ( cnt1 >= 1 ) + goto loop1; + + EarlyExitException eee1 = new EarlyExitException( 1, input ); + throw eee1; + } + cnt1++; + } + loop1: + ; + + + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "ID" + + // $ANTLR start "INT" + private void mINT() + { + try + { + int _type = INT; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:91:9: ( ( '0' .. '9' )+ ) + // BuildOptions\\DebugGrammar.g3:91:9: ( '0' .. '9' )+ + { + // BuildOptions\\DebugGrammar.g3:91:9: ( '0' .. '9' )+ + int cnt2=0; + for ( ; ; ) + { + int alt2=2; + int LA2_0 = input.LA(1); + + if ( ((LA2_0>='0' && LA2_0<='9')) ) + { + alt2=1; + } + + + switch ( alt2 ) + { + case 1: + // BuildOptions\\DebugGrammar.g3: + { + input.Consume(); + + + } + break; + + default: + if ( cnt2 >= 1 ) + goto loop2; + + EarlyExitException eee2 = new EarlyExitException( 2, input ); + throw eee2; + } + cnt2++; + } + loop2: + ; + + + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "INT" + + // $ANTLR start "NEWLINE" + private void mNEWLINE() + { + try + { + int _type = NEWLINE; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:95:7: ( ( '\\r' )? '\\n' ) + // BuildOptions\\DebugGrammar.g3:95:7: ( '\\r' )? '\\n' + { + // BuildOptions\\DebugGrammar.g3:95:7: ( '\\r' )? + int alt3=2; + int LA3_0 = input.LA(1); + + if ( (LA3_0=='\r') ) + { + alt3=1; + } + switch ( alt3 ) + { + case 1: + // BuildOptions\\DebugGrammar.g3:95:0: '\\r' + { + Match('\r'); + + } + break; + + } + + Match('\n'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "NEWLINE" + + // $ANTLR start "WS" + private void mWS() + { + try + { + int _type = WS; + int _channel = DefaultTokenChannel; + // BuildOptions\\DebugGrammar.g3:98:9: ( ( ' ' | '\\t' )+ ) + // BuildOptions\\DebugGrammar.g3:98:9: ( ' ' | '\\t' )+ + { + // BuildOptions\\DebugGrammar.g3:98:9: ( ' ' | '\\t' )+ + int cnt4=0; + for ( ; ; ) + { + int alt4=2; + int LA4_0 = input.LA(1); + + if ( (LA4_0=='\t'||LA4_0==' ') ) + { + alt4=1; + } + + + switch ( alt4 ) + { + case 1: + // BuildOptions\\DebugGrammar.g3: + { + input.Consume(); + + + } + break; + + default: + if ( cnt4 >= 1 ) + goto loop4; + + EarlyExitException eee4 = new EarlyExitException( 4, input ); + throw eee4; + } + cnt4++; + } + loop4: + ; + + + Skip(); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "WS" + + public override void mTokens() + { + // BuildOptions\\DebugGrammar.g3:1:10: ( T__10 | T__11 | T__12 | T__13 | T__14 | T__15 | T__16 | T__17 | ID | INT | NEWLINE | WS ) + int alt5=12; + switch ( input.LA(1) ) + { + case '-': + { + alt5=1; + } + break; + case '%': + { + alt5=2; + } + break; + case '(': + { + alt5=3; + } + break; + case ')': + { + alt5=4; + } + break; + case '*': + { + alt5=5; + } + break; + case '/': + { + alt5=6; + } + break; + case '+': + { + alt5=7; + } + break; + case '=': + { + alt5=8; + } + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + { + alt5=9; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + alt5=10; + } + break; + case '\n': + case '\r': + { + alt5=11; + } + break; + case '\t': + case ' ': + { + alt5=12; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 5, 0, input); + + throw nvae; + } + } + + switch ( alt5 ) + { + case 1: + // BuildOptions\\DebugGrammar.g3:1:10: T__10 + { + mT__10(); + + } + break; + case 2: + // BuildOptions\\DebugGrammar.g3:1:16: T__11 + { + mT__11(); + + } + break; + case 3: + // BuildOptions\\DebugGrammar.g3:1:22: T__12 + { + mT__12(); + + } + break; + case 4: + // BuildOptions\\DebugGrammar.g3:1:28: T__13 + { + mT__13(); + + } + break; + case 5: + // BuildOptions\\DebugGrammar.g3:1:34: T__14 + { + mT__14(); + + } + break; + case 6: + // BuildOptions\\DebugGrammar.g3:1:40: T__15 + { + mT__15(); + + } + break; + case 7: + // BuildOptions\\DebugGrammar.g3:1:46: T__16 + { + mT__16(); + + } + break; + case 8: + // BuildOptions\\DebugGrammar.g3:1:52: T__17 + { + mT__17(); + + } + break; + case 9: + // BuildOptions\\DebugGrammar.g3:1:58: ID + { + mID(); + + } + break; + case 10: + // BuildOptions\\DebugGrammar.g3:1:61: INT + { + mINT(); + + } + break; + case 11: + // BuildOptions\\DebugGrammar.g3:1:65: NEWLINE + { + mNEWLINE(); + + } + break; + case 12: + // BuildOptions\\DebugGrammar.g3:1:73: WS + { + mWS(); + + } + break; + + } + + } + + + #region DFA + + protected override void InitDFAs() + { + base.InitDFAs(); + } + + + #endregion + +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarLexerHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarLexerHelper.cs new file mode 100644 index 0000000..7271295 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarLexerHelper.cs @@ -0,0 +1,32 @@ +/* + * [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. + */ + diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarParser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarParser.cs new file mode 100644 index 0000000..7274b21 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarParser.cs @@ -0,0 +1,1556 @@ +// $ANTLR 3.1.2 BuildOptions\\DebugGrammar.g3 2009-09-30 13:18:13 + +// The variable 'variable' is assigned but its value is never used. +#pragma warning disable 219 +// Unreachable code detected. +#pragma warning disable 162 + + +using System.Collections.Generic; +using Antlr.Runtime; +using Stack = System.Collections.Generic.Stack<object>; +using List = System.Collections.IList; +using ArrayList = System.Collections.Generic.List<object>; + +using Antlr.Runtime.Debug; +using IOException = System.IO.IOException; + +using Antlr.Runtime.Tree; +using RewriteRuleITokenStream = Antlr.Runtime.Tree.RewriteRuleTokenStream; + +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "3.1.2")] +[System.CLSCompliant(false)] +public partial class DebugGrammarParser : DebugParser +{ + internal static readonly string[] tokenNames = new string[] { + "<invalid>", "<EOR>", "<DOWN>", "<UP>", "CALL", "FUNC", "ID", "INT", "NEWLINE", "WS", "'-'", "'%'", "'('", "')'", "'*'", "'/'", "'+'", "'='" + }; + public const int EOF=-1; + public const int T__10=10; + public const int T__11=11; + public const int T__12=12; + public const int T__13=13; + public const int T__14=14; + public const int T__15=15; + public const int T__16=16; + public const int T__17=17; + public const int CALL=4; + public const int FUNC=5; + public const int ID=6; + public const int INT=7; + public const int NEWLINE=8; + public const int WS=9; + + // delegates + // delegators + + public static readonly string[] ruleNames = + new string[] + { + "invalidRule", "atom", "expr", "formalPar", "func", "multExpr", "prog", + "stat" + }; + + int ruleLevel = 0; + public virtual int RuleLevel { get { return ruleLevel; } } + public virtual void IncRuleLevel() { ruleLevel++; } + public virtual void DecRuleLevel() { ruleLevel--; } + public DebugGrammarParser( ITokenStream input ) + : this( input, DebugEventSocketProxy.DefaultDebuggerPort, new RecognizerSharedState() ) + { + } + public DebugGrammarParser( ITokenStream input, int port, RecognizerSharedState state ) + : base( input, state ) + { + InitializeTreeAdaptor(); + if ( TreeAdaptor == null ) + TreeAdaptor = new CommonTreeAdaptor(); + DebugEventSocketProxy proxy = new DebugEventSocketProxy( this, port, adaptor ); + DebugListener = proxy; + TokenStream = new DebugTokenStream( input, proxy ); + try + { + proxy.Handshake(); + } + catch ( IOException ioe ) + { + ReportError( ioe ); + } + ITreeAdaptor adap = new CommonTreeAdaptor(); + TreeAdaptor = adap; + proxy.TreeAdaptor = adap; + } + public DebugGrammarParser( ITokenStream input, IDebugEventListener dbg ) + : base( input, dbg ) + { + InitializeTreeAdaptor(); + if ( TreeAdaptor == null ) + TreeAdaptor = new CommonTreeAdaptor(); + + ITreeAdaptor adap = new CommonTreeAdaptor(); + TreeAdaptor = adap; + + } + protected virtual bool EvalPredicate( bool result, string predicate ) + { + dbg.SemanticPredicate( result, predicate ); + return result; + } + + // Implement this function in your helper file to use a custom tree adaptor + partial void InitializeTreeAdaptor(); + protected DebugTreeAdaptor adaptor; + + public ITreeAdaptor TreeAdaptor + { + get + { + return adaptor; + } + set + { + this.adaptor = new DebugTreeAdaptor(dbg,adaptor); + + } + } + + + public override string[] TokenNames { get { return DebugGrammarParser.tokenNames; } } + public override string GrammarFileName { get { return "BuildOptions\\DebugGrammar.g3"; } } + + + #region Rules + public class prog_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "prog" + // BuildOptions\\DebugGrammar.g3:50:0: prog : ( stat )* ; + private DebugGrammarParser.prog_return prog( ) + { + DebugGrammarParser.prog_return retval = new DebugGrammarParser.prog_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + DebugGrammarParser.stat_return stat1 = default(DebugGrammarParser.stat_return); + + + try + { + dbg.EnterRule( GrammarFileName, "prog" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 50, -1 ); + + try + { + // BuildOptions\\DebugGrammar.g3:50:7: ( ( stat )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:50:7: ( stat )* + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 50, 6 ); + // BuildOptions\\DebugGrammar.g3:50:7: ( stat )* + try + { + dbg.EnterSubRule( 1 ); + + for ( ; ; ) + { + int alt1=2; + try + { + dbg.EnterDecision( 1 ); + + int LA1_0 = input.LA(1); + + if ( ((LA1_0>=ID && LA1_0<=NEWLINE)||LA1_0==12) ) + { + alt1=1; + } + + + } + finally + { + dbg.ExitDecision( 1 ); + } + + switch ( alt1 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:50:9: stat + { + dbg.Location( 50, 8 ); + PushFollow(Follow._stat_in_prog53); + stat1=stat(); + + state._fsp--; + + adaptor.AddChild(root_0, stat1.Tree); + + } + break; + + default: + goto loop1; + } + } + + loop1: + ; + + } + finally + { + dbg.ExitSubRule( 1 ); + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(51, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "prog" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "prog" + + public class stat_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "stat" + // BuildOptions\\DebugGrammar.g3:53:0: stat : ( expr NEWLINE -> expr | ID '=' expr NEWLINE -> ^( '=' ID expr ) | func NEWLINE -> func | NEWLINE ->); + private DebugGrammarParser.stat_return stat( ) + { + DebugGrammarParser.stat_return retval = new DebugGrammarParser.stat_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken NEWLINE3=null; + IToken ID4=null; + IToken char_literal5=null; + IToken NEWLINE7=null; + IToken NEWLINE9=null; + IToken NEWLINE10=null; + DebugGrammarParser.expr_return expr2 = default(DebugGrammarParser.expr_return); + DebugGrammarParser.expr_return expr6 = default(DebugGrammarParser.expr_return); + DebugGrammarParser.func_return func8 = default(DebugGrammarParser.func_return); + + CommonTree NEWLINE3_tree=null; + CommonTree ID4_tree=null; + CommonTree char_literal5_tree=null; + CommonTree NEWLINE7_tree=null; + CommonTree NEWLINE9_tree=null; + CommonTree NEWLINE10_tree=null; + RewriteRuleITokenStream stream_NEWLINE=new RewriteRuleITokenStream(adaptor,"token NEWLINE"); + RewriteRuleITokenStream stream_ID=new RewriteRuleITokenStream(adaptor,"token ID"); + RewriteRuleITokenStream stream_17=new RewriteRuleITokenStream(adaptor,"token 17"); + RewriteRuleSubtreeStream stream_expr=new RewriteRuleSubtreeStream(adaptor,"rule expr"); + RewriteRuleSubtreeStream stream_func=new RewriteRuleSubtreeStream(adaptor,"rule func"); + try + { + dbg.EnterRule( GrammarFileName, "stat" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 53, -1 ); + + try + { + // BuildOptions\\DebugGrammar.g3:53:9: ( expr NEWLINE -> expr | ID '=' expr NEWLINE -> ^( '=' ID expr ) | func NEWLINE -> func | NEWLINE ->) + int alt2=4; + try + { + dbg.EnterDecision( 2 ); + + try + { + isCyclicDecision = true; + alt2 = dfa2.Predict(input); + } + catch ( NoViableAltException nvae ) + { + dbg.RecognitionException( nvae ); + throw nvae; + } + } + finally + { + dbg.ExitDecision( 2 ); + } + + switch ( alt2 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:53:9: expr NEWLINE + { + dbg.Location( 53, 8 ); + PushFollow(Follow._expr_in_stat70); + expr2=expr(); + + state._fsp--; + + stream_expr.Add(expr2.Tree); + dbg.Location( 53, 13 ); + NEWLINE3=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat72); + stream_NEWLINE.Add(NEWLINE3); + + + + { + // AST REWRITE + // elements: expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 53:41: -> expr + { + dbg.Location( 53, 43 ); + adaptor.AddChild(root_0, stream_expr.NextTree()); + + } + + retval.tree = root_0; + } + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\DebugGrammar.g3:54:9: ID '=' expr NEWLINE + { + dbg.Location( 54, 8 ); + ID4=(IToken)Match(input,ID,Follow._ID_in_stat105); + stream_ID.Add(ID4); + + dbg.Location( 54, 11 ); + char_literal5=(IToken)Match(input,17,Follow._17_in_stat107); + stream_17.Add(char_literal5); + + dbg.Location( 54, 15 ); + PushFollow(Follow._expr_in_stat109); + expr6=expr(); + + state._fsp--; + + stream_expr.Add(expr6.Tree); + dbg.Location( 54, 20 ); + NEWLINE7=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat111); + stream_NEWLINE.Add(NEWLINE7); + + + + { + // AST REWRITE + // elements: 17, ID, expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 54:41: -> ^( '=' ID expr ) + { + dbg.Location( 54, 43 ); + // BuildOptions\\DebugGrammar.g3:54:44: ^( '=' ID expr ) + { + CommonTree root_1 = (CommonTree)adaptor.Nil(); + dbg.Location( 54, 45 ); + root_1 = (CommonTree)adaptor.BecomeRoot(stream_17.NextNode(), root_1); + + dbg.Location( 54, 49 ); + adaptor.AddChild(root_1, stream_ID.NextNode()); + dbg.Location( 54, 52 ); + adaptor.AddChild(root_1, stream_expr.NextTree()); + + adaptor.AddChild(root_0, root_1); + } + + } + + retval.tree = root_0; + } + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\DebugGrammar.g3:55:9: func NEWLINE + { + dbg.Location( 55, 8 ); + PushFollow(Follow._func_in_stat143); + func8=func(); + + state._fsp--; + + stream_func.Add(func8.Tree); + dbg.Location( 55, 13 ); + NEWLINE9=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat145); + stream_NEWLINE.Add(NEWLINE9); + + + + { + // AST REWRITE + // elements: func + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 55:41: -> func + { + dbg.Location( 55, 43 ); + adaptor.AddChild(root_0, stream_func.NextTree()); + + } + + retval.tree = root_0; + } + + } + break; + case 4: + dbg.EnterAlt( 4 ); + + // BuildOptions\\DebugGrammar.g3:56:9: NEWLINE + { + dbg.Location( 56, 8 ); + NEWLINE10=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat178); + stream_NEWLINE.Add(NEWLINE10); + + + + { + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 56:41: -> + { + dbg.Location( 57, 4 ); + root_0 = null; + } + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(57, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "stat" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "stat" + + public class func_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "func" + // BuildOptions\\DebugGrammar.g3:59:0: func : ID '(' formalPar ')' '=' expr -> ^( FUNC ID formalPar expr ) ; + private DebugGrammarParser.func_return func( ) + { + DebugGrammarParser.func_return retval = new DebugGrammarParser.func_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken ID11=null; + IToken char_literal12=null; + IToken char_literal14=null; + IToken char_literal15=null; + DebugGrammarParser.formalPar_return formalPar13 = default(DebugGrammarParser.formalPar_return); + DebugGrammarParser.expr_return expr16 = default(DebugGrammarParser.expr_return); + + CommonTree ID11_tree=null; + CommonTree char_literal12_tree=null; + CommonTree char_literal14_tree=null; + CommonTree char_literal15_tree=null; + RewriteRuleITokenStream stream_ID=new RewriteRuleITokenStream(adaptor,"token ID"); + RewriteRuleITokenStream stream_12=new RewriteRuleITokenStream(adaptor,"token 12"); + RewriteRuleITokenStream stream_13=new RewriteRuleITokenStream(adaptor,"token 13"); + RewriteRuleITokenStream stream_17=new RewriteRuleITokenStream(adaptor,"token 17"); + RewriteRuleSubtreeStream stream_formalPar=new RewriteRuleSubtreeStream(adaptor,"rule formalPar"); + RewriteRuleSubtreeStream stream_expr=new RewriteRuleSubtreeStream(adaptor,"rule expr"); + try + { + dbg.EnterRule( GrammarFileName, "func" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 59, -1 ); + + try + { + // BuildOptions\\DebugGrammar.g3:59:9: ( ID '(' formalPar ')' '=' expr -> ^( FUNC ID formalPar expr ) ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:59:9: ID '(' formalPar ')' '=' expr + { + dbg.Location( 59, 8 ); + ID11=(IToken)Match(input,ID,Follow._ID_in_func219); + stream_ID.Add(ID11); + + dbg.Location( 59, 12 ); + char_literal12=(IToken)Match(input,12,Follow._12_in_func222); + stream_12.Add(char_literal12); + + dbg.Location( 59, 16 ); + PushFollow(Follow._formalPar_in_func224); + formalPar13=formalPar(); + + state._fsp--; + + stream_formalPar.Add(formalPar13.Tree); + dbg.Location( 59, 26 ); + char_literal14=(IToken)Match(input,13,Follow._13_in_func226); + stream_13.Add(char_literal14); + + dbg.Location( 59, 30 ); + char_literal15=(IToken)Match(input,17,Follow._17_in_func228); + stream_17.Add(char_literal15); + + dbg.Location( 59, 34 ); + PushFollow(Follow._expr_in_func230); + expr16=expr(); + + state._fsp--; + + stream_expr.Add(expr16.Tree); + + + { + // AST REWRITE + // elements: ID, formalPar, expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 59:41: -> ^( FUNC ID formalPar expr ) + { + dbg.Location( 59, 43 ); + // BuildOptions\\DebugGrammar.g3:59:44: ^( FUNC ID formalPar expr ) + { + CommonTree root_1 = (CommonTree)adaptor.Nil(); + dbg.Location( 59, 45 ); + root_1 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(FUNC, "FUNC"), root_1); + + dbg.Location( 59, 50 ); + adaptor.AddChild(root_1, stream_ID.NextNode()); + dbg.Location( 59, 53 ); + adaptor.AddChild(root_1, stream_formalPar.NextTree()); + dbg.Location( 59, 63 ); + adaptor.AddChild(root_1, stream_expr.NextTree()); + + adaptor.AddChild(root_0, root_1); + } + + } + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + + functionDefinitions.Add(((CommonTree)retval.Tree)); + + } + dbg.Location(60, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "func" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "func" + + public class formalPar_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "formalPar" + // BuildOptions\\DebugGrammar.g3:65:0: formalPar : ( ID | INT ); + private DebugGrammarParser.formalPar_return formalPar( ) + { + DebugGrammarParser.formalPar_return retval = new DebugGrammarParser.formalPar_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken set17=null; + + CommonTree set17_tree=null; + + try + { + dbg.EnterRule( GrammarFileName, "formalPar" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 65, -1 ); + + try + { + // BuildOptions\\DebugGrammar.g3:66:9: ( ID | INT ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3: + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 66, 8 ); + set17=(IToken)input.LT(1); + if ( (input.LA(1)>=ID && input.LA(1)<=INT) ) + { + input.Consume(); + adaptor.AddChild(root_0, (CommonTree)adaptor.Create(set17)); + state.errorRecovery=false; + } + else + { + MismatchedSetException mse = new MismatchedSetException(null,input); + dbg.RecognitionException( mse ); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(68, 1); + + } + finally + { + dbg.ExitRule( GrammarFileName, "formalPar" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "formalPar" + + public class expr_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "expr" + // BuildOptions\\DebugGrammar.g3:73:0: expr : multExpr ( ( '+' | '-' ) multExpr )* ; + private DebugGrammarParser.expr_return expr( ) + { + DebugGrammarParser.expr_return retval = new DebugGrammarParser.expr_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken char_literal19=null; + IToken char_literal20=null; + DebugGrammarParser.multExpr_return multExpr18 = default(DebugGrammarParser.multExpr_return); + DebugGrammarParser.multExpr_return multExpr21 = default(DebugGrammarParser.multExpr_return); + + CommonTree char_literal19_tree=null; + CommonTree char_literal20_tree=null; + + try + { + dbg.EnterRule( GrammarFileName, "expr" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 73, -1 ); + + try + { + // BuildOptions\\DebugGrammar.g3:73:9: ( multExpr ( ( '+' | '-' ) multExpr )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:73:9: multExpr ( ( '+' | '-' ) multExpr )* + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 73, 8 ); + PushFollow(Follow._multExpr_in_expr288); + multExpr18=multExpr(); + + state._fsp--; + + adaptor.AddChild(root_0, multExpr18.Tree); + dbg.Location( 73, 17 ); + // BuildOptions\\DebugGrammar.g3:73:18: ( ( '+' | '-' ) multExpr )* + try + { + dbg.EnterSubRule( 4 ); + + for ( ; ; ) + { + int alt4=2; + try + { + dbg.EnterDecision( 4 ); + + int LA4_0 = input.LA(1); + + if ( (LA4_0==10||LA4_0==16) ) + { + alt4=1; + } + + + } + finally + { + dbg.ExitDecision( 4 ); + } + + switch ( alt4 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:73:19: ( '+' | '-' ) multExpr + { + dbg.Location( 73, 18 ); + // BuildOptions\\DebugGrammar.g3:73:19: ( '+' | '-' ) + int alt3=2; + try + { + dbg.EnterSubRule( 3 ); + try + { + dbg.EnterDecision( 3 ); + + int LA3_0 = input.LA(1); + + if ( (LA3_0==16) ) + { + alt3=1; + } + else if ( (LA3_0==10) ) + { + alt3=2; + } + else + { + NoViableAltException nvae = new NoViableAltException("", 3, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + finally + { + dbg.ExitDecision( 3 ); + } + + switch ( alt3 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:73:20: '+' + { + dbg.Location( 73, 22 ); + char_literal19=(IToken)Match(input,16,Follow._16_in_expr292); + char_literal19_tree = (CommonTree)adaptor.Create(char_literal19); + root_0 = (CommonTree)adaptor.BecomeRoot(char_literal19_tree, root_0); + + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\DebugGrammar.g3:73:25: '-' + { + dbg.Location( 73, 27 ); + char_literal20=(IToken)Match(input,10,Follow._10_in_expr295); + char_literal20_tree = (CommonTree)adaptor.Create(char_literal20); + root_0 = (CommonTree)adaptor.BecomeRoot(char_literal20_tree, root_0); + + + } + break; + + } + } + finally + { + dbg.ExitSubRule( 3 ); + } + + dbg.Location( 73, 30 ); + PushFollow(Follow._multExpr_in_expr299); + multExpr21=multExpr(); + + state._fsp--; + + adaptor.AddChild(root_0, multExpr21.Tree); + + } + break; + + default: + goto loop4; + } + } + + loop4: + ; + + } + finally + { + dbg.ExitSubRule( 4 ); + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(74, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "expr" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "expr" + + public class multExpr_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "multExpr" + // BuildOptions\\DebugGrammar.g3:76:0: multExpr : atom ( ( '*' | '/' | '%' ) atom )* ; + private DebugGrammarParser.multExpr_return multExpr( ) + { + DebugGrammarParser.multExpr_return retval = new DebugGrammarParser.multExpr_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken set23=null; + DebugGrammarParser.atom_return atom22 = default(DebugGrammarParser.atom_return); + DebugGrammarParser.atom_return atom24 = default(DebugGrammarParser.atom_return); + + CommonTree set23_tree=null; + + try + { + dbg.EnterRule( GrammarFileName, "multExpr" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 76, -1 ); + + try + { + // BuildOptions\\DebugGrammar.g3:77:9: ( atom ( ( '*' | '/' | '%' ) atom )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:77:9: atom ( ( '*' | '/' | '%' ) atom )* + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 77, 8 ); + PushFollow(Follow._atom_in_multExpr320); + atom22=atom(); + + state._fsp--; + + adaptor.AddChild(root_0, atom22.Tree); + dbg.Location( 77, 13 ); + // BuildOptions\\DebugGrammar.g3:77:14: ( ( '*' | '/' | '%' ) atom )* + try + { + dbg.EnterSubRule( 5 ); + + for ( ; ; ) + { + int alt5=2; + try + { + dbg.EnterDecision( 5 ); + + int LA5_0 = input.LA(1); + + if ( (LA5_0==11||(LA5_0>=14 && LA5_0<=15)) ) + { + alt5=1; + } + + + } + finally + { + dbg.ExitDecision( 5 ); + } + + switch ( alt5 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:77:15: ( '*' | '/' | '%' ) atom + { + dbg.Location( 77, 27 ); + set23=(IToken)input.LT(1); + set23=(IToken)input.LT(1); + if ( input.LA(1)==11||(input.LA(1)>=14 && input.LA(1)<=15) ) + { + input.Consume(); + root_0 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(set23), root_0); + state.errorRecovery=false; + } + else + { + MismatchedSetException mse = new MismatchedSetException(null,input); + dbg.RecognitionException( mse ); + throw mse; + } + + dbg.Location( 77, 29 ); + PushFollow(Follow._atom_in_multExpr332); + atom24=atom(); + + state._fsp--; + + adaptor.AddChild(root_0, atom24.Tree); + + } + break; + + default: + goto loop5; + } + } + + loop5: + ; + + } + finally + { + dbg.ExitSubRule( 5 ); + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(78, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "multExpr" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "multExpr" + + public class atom_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "atom" + // BuildOptions\\DebugGrammar.g3:80:0: atom : ( INT | ID | '(' expr ')' -> expr | ID '(' expr ')' -> ^( CALL ID expr ) ); + private DebugGrammarParser.atom_return atom( ) + { + DebugGrammarParser.atom_return retval = new DebugGrammarParser.atom_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken INT25=null; + IToken ID26=null; + IToken char_literal27=null; + IToken char_literal29=null; + IToken ID30=null; + IToken char_literal31=null; + IToken char_literal33=null; + DebugGrammarParser.expr_return expr28 = default(DebugGrammarParser.expr_return); + DebugGrammarParser.expr_return expr32 = default(DebugGrammarParser.expr_return); + + CommonTree INT25_tree=null; + CommonTree ID26_tree=null; + CommonTree char_literal27_tree=null; + CommonTree char_literal29_tree=null; + CommonTree ID30_tree=null; + CommonTree char_literal31_tree=null; + CommonTree char_literal33_tree=null; + RewriteRuleITokenStream stream_12=new RewriteRuleITokenStream(adaptor,"token 12"); + RewriteRuleITokenStream stream_13=new RewriteRuleITokenStream(adaptor,"token 13"); + RewriteRuleITokenStream stream_ID=new RewriteRuleITokenStream(adaptor,"token ID"); + RewriteRuleSubtreeStream stream_expr=new RewriteRuleSubtreeStream(adaptor,"rule expr"); + try + { + dbg.EnterRule( GrammarFileName, "atom" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 80, -1 ); + + try + { + // BuildOptions\\DebugGrammar.g3:80:9: ( INT | ID | '(' expr ')' -> expr | ID '(' expr ')' -> ^( CALL ID expr ) ) + int alt6=4; + try + { + dbg.EnterDecision( 6 ); + + switch ( input.LA(1) ) + { + case INT: + { + alt6=1; + } + break; + case ID: + { + int LA6_2 = input.LA(2); + + if ( (LA6_2==12) ) + { + alt6=4; + } + else if ( (LA6_2==NEWLINE||(LA6_2>=10 && LA6_2<=11)||(LA6_2>=13 && LA6_2<=16)) ) + { + alt6=2; + } + else + { + NoViableAltException nvae = new NoViableAltException("", 6, 2, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + break; + case 12: + { + alt6=3; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 6, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + + } + finally + { + dbg.ExitDecision( 6 ); + } + + switch ( alt6 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugGrammar.g3:80:9: INT + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 80, 8 ); + INT25=(IToken)Match(input,INT,Follow._INT_in_atom348); + INT25_tree = (CommonTree)adaptor.Create(INT25); + adaptor.AddChild(root_0, INT25_tree); + + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\DebugGrammar.g3:81:9: ID + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 81, 8 ); + ID26=(IToken)Match(input,ID,Follow._ID_in_atom358); + ID26_tree = (CommonTree)adaptor.Create(ID26); + adaptor.AddChild(root_0, ID26_tree); + + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\DebugGrammar.g3:82:9: '(' expr ')' + { + dbg.Location( 82, 8 ); + char_literal27=(IToken)Match(input,12,Follow._12_in_atom368); + stream_12.Add(char_literal27); + + dbg.Location( 82, 12 ); + PushFollow(Follow._expr_in_atom370); + expr28=expr(); + + state._fsp--; + + stream_expr.Add(expr28.Tree); + dbg.Location( 82, 17 ); + char_literal29=(IToken)Match(input,13,Follow._13_in_atom372); + stream_13.Add(char_literal29); + + + + { + // AST REWRITE + // elements: expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 82:25: -> expr + { + dbg.Location( 82, 27 ); + adaptor.AddChild(root_0, stream_expr.NextTree()); + + } + + retval.tree = root_0; + } + + } + break; + case 4: + dbg.EnterAlt( 4 ); + + // BuildOptions\\DebugGrammar.g3:83:9: ID '(' expr ')' + { + dbg.Location( 83, 8 ); + ID30=(IToken)Match(input,ID,Follow._ID_in_atom389); + stream_ID.Add(ID30); + + dbg.Location( 83, 11 ); + char_literal31=(IToken)Match(input,12,Follow._12_in_atom391); + stream_12.Add(char_literal31); + + dbg.Location( 83, 15 ); + PushFollow(Follow._expr_in_atom393); + expr32=expr(); + + state._fsp--; + + stream_expr.Add(expr32.Tree); + dbg.Location( 83, 20 ); + char_literal33=(IToken)Match(input,13,Follow._13_in_atom395); + stream_13.Add(char_literal33); + + + + { + // AST REWRITE + // elements: ID, expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 83:25: -> ^( CALL ID expr ) + { + dbg.Location( 83, 27 ); + // BuildOptions\\DebugGrammar.g3:83:28: ^( CALL ID expr ) + { + CommonTree root_1 = (CommonTree)adaptor.Nil(); + dbg.Location( 83, 29 ); + root_1 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(CALL, "CALL"), root_1); + + dbg.Location( 83, 34 ); + adaptor.AddChild(root_1, stream_ID.NextNode()); + dbg.Location( 83, 37 ); + adaptor.AddChild(root_1, stream_expr.NextTree()); + + adaptor.AddChild(root_0, root_1); + } + + } + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(84, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "atom" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "atom" + #endregion Rules + + + #region DFA + DFA2 dfa2; + + protected override void InitDFAs() + { + base.InitDFAs(); + dfa2 = new DFA2( this ); + } + + class DFA2 : DFA + { + + const string DFA2_eotS = + "\xA\xFFFF"; + const string DFA2_eofS = + "\xA\xFFFF"; + const string DFA2_minS = + "\x1\x6\x1\xFFFF\x1\x8\x1\xFFFF\x1\x6\x1\xFFFF\x2\xA\x1\x8\x1\xFFFF"; + const string DFA2_maxS = + "\x1\xC\x1\xFFFF\x1\x11\x1\xFFFF\x1\xC\x1\xFFFF\x2\x10\x1\x11\x1\xFFFF"; + const string DFA2_acceptS = + "\x1\xFFFF\x1\x1\x1\xFFFF\x1\x4\x1\xFFFF\x1\x2\x3\xFFFF\x1\x3"; + const string DFA2_specialS = + "\xA\xFFFF}>"; + static readonly string[] DFA2_transitionS = + { + "\x1\x2\x1\x1\x1\x3\x3\xFFFF\x1\x1", + "", + "\x1\x1\x1\xFFFF\x2\x1\x1\x4\x1\xFFFF\x3\x1\x1\x5", + "", + "\x1\x7\x1\x6\x4\xFFFF\x1\x1", + "", + "\x2\x1\x1\xFFFF\x1\x8\x3\x1", + "\x3\x1\x1\x8\x3\x1", + "\x1\x1\x1\xFFFF\x2\x1\x2\xFFFF\x3\x1\x1\x9", + "" + }; + + static readonly short[] DFA2_eot = DFA.UnpackEncodedString(DFA2_eotS); + static readonly short[] DFA2_eof = DFA.UnpackEncodedString(DFA2_eofS); + static readonly char[] DFA2_min = DFA.UnpackEncodedStringToUnsignedChars(DFA2_minS); + static readonly char[] DFA2_max = DFA.UnpackEncodedStringToUnsignedChars(DFA2_maxS); + static readonly short[] DFA2_accept = DFA.UnpackEncodedString(DFA2_acceptS); + static readonly short[] DFA2_special = DFA.UnpackEncodedString(DFA2_specialS); + static readonly short[][] DFA2_transition; + + static DFA2() + { + int numStates = DFA2_transitionS.Length; + DFA2_transition = new short[numStates][]; + for ( int i=0; i < numStates; i++ ) + { + DFA2_transition[i] = DFA.UnpackEncodedString(DFA2_transitionS[i]); + } + } + + public DFA2( BaseRecognizer recognizer ) + { + this.recognizer = recognizer; + this.decisionNumber = 2; + this.eot = DFA2_eot; + this.eof = DFA2_eof; + this.min = DFA2_min; + this.max = DFA2_max; + this.accept = DFA2_accept; + this.special = DFA2_special; + this.transition = DFA2_transition; + } + public override string GetDescription() + { + return "53:0: stat : ( expr NEWLINE -> expr | ID '=' expr NEWLINE -> ^( '=' ID expr ) | func NEWLINE -> func | NEWLINE ->);"; + } + public override void Error( NoViableAltException nvae ) + { + ((DebugParser)recognizer).dbg.RecognitionException( nvae ); + } + } + + + #endregion DFA + + #region Follow sets + private static class Follow + { + public static readonly BitSet _stat_in_prog53 = new BitSet(new ulong[]{0x11C2UL}); + public static readonly BitSet _expr_in_stat70 = new BitSet(new ulong[]{0x100UL}); + public static readonly BitSet _NEWLINE_in_stat72 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_stat105 = new BitSet(new ulong[]{0x20000UL}); + public static readonly BitSet _17_in_stat107 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_stat109 = new BitSet(new ulong[]{0x100UL}); + public static readonly BitSet _NEWLINE_in_stat111 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _func_in_stat143 = new BitSet(new ulong[]{0x100UL}); + public static readonly BitSet _NEWLINE_in_stat145 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _NEWLINE_in_stat178 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_func219 = new BitSet(new ulong[]{0x1000UL}); + public static readonly BitSet _12_in_func222 = new BitSet(new ulong[]{0xC0UL}); + public static readonly BitSet _formalPar_in_func224 = new BitSet(new ulong[]{0x2000UL}); + public static readonly BitSet _13_in_func226 = new BitSet(new ulong[]{0x20000UL}); + public static readonly BitSet _17_in_func228 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_func230 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _set_in_formalPar267 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _multExpr_in_expr288 = new BitSet(new ulong[]{0x10402UL}); + public static readonly BitSet _16_in_expr292 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _10_in_expr295 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _multExpr_in_expr299 = new BitSet(new ulong[]{0x10402UL}); + public static readonly BitSet _atom_in_multExpr320 = new BitSet(new ulong[]{0xC802UL}); + public static readonly BitSet _set_in_multExpr323 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _atom_in_multExpr332 = new BitSet(new ulong[]{0xC802UL}); + public static readonly BitSet _INT_in_atom348 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_atom358 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _12_in_atom368 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_atom370 = new BitSet(new ulong[]{0x2000UL}); + public static readonly BitSet _13_in_atom372 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_atom389 = new BitSet(new ulong[]{0x1000UL}); + public static readonly BitSet _12_in_atom391 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_atom393 = new BitSet(new ulong[]{0x2000UL}); + public static readonly BitSet _13_in_atom395 = new BitSet(new ulong[]{0x2UL}); + + } + #endregion Follow sets +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarParserHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarParserHelper.cs new file mode 100644 index 0000000..95beb20 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugGrammarParserHelper.cs @@ -0,0 +1,40 @@ +/* + * [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. + */ + +using System.Collections.Generic; +using Antlr.Runtime.Tree; + +partial class DebugGrammarParser +{ + /** List of function definitions. Must point at the FUNC nodes. */ + List<CommonTree> functionDefinitions = new List<CommonTree>(); +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammar.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammar.cs new file mode 100644 index 0000000..c9122e5 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammar.cs @@ -0,0 +1,845 @@ +// $ANTLR 3.1.2 BuildOptions\\DebugTreeGrammar.g3 2009-09-30 13:18:15 + +// The variable 'variable' is assigned but its value is never used. +#pragma warning disable 219 +// Unreachable code detected. +#pragma warning disable 162 + + +//import java.util.Map; +//import java.util.HashMap; +using BigInteger = java.math.BigInteger; +using Console = System.Console; + + +using System.Collections.Generic; +using Antlr.Runtime; +using Antlr.Runtime.Tree; +using RewriteRuleITokenStream = Antlr.Runtime.Tree.RewriteRuleTokenStream;using Stack = System.Collections.Generic.Stack<object>; +using List = System.Collections.IList; +using ArrayList = System.Collections.Generic.List<object>; + +using Antlr.Runtime.Debug; +using IOException = System.IO.IOException; +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "3.1.2")] +[System.CLSCompliant(false)] +public partial class DebugTreeGrammar : DebugTreeParser +{ + internal static readonly string[] tokenNames = new string[] { + "<invalid>", "<EOR>", "<DOWN>", "<UP>", "CALL", "FUNC", "ID", "INT", "NEWLINE", "WS", "'-'", "'%'", "'('", "')'", "'*'", "'/'", "'+'", "'='" + }; + public const int EOF=-1; + public const int T__10=10; + public const int T__11=11; + public const int T__12=12; + public const int T__13=13; + public const int T__14=14; + public const int T__15=15; + public const int T__16=16; + public const int T__17=17; + public const int CALL=4; + public const int FUNC=5; + public const int ID=6; + public const int INT=7; + public const int NEWLINE=8; + public const int WS=9; + + // delegates + // delegators + + public static readonly string[] ruleNames = + new string[] + { + "invalidRule", "call", "expr", "prog", "stat" + }; + + int ruleLevel = 0; + public virtual int RuleLevel { get { return ruleLevel; } } + public virtual void IncRuleLevel() { ruleLevel++; } + public virtual void DecRuleLevel() { ruleLevel--; } + public DebugTreeGrammar( ITreeNodeStream input ) + : this( input, DebugEventSocketProxy.DefaultDebuggerPort, new RecognizerSharedState() ) + { + } + public DebugTreeGrammar( ITreeNodeStream input, int port, RecognizerSharedState state ) + : base( input, state ) + { + DebugEventSocketProxy proxy = new DebugEventSocketProxy( this, port, input.TreeAdaptor ); + DebugListener = proxy; + try + { + proxy.Handshake(); + } + catch ( IOException ioe ) + { + ReportError( ioe ); + } + } + public DebugTreeGrammar( ITreeNodeStream input, IDebugEventListener dbg ) + : base( input, dbg, new RecognizerSharedState() ) + { + + } + protected virtual bool EvalPredicate( bool result, string predicate ) + { + dbg.SemanticPredicate( result, predicate ); + return result; + } + + + public override string[] TokenNames { get { return DebugTreeGrammar.tokenNames; } } + public override string GrammarFileName { get { return "BuildOptions\\DebugTreeGrammar.g3"; } } + + + #region Rules + + // $ANTLR start "prog" + // BuildOptions\\DebugTreeGrammar.g3:53:0: prog : ( stat )* ; + private void prog( ) + { + try + { + dbg.EnterRule( GrammarFileName, "prog" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 53, -1 ); + + try + { + // BuildOptions\\DebugTreeGrammar.g3:53:9: ( ( stat )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugTreeGrammar.g3:53:9: ( stat )* + { + dbg.Location( 53, 8 ); + // BuildOptions\\DebugTreeGrammar.g3:53:9: ( stat )* + try + { + dbg.EnterSubRule( 1 ); + + for ( ; ; ) + { + int alt1=2; + try + { + dbg.EnterDecision( 1 ); + + int LA1_0 = input.LA(1); + + if ( ((LA1_0>=CALL && LA1_0<=INT)||(LA1_0>=10 && LA1_0<=11)||(LA1_0>=14 && LA1_0<=17)) ) + { + alt1=1; + } + + + } + finally + { + dbg.ExitDecision( 1 ); + } + + switch ( alt1 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugTreeGrammar.g3:53:0: stat + { + dbg.Location( 53, 8 ); + PushFollow(Follow._stat_in_prog48); + stat(); + + state._fsp--; + + + } + break; + + default: + goto loop1; + } + } + + loop1: + ; + + } + finally + { + dbg.ExitSubRule( 1 ); + } + + + } + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(54, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "prog" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return ; + } + // $ANTLR end "prog" + + + // $ANTLR start "stat" + // BuildOptions\\DebugTreeGrammar.g3:56:0: stat : ( expr | ^( '=' ID expr ) | ^( FUNC ( . )+ ) ); + private void stat( ) + { + CommonTree ID2=null; + BigInteger expr1 = default(BigInteger); + BigInteger expr3 = default(BigInteger); + + try + { + dbg.EnterRule( GrammarFileName, "stat" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 56, -1 ); + + try + { + // BuildOptions\\DebugTreeGrammar.g3:56:9: ( expr | ^( '=' ID expr ) | ^( FUNC ( . )+ ) ) + int alt3=3; + try + { + dbg.EnterDecision( 3 ); + + switch ( input.LA(1) ) + { + case CALL: + case ID: + case INT: + case 10: + case 11: + case 14: + case 15: + case 16: + { + alt3=1; + } + break; + case 17: + { + alt3=2; + } + break; + case FUNC: + { + alt3=3; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 3, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + + } + finally + { + dbg.ExitDecision( 3 ); + } + + switch ( alt3 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugTreeGrammar.g3:56:9: expr + { + dbg.Location( 56, 8 ); + PushFollow(Follow._expr_in_stat63); + expr1=expr(); + + state._fsp--; + + dbg.Location( 56, 35 ); + string result = expr1.ToString(); + Console.Out.WriteLine(expr1 + " (about " + result[0] + "*10^" + (result.Length-1) + ")"); + + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\DebugTreeGrammar.g3:59:9: ^( '=' ID expr ) + { + dbg.Location( 59, 8 ); + dbg.Location( 59, 10 ); + Match(input,17,Follow._17_in_stat98); + + Match(input, TokenTypes.Down, null); + dbg.Location( 59, 14 ); + ID2=(CommonTree)Match(input,ID,Follow._ID_in_stat100); + dbg.Location( 59, 17 ); + PushFollow(Follow._expr_in_stat102); + expr3=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 59, 35 ); + globalMemory[(ID2!=null?ID2.Text:null)] = expr3; + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\DebugTreeGrammar.g3:60:9: ^( FUNC ( . )+ ) + { + dbg.Location( 60, 8 ); + dbg.Location( 60, 10 ); + Match(input,FUNC,Follow._FUNC_in_stat128); + + Match(input, TokenTypes.Down, null); + dbg.Location( 60, 15 ); + // BuildOptions\\DebugTreeGrammar.g3:60:16: ( . )+ + int cnt2=0; + try + { + dbg.EnterSubRule( 2 ); + + for ( ; ; ) + { + int alt2=2; + try + { + dbg.EnterDecision( 2 ); + + int LA2_0 = input.LA(1); + + if ( ((LA2_0>=CALL && LA2_0<=17)) ) + { + alt2=1; + } + else if ( (LA2_0==UP) ) + { + alt2=2; + } + + + } + finally + { + dbg.ExitDecision( 2 ); + } + + switch ( alt2 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugTreeGrammar.g3:60:0: . + { + dbg.Location( 60, 15 ); + MatchAny(input); + + } + break; + + default: + if ( cnt2 >= 1 ) + goto loop2; + + EarlyExitException eee2 = new EarlyExitException( 2, input ); + dbg.RecognitionException( eee2 ); + + throw eee2; + } + cnt2++; + } + loop2: + ; + + } + finally + { + dbg.ExitSubRule( 2 ); + } + + + Match(input, TokenTypes.Up, null); + + } + break; + + } + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(61, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "stat" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return ; + } + // $ANTLR end "stat" + + + // $ANTLR start "expr" + // BuildOptions\\DebugTreeGrammar.g3:63:0: expr returns [BigInteger value] : ( ^( '+' a= expr b= expr ) | ^( '-' a= expr b= expr ) | ^( '*' a= expr b= expr ) | ^( '/' a= expr b= expr ) | ^( '%' a= expr b= expr ) | ID | INT | call ); + private BigInteger expr( ) + { + BigInteger value = default(BigInteger); + + CommonTree ID4=null; + CommonTree INT5=null; + BigInteger a = default(BigInteger); + BigInteger b = default(BigInteger); + BigInteger call6 = default(BigInteger); + + try + { + dbg.EnterRule( GrammarFileName, "expr" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 63, -1 ); + + try + { + // BuildOptions\\DebugTreeGrammar.g3:64:9: ( ^( '+' a= expr b= expr ) | ^( '-' a= expr b= expr ) | ^( '*' a= expr b= expr ) | ^( '/' a= expr b= expr ) | ^( '%' a= expr b= expr ) | ID | INT | call ) + int alt4=8; + try + { + dbg.EnterDecision( 4 ); + + switch ( input.LA(1) ) + { + case 16: + { + alt4=1; + } + break; + case 10: + { + alt4=2; + } + break; + case 14: + { + alt4=3; + } + break; + case 15: + { + alt4=4; + } + break; + case 11: + { + alt4=5; + } + break; + case ID: + { + alt4=6; + } + break; + case INT: + { + alt4=7; + } + break; + case CALL: + { + alt4=8; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 4, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + + } + finally + { + dbg.ExitDecision( 4 ); + } + + switch ( alt4 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugTreeGrammar.g3:64:9: ^( '+' a= expr b= expr ) + { + dbg.Location( 64, 8 ); + dbg.Location( 64, 10 ); + Match(input,16,Follow._16_in_expr172); + + Match(input, TokenTypes.Down, null); + dbg.Location( 64, 15 ); + PushFollow(Follow._expr_in_expr176); + a=expr(); + + state._fsp--; + + dbg.Location( 64, 22 ); + PushFollow(Follow._expr_in_expr180); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 64, 35 ); + value = a.add(b); + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\DebugTreeGrammar.g3:65:9: ^( '-' a= expr b= expr ) + { + dbg.Location( 65, 8 ); + dbg.Location( 65, 10 ); + Match(input,10,Follow._10_in_expr200); + + Match(input, TokenTypes.Down, null); + dbg.Location( 65, 15 ); + PushFollow(Follow._expr_in_expr204); + a=expr(); + + state._fsp--; + + dbg.Location( 65, 22 ); + PushFollow(Follow._expr_in_expr208); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 65, 35 ); + value = a.subtract(b); + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\DebugTreeGrammar.g3:66:9: ^( '*' a= expr b= expr ) + { + dbg.Location( 66, 8 ); + dbg.Location( 66, 10 ); + Match(input,14,Follow._14_in_expr228); + + Match(input, TokenTypes.Down, null); + dbg.Location( 66, 15 ); + PushFollow(Follow._expr_in_expr232); + a=expr(); + + state._fsp--; + + dbg.Location( 66, 22 ); + PushFollow(Follow._expr_in_expr236); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 66, 35 ); + value = a.multiply(b); + + } + break; + case 4: + dbg.EnterAlt( 4 ); + + // BuildOptions\\DebugTreeGrammar.g3:67:9: ^( '/' a= expr b= expr ) + { + dbg.Location( 67, 8 ); + dbg.Location( 67, 10 ); + Match(input,15,Follow._15_in_expr256); + + Match(input, TokenTypes.Down, null); + dbg.Location( 67, 15 ); + PushFollow(Follow._expr_in_expr260); + a=expr(); + + state._fsp--; + + dbg.Location( 67, 22 ); + PushFollow(Follow._expr_in_expr264); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 67, 35 ); + value = a.divide(b); + + } + break; + case 5: + dbg.EnterAlt( 5 ); + + // BuildOptions\\DebugTreeGrammar.g3:68:9: ^( '%' a= expr b= expr ) + { + dbg.Location( 68, 8 ); + dbg.Location( 68, 10 ); + Match(input,11,Follow._11_in_expr284); + + Match(input, TokenTypes.Down, null); + dbg.Location( 68, 15 ); + PushFollow(Follow._expr_in_expr288); + a=expr(); + + state._fsp--; + + dbg.Location( 68, 22 ); + PushFollow(Follow._expr_in_expr292); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 68, 35 ); + value = a.remainder(b); + + } + break; + case 6: + dbg.EnterAlt( 6 ); + + // BuildOptions\\DebugTreeGrammar.g3:69:9: ID + { + dbg.Location( 69, 8 ); + ID4=(CommonTree)Match(input,ID,Follow._ID_in_expr311); + dbg.Location( 69, 35 ); + value = getValue((ID4!=null?ID4.Text:null)); + + } + break; + case 7: + dbg.EnterAlt( 7 ); + + // BuildOptions\\DebugTreeGrammar.g3:70:9: INT + { + dbg.Location( 70, 8 ); + INT5=(CommonTree)Match(input,INT,Follow._INT_in_expr347); + dbg.Location( 70, 35 ); + value = new BigInteger((INT5!=null?INT5.Text:null)); + + } + break; + case 8: + dbg.EnterAlt( 8 ); + + // BuildOptions\\DebugTreeGrammar.g3:71:9: call + { + dbg.Location( 71, 8 ); + PushFollow(Follow._call_in_expr382); + call6=call(); + + state._fsp--; + + dbg.Location( 71, 35 ); + value = call6; + + } + break; + + } + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(72, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "expr" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return value; + } + // $ANTLR end "expr" + + + // $ANTLR start "call" + // BuildOptions\\DebugTreeGrammar.g3:74:0: call returns [BigInteger value] : ^( CALL ID expr ) ; + private BigInteger call( ) + { + BigInteger value = default(BigInteger); + + CommonTree ID8=null; + BigInteger expr7 = default(BigInteger); + + try + { + dbg.EnterRule( GrammarFileName, "call" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 74, -1 ); + + try + { + // BuildOptions\\DebugTreeGrammar.g3:75:9: ( ^( CALL ID expr ) ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\DebugTreeGrammar.g3:75:9: ^( CALL ID expr ) + { + dbg.Location( 75, 8 ); + dbg.Location( 75, 10 ); + Match(input,CALL,Follow._CALL_in_call430); + + Match(input, TokenTypes.Down, null); + dbg.Location( 75, 15 ); + ID8=(CommonTree)Match(input,ID,Follow._ID_in_call432); + dbg.Location( 75, 18 ); + PushFollow(Follow._expr_in_call434); + expr7=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 75, 35 ); + BigInteger p = expr7; + CommonTree funcRoot = findFunction((ID8!=null?ID8.Text:null), p); + if (funcRoot == null) { + Console.Error.WriteLine("No match found for " + (ID8!=null?ID8.Text:null) + "(" + p + ")"); + } else { + // Here we set up the local evaluator to run over the + // function definition with the parameter value. + // This re-reads a sub-AST of our input AST! + DebugTreeGrammar e = new DebugTreeGrammar(funcRoot, functionDefinitions, globalMemory, p); + value = e.expr(); + } + + + } + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(87, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "call" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return value; + } + // $ANTLR end "call" + #endregion Rules + + + #region Follow sets + private static class Follow + { + public static readonly BitSet _stat_in_prog48 = new BitSet(new ulong[]{0x3CCF2UL}); + public static readonly BitSet _expr_in_stat63 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _17_in_stat98 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _ID_in_stat100 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_stat102 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _FUNC_in_stat128 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _16_in_expr172 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr176 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr180 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _10_in_expr200 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr204 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr208 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _14_in_expr228 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr232 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr236 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _15_in_expr256 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr260 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr264 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _11_in_expr284 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr288 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr292 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _ID_in_expr311 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _INT_in_expr347 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _call_in_expr382 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _CALL_in_call430 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _ID_in_call432 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_call434 = new BitSet(new ulong[]{0x8UL}); + + } + #endregion Follow sets +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammar.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammar.g3 new file mode 100644 index 0000000..b16a73e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammar.g3 @@ -0,0 +1,88 @@ +/* + * [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. + */ + +tree grammar DebugTreeGrammar; + +options +{ + language=CSharp3; + tokenVocab=DebugGrammar; + ASTLabelType=CommonTree; +} + +// START:members +@header +{ +//import java.util.Map; +//import java.util.HashMap; +using BigInteger = java.math.BigInteger; +using Console = System.Console; +} +// END:members + +// START:rules +prog: stat* + ; + +stat: expr { string result = $expr.value.ToString(); + Console.Out.WriteLine($expr.value + " (about " + result[0] + "*10^" + (result.Length-1) + ")"); + } + | ^('=' ID expr) { globalMemory[$ID.text] = $expr.value; } + | ^(FUNC .+) // ignore FUNCs - we added them to functionDefinitions already in parser. + ; + +expr returns [BigInteger value] + : ^('+' a=expr b=expr) { $value = $a.value.add($b.value); } + | ^('-' a=expr b=expr) { $value = $a.value.subtract($b.value); } + | ^('*' a=expr b=expr) { $value = $a.value.multiply($b.value); } + | ^('/' a=expr b=expr) { $value = $a.value.divide($b.value); } + | ^('%' a=expr b=expr) { $value = $a.value.remainder($b.value); } + | ID { $value = getValue($ID.text); } + | INT { $value = new BigInteger($INT.text); } + | call { $value = $call.value; } + ; + +call returns [BigInteger value] + : ^(CALL ID expr) { BigInteger p = $expr.value; + CommonTree funcRoot = findFunction($ID.text, p); + if (funcRoot == null) { + Console.Error.WriteLine("No match found for " + $ID.text + "(" + p + ")"); + } else { + // Here we set up the local evaluator to run over the + // function definition with the parameter value. + // This re-reads a sub-AST of our input AST! + DebugTreeGrammar e = new DebugTreeGrammar(funcRoot, functionDefinitions, globalMemory, p); + $value = e.expr(); + } + } + ; +// END:rules diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammarHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammarHelper.cs new file mode 100644 index 0000000..af83214 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/DebugTreeGrammarHelper.cs @@ -0,0 +1,116 @@ +/* + * [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. + */ + +using System.Collections.Generic; +using Antlr.Runtime.Tree; + +using BigInteger = java.math.BigInteger; +using Console = System.Console; + +partial class DebugTreeGrammar +{ + /** Points to functions tracked by tree builder. */ + private List<CommonTree> functionDefinitions; + + /** Remember local variables. Currently, this is only the function parameter. + */ + private readonly IDictionary<string, BigInteger> localMemory = new Dictionary<string, BigInteger>(); + + /** Remember global variables set by =. */ + private IDictionary<string, BigInteger> globalMemory = new Dictionary<string, BigInteger>(); + + /** Set up an evaluator with a node stream; and a set of function definition ASTs. */ + public DebugTreeGrammar( CommonTreeNodeStream nodes, List<CommonTree> functionDefinitions ) + : this( nodes ) + { + this.functionDefinitions = functionDefinitions; + } + + /** Set up a local evaluator for a nested function call. The evaluator gets the definition + * tree of the function; the set of all defined functions (to find locally called ones); a + * pointer to the global variable memory; and the value of the function parameter to be + * added to the local memory. + */ + private DebugTreeGrammar( CommonTree function, + List<CommonTree> functionDefinitions, + IDictionary<string, BigInteger> globalMemory, + BigInteger paramValue ) + // Expected tree for function: ^(FUNC ID ( INT | ID ) expr) + : this( new CommonTreeNodeStream( function.GetChild( 2 ) ), functionDefinitions ) + { + this.globalMemory = globalMemory; + localMemory[function.GetChild( 1 ).Text] = paramValue; + } + + /** Find matching function definition for a function name and parameter + * value. The first definition is returned where (a) the name matches + * and (b) the formal parameter agrees if it is defined as constant. + */ + private CommonTree findFunction( string name, BigInteger paramValue ) + { + foreach ( CommonTree f in functionDefinitions ) + { + // Expected tree for f: ^(FUNC ID (ID | INT) expr) + if ( f.GetChild( 0 ).Text.Equals( name ) ) + { + // Check whether parameter matches + CommonTree formalPar = (CommonTree)f.GetChild( 1 ); + if ( formalPar.Token.Type == INT + && !new BigInteger( formalPar.Token.Text ).Equals( paramValue ) ) + { + // Constant in formalPar list does not match actual value -> no match. + continue; + } + // Parameter (value for INT formal arg) as well as fct name agrees! + return f; + } + } + return null; + } + + /** Get value of name up call stack. */ + internal BigInteger getValue( string name ) + { + BigInteger value; + if ( localMemory.TryGetValue( name, out value ) && value != null ) + { + return value; + } + if ( globalMemory.TryGetValue( name, out value ) && value != null ) + { + return value; + } + // not found in local memory or global memory + Console.Error.WriteLine( "undefined variable " + name ); + return new BigInteger( "0" ); + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammar.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammar.g3 new file mode 100644 index 0000000..5f8de16 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammar.g3 @@ -0,0 +1,100 @@ +/* + * [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. + */ + +grammar ProfileGrammar; + +options +{ + language=CSharp3; + output=AST; + ASTLabelType=CommonTree; +} + +tokens +{ + // define pseudo-operations + FUNC; + CALL; +} + +// START:stat +prog: ( stat )* + ; + +stat: expr NEWLINE -> expr + | ID '=' expr NEWLINE -> ^('=' ID expr) + | func NEWLINE -> func + | NEWLINE -> // ignore + ; + +func: ID '(' formalPar ')' '=' expr -> ^(FUNC ID formalPar expr) + ; + finally { + functionDefinitions.Add($func.tree); + } + +formalPar + : ID + | INT + ; + +// END:stat + +// START:expr +expr: multExpr (('+'^|'-'^) multExpr)* + ; + +multExpr + : atom (('*'|'/'|'%')^ atom)* + ; + +atom: INT + | ID + | '(' expr ')' -> expr + | ID '(' expr ')' -> ^(CALL ID expr) + ; +// END:expr + +// START:tokens +ID : ('a'..'z'|'A'..'Z')+ + ; + +INT : '0'..'9'+ + ; + +NEWLINE + : '\r'? '\n' + ; + +WS : (' '|'\t')+ { Skip(); } + ; +// END:tokens diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarLexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarLexer.cs new file mode 100644 index 0000000..dae1ef4 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarLexer.cs @@ -0,0 +1,693 @@ +// $ANTLR 3.1.2 BuildOptions\\ProfileGrammar.g3 2009-09-30 13:18:18 + +// The variable 'variable' is assigned but its value is never used. +#pragma warning disable 219 +// Unreachable code detected. +#pragma warning disable 162 + + +using System.Collections.Generic; +using Antlr.Runtime; +using Stack = System.Collections.Generic.Stack<object>; +using List = System.Collections.IList; +using ArrayList = System.Collections.Generic.List<object>; + +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "3.1.2")] +[System.CLSCompliant(false)] +public partial class ProfileGrammarLexer : Lexer +{ + public const int EOF=-1; + public const int T__10=10; + public const int T__11=11; + public const int T__12=12; + public const int T__13=13; + public const int T__14=14; + public const int T__15=15; + public const int T__16=16; + public const int T__17=17; + public const int CALL=4; + public const int FUNC=5; + public const int ID=6; + public const int INT=7; + public const int NEWLINE=8; + public const int WS=9; + + // delegates + // delegators + + public ProfileGrammarLexer() {} + public ProfileGrammarLexer( ICharStream input ) + : this( input, new RecognizerSharedState() ) + { + } + public ProfileGrammarLexer( ICharStream input, RecognizerSharedState state ) + : base( input, state ) + { + + } + public override string GrammarFileName { get { return "BuildOptions\\ProfileGrammar.g3"; } } + + // $ANTLR start "T__10" + private void mT__10() + { + try + { + int _type = T__10; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:7:9: ( '-' ) + // BuildOptions\\ProfileGrammar.g3:7:9: '-' + { + Match('-'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__10" + + // $ANTLR start "T__11" + private void mT__11() + { + try + { + int _type = T__11; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:8:9: ( '%' ) + // BuildOptions\\ProfileGrammar.g3:8:9: '%' + { + Match('%'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__11" + + // $ANTLR start "T__12" + private void mT__12() + { + try + { + int _type = T__12; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:9:9: ( '(' ) + // BuildOptions\\ProfileGrammar.g3:9:9: '(' + { + Match('('); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__12" + + // $ANTLR start "T__13" + private void mT__13() + { + try + { + int _type = T__13; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:10:9: ( ')' ) + // BuildOptions\\ProfileGrammar.g3:10:9: ')' + { + Match(')'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__13" + + // $ANTLR start "T__14" + private void mT__14() + { + try + { + int _type = T__14; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:11:9: ( '*' ) + // BuildOptions\\ProfileGrammar.g3:11:9: '*' + { + Match('*'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__14" + + // $ANTLR start "T__15" + private void mT__15() + { + try + { + int _type = T__15; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:12:9: ( '/' ) + // BuildOptions\\ProfileGrammar.g3:12:9: '/' + { + Match('/'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__15" + + // $ANTLR start "T__16" + private void mT__16() + { + try + { + int _type = T__16; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:13:9: ( '+' ) + // BuildOptions\\ProfileGrammar.g3:13:9: '+' + { + Match('+'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__16" + + // $ANTLR start "T__17" + private void mT__17() + { + try + { + int _type = T__17; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:14:9: ( '=' ) + // BuildOptions\\ProfileGrammar.g3:14:9: '=' + { + Match('='); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "T__17" + + // $ANTLR start "ID" + private void mID() + { + try + { + int _type = ID; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:88:9: ( ( 'a' .. 'z' | 'A' .. 'Z' )+ ) + // BuildOptions\\ProfileGrammar.g3:88:9: ( 'a' .. 'z' | 'A' .. 'Z' )+ + { + // BuildOptions\\ProfileGrammar.g3:88:9: ( 'a' .. 'z' | 'A' .. 'Z' )+ + int cnt1=0; + for ( ; ; ) + { + int alt1=2; + int LA1_0 = input.LA(1); + + if ( ((LA1_0>='A' && LA1_0<='Z')||(LA1_0>='a' && LA1_0<='z')) ) + { + alt1=1; + } + + + switch ( alt1 ) + { + case 1: + // BuildOptions\\ProfileGrammar.g3: + { + input.Consume(); + + + } + break; + + default: + if ( cnt1 >= 1 ) + goto loop1; + + EarlyExitException eee1 = new EarlyExitException( 1, input ); + throw eee1; + } + cnt1++; + } + loop1: + ; + + + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "ID" + + // $ANTLR start "INT" + private void mINT() + { + try + { + int _type = INT; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:91:9: ( ( '0' .. '9' )+ ) + // BuildOptions\\ProfileGrammar.g3:91:9: ( '0' .. '9' )+ + { + // BuildOptions\\ProfileGrammar.g3:91:9: ( '0' .. '9' )+ + int cnt2=0; + for ( ; ; ) + { + int alt2=2; + int LA2_0 = input.LA(1); + + if ( ((LA2_0>='0' && LA2_0<='9')) ) + { + alt2=1; + } + + + switch ( alt2 ) + { + case 1: + // BuildOptions\\ProfileGrammar.g3: + { + input.Consume(); + + + } + break; + + default: + if ( cnt2 >= 1 ) + goto loop2; + + EarlyExitException eee2 = new EarlyExitException( 2, input ); + throw eee2; + } + cnt2++; + } + loop2: + ; + + + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "INT" + + // $ANTLR start "NEWLINE" + private void mNEWLINE() + { + try + { + int _type = NEWLINE; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:95:7: ( ( '\\r' )? '\\n' ) + // BuildOptions\\ProfileGrammar.g3:95:7: ( '\\r' )? '\\n' + { + // BuildOptions\\ProfileGrammar.g3:95:7: ( '\\r' )? + int alt3=2; + int LA3_0 = input.LA(1); + + if ( (LA3_0=='\r') ) + { + alt3=1; + } + switch ( alt3 ) + { + case 1: + // BuildOptions\\ProfileGrammar.g3:95:0: '\\r' + { + Match('\r'); + + } + break; + + } + + Match('\n'); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "NEWLINE" + + // $ANTLR start "WS" + private void mWS() + { + try + { + int _type = WS; + int _channel = DefaultTokenChannel; + // BuildOptions\\ProfileGrammar.g3:98:9: ( ( ' ' | '\\t' )+ ) + // BuildOptions\\ProfileGrammar.g3:98:9: ( ' ' | '\\t' )+ + { + // BuildOptions\\ProfileGrammar.g3:98:9: ( ' ' | '\\t' )+ + int cnt4=0; + for ( ; ; ) + { + int alt4=2; + int LA4_0 = input.LA(1); + + if ( (LA4_0=='\t'||LA4_0==' ') ) + { + alt4=1; + } + + + switch ( alt4 ) + { + case 1: + // BuildOptions\\ProfileGrammar.g3: + { + input.Consume(); + + + } + break; + + default: + if ( cnt4 >= 1 ) + goto loop4; + + EarlyExitException eee4 = new EarlyExitException( 4, input ); + throw eee4; + } + cnt4++; + } + loop4: + ; + + + Skip(); + + } + + state.type = _type; + state.channel = _channel; + } + finally + { + } + } + // $ANTLR end "WS" + + public override void mTokens() + { + // BuildOptions\\ProfileGrammar.g3:1:10: ( T__10 | T__11 | T__12 | T__13 | T__14 | T__15 | T__16 | T__17 | ID | INT | NEWLINE | WS ) + int alt5=12; + switch ( input.LA(1) ) + { + case '-': + { + alt5=1; + } + break; + case '%': + { + alt5=2; + } + break; + case '(': + { + alt5=3; + } + break; + case ')': + { + alt5=4; + } + break; + case '*': + { + alt5=5; + } + break; + case '/': + { + alt5=6; + } + break; + case '+': + { + alt5=7; + } + break; + case '=': + { + alt5=8; + } + break; + case 'A': + case 'B': + case 'C': + case 'D': + case 'E': + case 'F': + case 'G': + case 'H': + case 'I': + case 'J': + case 'K': + case 'L': + case 'M': + case 'N': + case 'O': + case 'P': + case 'Q': + case 'R': + case 'S': + case 'T': + case 'U': + case 'V': + case 'W': + case 'X': + case 'Y': + case 'Z': + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + case 'i': + case 'j': + case 'k': + case 'l': + case 'm': + case 'n': + case 'o': + case 'p': + case 'q': + case 'r': + case 's': + case 't': + case 'u': + case 'v': + case 'w': + case 'x': + case 'y': + case 'z': + { + alt5=9; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + { + alt5=10; + } + break; + case '\n': + case '\r': + { + alt5=11; + } + break; + case '\t': + case ' ': + { + alt5=12; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 5, 0, input); + + throw nvae; + } + } + + switch ( alt5 ) + { + case 1: + // BuildOptions\\ProfileGrammar.g3:1:10: T__10 + { + mT__10(); + + } + break; + case 2: + // BuildOptions\\ProfileGrammar.g3:1:16: T__11 + { + mT__11(); + + } + break; + case 3: + // BuildOptions\\ProfileGrammar.g3:1:22: T__12 + { + mT__12(); + + } + break; + case 4: + // BuildOptions\\ProfileGrammar.g3:1:28: T__13 + { + mT__13(); + + } + break; + case 5: + // BuildOptions\\ProfileGrammar.g3:1:34: T__14 + { + mT__14(); + + } + break; + case 6: + // BuildOptions\\ProfileGrammar.g3:1:40: T__15 + { + mT__15(); + + } + break; + case 7: + // BuildOptions\\ProfileGrammar.g3:1:46: T__16 + { + mT__16(); + + } + break; + case 8: + // BuildOptions\\ProfileGrammar.g3:1:52: T__17 + { + mT__17(); + + } + break; + case 9: + // BuildOptions\\ProfileGrammar.g3:1:58: ID + { + mID(); + + } + break; + case 10: + // BuildOptions\\ProfileGrammar.g3:1:61: INT + { + mINT(); + + } + break; + case 11: + // BuildOptions\\ProfileGrammar.g3:1:65: NEWLINE + { + mNEWLINE(); + + } + break; + case 12: + // BuildOptions\\ProfileGrammar.g3:1:73: WS + { + mWS(); + + } + break; + + } + + } + + + #region DFA + + protected override void InitDFAs() + { + base.InitDFAs(); + } + + + #endregion + +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarLexerHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarLexerHelper.cs new file mode 100644 index 0000000..7271295 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarLexerHelper.cs @@ -0,0 +1,32 @@ +/* + * [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. + */ + diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarParser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarParser.cs new file mode 100644 index 0000000..5cc9872 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarParser.cs @@ -0,0 +1,1560 @@ +// $ANTLR 3.1.2 BuildOptions\\ProfileGrammar.g3 2009-09-30 13:18:17 + +// The variable 'variable' is assigned but its value is never used. +#pragma warning disable 219 +// Unreachable code detected. +#pragma warning disable 162 + + +using System.Collections.Generic; +using Antlr.Runtime; +using Stack = System.Collections.Generic.Stack<object>; +using List = System.Collections.IList; +using ArrayList = System.Collections.Generic.List<object>; + +using Antlr.Runtime.Debug; +using IOException = System.IO.IOException; + +using Antlr.Runtime.Tree; +using RewriteRuleITokenStream = Antlr.Runtime.Tree.RewriteRuleTokenStream; + +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "3.1.2")] +[System.CLSCompliant(false)] +public partial class ProfileGrammarParser : DebugParser +{ + internal static readonly string[] tokenNames = new string[] { + "<invalid>", "<EOR>", "<DOWN>", "<UP>", "CALL", "FUNC", "ID", "INT", "NEWLINE", "WS", "'-'", "'%'", "'('", "')'", "'*'", "'/'", "'+'", "'='" + }; + public const int EOF=-1; + public const int T__10=10; + public const int T__11=11; + public const int T__12=12; + public const int T__13=13; + public const int T__14=14; + public const int T__15=15; + public const int T__16=16; + public const int T__17=17; + public const int CALL=4; + public const int FUNC=5; + public const int ID=6; + public const int INT=7; + public const int NEWLINE=8; + public const int WS=9; + + // delegates + // delegators + + public static readonly string[] ruleNames = + new string[] + { + "invalidRule", "atom", "expr", "formalPar", "func", "multExpr", "prog", + "stat" + }; + + int ruleLevel = 0; + public virtual int RuleLevel { get { return ruleLevel; } } + public virtual void IncRuleLevel() { ruleLevel++; } + public virtual void DecRuleLevel() { ruleLevel--; } + public ProfileGrammarParser( ITokenStream input ) + : this( input, new Profiler(null), new RecognizerSharedState() ) + { + } + public ProfileGrammarParser( ITokenStream input, IDebugEventListener dbg, RecognizerSharedState state ) + : base( input, dbg, state ) + { + Profiler p = (Profiler)dbg; + p.setParser(this); + InitializeTreeAdaptor(); + if ( TreeAdaptor == null ) + TreeAdaptor = new CommonTreeAdaptor(); + ITreeAdaptor adap = new CommonTreeAdaptor(); + TreeAdaptor = adap; + proxy.TreeAdaptor = adap; + } + + public ProfileGrammarParser( ITokenStream input, IDebugEventListener dbg ) + : base( input, dbg ) + { + Profiler p = (Profiler)dbg; + p.setParser(this);InitializeTreeAdaptor(); + if ( TreeAdaptor == null ) + TreeAdaptor = new CommonTreeAdaptor(); + + ITreeAdaptor adap = new CommonTreeAdaptor(); + TreeAdaptor = adap; + + } + public virtual bool AlreadyParsedRule( IIntStream input, int ruleIndex ) + { + ((Profiler)dbg).ExamineRuleMemoization(input, ruleIndex, ProfileGrammarParser.ruleNames[ruleIndex]); + return super.AlreadyParsedRule(input, ruleIndex); + } + + public virtual void Memoize( IIntStream input, int ruleIndex, int ruleStartIndex ) + { + ((Profiler)dbg).Memoize(input, ruleIndex, ruleStartIndex, ProfileGrammarParser.ruleNames[ruleIndex]); + super.Memoize(input, ruleIndex, ruleStartIndex); + } + protected virtual bool EvalPredicate( bool result, string predicate ) + { + dbg.SemanticPredicate( result, predicate ); + return result; + } + + // Implement this function in your helper file to use a custom tree adaptor + partial void InitializeTreeAdaptor(); + protected DebugTreeAdaptor adaptor; + + public ITreeAdaptor TreeAdaptor + { + get + { + return adaptor; + } + set + { + this.adaptor = new DebugTreeAdaptor(dbg,adaptor); + + } + } + + + public override string[] TokenNames { get { return ProfileGrammarParser.tokenNames; } } + public override string GrammarFileName { get { return "BuildOptions\\ProfileGrammar.g3"; } } + + + #region Rules + public class prog_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "prog" + // BuildOptions\\ProfileGrammar.g3:50:0: prog : ( stat )* ; + private ProfileGrammarParser.prog_return prog( ) + { + ProfileGrammarParser.prog_return retval = new ProfileGrammarParser.prog_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + ProfileGrammarParser.stat_return stat1 = default(ProfileGrammarParser.stat_return); + + + try + { + dbg.EnterRule( GrammarFileName, "prog" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 50, -1 ); + + try + { + // BuildOptions\\ProfileGrammar.g3:50:7: ( ( stat )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:50:7: ( stat )* + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 50, 6 ); + // BuildOptions\\ProfileGrammar.g3:50:7: ( stat )* + try + { + dbg.EnterSubRule( 1 ); + + for ( ; ; ) + { + int alt1=2; + try + { + dbg.EnterDecision( 1 ); + + int LA1_0 = input.LA(1); + + if ( ((LA1_0>=ID && LA1_0<=NEWLINE)||LA1_0==12) ) + { + alt1=1; + } + + + } + finally + { + dbg.ExitDecision( 1 ); + } + + switch ( alt1 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:50:9: stat + { + dbg.Location( 50, 8 ); + PushFollow(Follow._stat_in_prog53); + stat1=stat(); + + state._fsp--; + + adaptor.AddChild(root_0, stat1.Tree); + + } + break; + + default: + goto loop1; + } + } + + loop1: + ; + + } + finally + { + dbg.ExitSubRule( 1 ); + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(51, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "prog" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "prog" + + public class stat_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "stat" + // BuildOptions\\ProfileGrammar.g3:53:0: stat : ( expr NEWLINE -> expr | ID '=' expr NEWLINE -> ^( '=' ID expr ) | func NEWLINE -> func | NEWLINE ->); + private ProfileGrammarParser.stat_return stat( ) + { + ProfileGrammarParser.stat_return retval = new ProfileGrammarParser.stat_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken NEWLINE3=null; + IToken ID4=null; + IToken char_literal5=null; + IToken NEWLINE7=null; + IToken NEWLINE9=null; + IToken NEWLINE10=null; + ProfileGrammarParser.expr_return expr2 = default(ProfileGrammarParser.expr_return); + ProfileGrammarParser.expr_return expr6 = default(ProfileGrammarParser.expr_return); + ProfileGrammarParser.func_return func8 = default(ProfileGrammarParser.func_return); + + CommonTree NEWLINE3_tree=null; + CommonTree ID4_tree=null; + CommonTree char_literal5_tree=null; + CommonTree NEWLINE7_tree=null; + CommonTree NEWLINE9_tree=null; + CommonTree NEWLINE10_tree=null; + RewriteRuleITokenStream stream_NEWLINE=new RewriteRuleITokenStream(adaptor,"token NEWLINE"); + RewriteRuleITokenStream stream_ID=new RewriteRuleITokenStream(adaptor,"token ID"); + RewriteRuleITokenStream stream_17=new RewriteRuleITokenStream(adaptor,"token 17"); + RewriteRuleSubtreeStream stream_expr=new RewriteRuleSubtreeStream(adaptor,"rule expr"); + RewriteRuleSubtreeStream stream_func=new RewriteRuleSubtreeStream(adaptor,"rule func"); + try + { + dbg.EnterRule( GrammarFileName, "stat" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 53, -1 ); + + try + { + // BuildOptions\\ProfileGrammar.g3:53:9: ( expr NEWLINE -> expr | ID '=' expr NEWLINE -> ^( '=' ID expr ) | func NEWLINE -> func | NEWLINE ->) + int alt2=4; + try + { + dbg.EnterDecision( 2 ); + + try + { + isCyclicDecision = true; + alt2 = dfa2.Predict(input); + } + catch ( NoViableAltException nvae ) + { + dbg.RecognitionException( nvae ); + throw nvae; + } + } + finally + { + dbg.ExitDecision( 2 ); + } + + switch ( alt2 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:53:9: expr NEWLINE + { + dbg.Location( 53, 8 ); + PushFollow(Follow._expr_in_stat70); + expr2=expr(); + + state._fsp--; + + stream_expr.Add(expr2.Tree); + dbg.Location( 53, 13 ); + NEWLINE3=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat72); + stream_NEWLINE.Add(NEWLINE3); + + + + { + // AST REWRITE + // elements: expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 53:41: -> expr + { + dbg.Location( 53, 43 ); + adaptor.AddChild(root_0, stream_expr.NextTree()); + + } + + retval.tree = root_0; + } + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\ProfileGrammar.g3:54:9: ID '=' expr NEWLINE + { + dbg.Location( 54, 8 ); + ID4=(IToken)Match(input,ID,Follow._ID_in_stat105); + stream_ID.Add(ID4); + + dbg.Location( 54, 11 ); + char_literal5=(IToken)Match(input,17,Follow._17_in_stat107); + stream_17.Add(char_literal5); + + dbg.Location( 54, 15 ); + PushFollow(Follow._expr_in_stat109); + expr6=expr(); + + state._fsp--; + + stream_expr.Add(expr6.Tree); + dbg.Location( 54, 20 ); + NEWLINE7=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat111); + stream_NEWLINE.Add(NEWLINE7); + + + + { + // AST REWRITE + // elements: 17, ID, expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 54:41: -> ^( '=' ID expr ) + { + dbg.Location( 54, 43 ); + // BuildOptions\\ProfileGrammar.g3:54:44: ^( '=' ID expr ) + { + CommonTree root_1 = (CommonTree)adaptor.Nil(); + dbg.Location( 54, 45 ); + root_1 = (CommonTree)adaptor.BecomeRoot(stream_17.NextNode(), root_1); + + dbg.Location( 54, 49 ); + adaptor.AddChild(root_1, stream_ID.NextNode()); + dbg.Location( 54, 52 ); + adaptor.AddChild(root_1, stream_expr.NextTree()); + + adaptor.AddChild(root_0, root_1); + } + + } + + retval.tree = root_0; + } + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\ProfileGrammar.g3:55:9: func NEWLINE + { + dbg.Location( 55, 8 ); + PushFollow(Follow._func_in_stat143); + func8=func(); + + state._fsp--; + + stream_func.Add(func8.Tree); + dbg.Location( 55, 13 ); + NEWLINE9=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat145); + stream_NEWLINE.Add(NEWLINE9); + + + + { + // AST REWRITE + // elements: func + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 55:41: -> func + { + dbg.Location( 55, 43 ); + adaptor.AddChild(root_0, stream_func.NextTree()); + + } + + retval.tree = root_0; + } + + } + break; + case 4: + dbg.EnterAlt( 4 ); + + // BuildOptions\\ProfileGrammar.g3:56:9: NEWLINE + { + dbg.Location( 56, 8 ); + NEWLINE10=(IToken)Match(input,NEWLINE,Follow._NEWLINE_in_stat178); + stream_NEWLINE.Add(NEWLINE10); + + + + { + // AST REWRITE + // elements: + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 56:41: -> + { + dbg.Location( 57, 4 ); + root_0 = null; + } + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(57, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "stat" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "stat" + + public class func_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "func" + // BuildOptions\\ProfileGrammar.g3:59:0: func : ID '(' formalPar ')' '=' expr -> ^( FUNC ID formalPar expr ) ; + private ProfileGrammarParser.func_return func( ) + { + ProfileGrammarParser.func_return retval = new ProfileGrammarParser.func_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken ID11=null; + IToken char_literal12=null; + IToken char_literal14=null; + IToken char_literal15=null; + ProfileGrammarParser.formalPar_return formalPar13 = default(ProfileGrammarParser.formalPar_return); + ProfileGrammarParser.expr_return expr16 = default(ProfileGrammarParser.expr_return); + + CommonTree ID11_tree=null; + CommonTree char_literal12_tree=null; + CommonTree char_literal14_tree=null; + CommonTree char_literal15_tree=null; + RewriteRuleITokenStream stream_ID=new RewriteRuleITokenStream(adaptor,"token ID"); + RewriteRuleITokenStream stream_12=new RewriteRuleITokenStream(adaptor,"token 12"); + RewriteRuleITokenStream stream_13=new RewriteRuleITokenStream(adaptor,"token 13"); + RewriteRuleITokenStream stream_17=new RewriteRuleITokenStream(adaptor,"token 17"); + RewriteRuleSubtreeStream stream_formalPar=new RewriteRuleSubtreeStream(adaptor,"rule formalPar"); + RewriteRuleSubtreeStream stream_expr=new RewriteRuleSubtreeStream(adaptor,"rule expr"); + try + { + dbg.EnterRule( GrammarFileName, "func" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 59, -1 ); + + try + { + // BuildOptions\\ProfileGrammar.g3:59:9: ( ID '(' formalPar ')' '=' expr -> ^( FUNC ID formalPar expr ) ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:59:9: ID '(' formalPar ')' '=' expr + { + dbg.Location( 59, 8 ); + ID11=(IToken)Match(input,ID,Follow._ID_in_func219); + stream_ID.Add(ID11); + + dbg.Location( 59, 12 ); + char_literal12=(IToken)Match(input,12,Follow._12_in_func222); + stream_12.Add(char_literal12); + + dbg.Location( 59, 16 ); + PushFollow(Follow._formalPar_in_func224); + formalPar13=formalPar(); + + state._fsp--; + + stream_formalPar.Add(formalPar13.Tree); + dbg.Location( 59, 26 ); + char_literal14=(IToken)Match(input,13,Follow._13_in_func226); + stream_13.Add(char_literal14); + + dbg.Location( 59, 30 ); + char_literal15=(IToken)Match(input,17,Follow._17_in_func228); + stream_17.Add(char_literal15); + + dbg.Location( 59, 34 ); + PushFollow(Follow._expr_in_func230); + expr16=expr(); + + state._fsp--; + + stream_expr.Add(expr16.Tree); + + + { + // AST REWRITE + // elements: ID, formalPar, expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 59:41: -> ^( FUNC ID formalPar expr ) + { + dbg.Location( 59, 43 ); + // BuildOptions\\ProfileGrammar.g3:59:44: ^( FUNC ID formalPar expr ) + { + CommonTree root_1 = (CommonTree)adaptor.Nil(); + dbg.Location( 59, 45 ); + root_1 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(FUNC, "FUNC"), root_1); + + dbg.Location( 59, 50 ); + adaptor.AddChild(root_1, stream_ID.NextNode()); + dbg.Location( 59, 53 ); + adaptor.AddChild(root_1, stream_formalPar.NextTree()); + dbg.Location( 59, 63 ); + adaptor.AddChild(root_1, stream_expr.NextTree()); + + adaptor.AddChild(root_0, root_1); + } + + } + + retval.tree = root_0; + } + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + + functionDefinitions.Add(((CommonTree)retval.Tree)); + + } + dbg.Location(60, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "func" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "func" + + public class formalPar_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "formalPar" + // BuildOptions\\ProfileGrammar.g3:65:0: formalPar : ( ID | INT ); + private ProfileGrammarParser.formalPar_return formalPar( ) + { + ProfileGrammarParser.formalPar_return retval = new ProfileGrammarParser.formalPar_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken set17=null; + + CommonTree set17_tree=null; + + try + { + dbg.EnterRule( GrammarFileName, "formalPar" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 65, -1 ); + + try + { + // BuildOptions\\ProfileGrammar.g3:66:9: ( ID | INT ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3: + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 66, 8 ); + set17=(IToken)input.LT(1); + if ( (input.LA(1)>=ID && input.LA(1)<=INT) ) + { + input.Consume(); + adaptor.AddChild(root_0, (CommonTree)adaptor.Create(set17)); + state.errorRecovery=false; + } + else + { + MismatchedSetException mse = new MismatchedSetException(null,input); + dbg.RecognitionException( mse ); + throw mse; + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(68, 1); + + } + finally + { + dbg.ExitRule( GrammarFileName, "formalPar" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "formalPar" + + public class expr_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "expr" + // BuildOptions\\ProfileGrammar.g3:73:0: expr : multExpr ( ( '+' | '-' ) multExpr )* ; + private ProfileGrammarParser.expr_return expr( ) + { + ProfileGrammarParser.expr_return retval = new ProfileGrammarParser.expr_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken char_literal19=null; + IToken char_literal20=null; + ProfileGrammarParser.multExpr_return multExpr18 = default(ProfileGrammarParser.multExpr_return); + ProfileGrammarParser.multExpr_return multExpr21 = default(ProfileGrammarParser.multExpr_return); + + CommonTree char_literal19_tree=null; + CommonTree char_literal20_tree=null; + + try + { + dbg.EnterRule( GrammarFileName, "expr" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 73, -1 ); + + try + { + // BuildOptions\\ProfileGrammar.g3:73:9: ( multExpr ( ( '+' | '-' ) multExpr )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:73:9: multExpr ( ( '+' | '-' ) multExpr )* + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 73, 8 ); + PushFollow(Follow._multExpr_in_expr288); + multExpr18=multExpr(); + + state._fsp--; + + adaptor.AddChild(root_0, multExpr18.Tree); + dbg.Location( 73, 17 ); + // BuildOptions\\ProfileGrammar.g3:73:18: ( ( '+' | '-' ) multExpr )* + try + { + dbg.EnterSubRule( 4 ); + + for ( ; ; ) + { + int alt4=2; + try + { + dbg.EnterDecision( 4 ); + + int LA4_0 = input.LA(1); + + if ( (LA4_0==10||LA4_0==16) ) + { + alt4=1; + } + + + } + finally + { + dbg.ExitDecision( 4 ); + } + + switch ( alt4 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:73:19: ( '+' | '-' ) multExpr + { + dbg.Location( 73, 18 ); + // BuildOptions\\ProfileGrammar.g3:73:19: ( '+' | '-' ) + int alt3=2; + try + { + dbg.EnterSubRule( 3 ); + try + { + dbg.EnterDecision( 3 ); + + int LA3_0 = input.LA(1); + + if ( (LA3_0==16) ) + { + alt3=1; + } + else if ( (LA3_0==10) ) + { + alt3=2; + } + else + { + NoViableAltException nvae = new NoViableAltException("", 3, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + finally + { + dbg.ExitDecision( 3 ); + } + + switch ( alt3 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:73:20: '+' + { + dbg.Location( 73, 22 ); + char_literal19=(IToken)Match(input,16,Follow._16_in_expr292); + char_literal19_tree = (CommonTree)adaptor.Create(char_literal19); + root_0 = (CommonTree)adaptor.BecomeRoot(char_literal19_tree, root_0); + + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\ProfileGrammar.g3:73:25: '-' + { + dbg.Location( 73, 27 ); + char_literal20=(IToken)Match(input,10,Follow._10_in_expr295); + char_literal20_tree = (CommonTree)adaptor.Create(char_literal20); + root_0 = (CommonTree)adaptor.BecomeRoot(char_literal20_tree, root_0); + + + } + break; + + } + } + finally + { + dbg.ExitSubRule( 3 ); + } + + dbg.Location( 73, 30 ); + PushFollow(Follow._multExpr_in_expr299); + multExpr21=multExpr(); + + state._fsp--; + + adaptor.AddChild(root_0, multExpr21.Tree); + + } + break; + + default: + goto loop4; + } + } + + loop4: + ; + + } + finally + { + dbg.ExitSubRule( 4 ); + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(74, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "expr" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "expr" + + public class multExpr_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "multExpr" + // BuildOptions\\ProfileGrammar.g3:76:0: multExpr : atom ( ( '*' | '/' | '%' ) atom )* ; + private ProfileGrammarParser.multExpr_return multExpr( ) + { + ProfileGrammarParser.multExpr_return retval = new ProfileGrammarParser.multExpr_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken set23=null; + ProfileGrammarParser.atom_return atom22 = default(ProfileGrammarParser.atom_return); + ProfileGrammarParser.atom_return atom24 = default(ProfileGrammarParser.atom_return); + + CommonTree set23_tree=null; + + try + { + dbg.EnterRule( GrammarFileName, "multExpr" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 76, -1 ); + + try + { + // BuildOptions\\ProfileGrammar.g3:77:9: ( atom ( ( '*' | '/' | '%' ) atom )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:77:9: atom ( ( '*' | '/' | '%' ) atom )* + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 77, 8 ); + PushFollow(Follow._atom_in_multExpr320); + atom22=atom(); + + state._fsp--; + + adaptor.AddChild(root_0, atom22.Tree); + dbg.Location( 77, 13 ); + // BuildOptions\\ProfileGrammar.g3:77:14: ( ( '*' | '/' | '%' ) atom )* + try + { + dbg.EnterSubRule( 5 ); + + for ( ; ; ) + { + int alt5=2; + try + { + dbg.EnterDecision( 5 ); + + int LA5_0 = input.LA(1); + + if ( (LA5_0==11||(LA5_0>=14 && LA5_0<=15)) ) + { + alt5=1; + } + + + } + finally + { + dbg.ExitDecision( 5 ); + } + + switch ( alt5 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:77:15: ( '*' | '/' | '%' ) atom + { + dbg.Location( 77, 27 ); + set23=(IToken)input.LT(1); + set23=(IToken)input.LT(1); + if ( input.LA(1)==11||(input.LA(1)>=14 && input.LA(1)<=15) ) + { + input.Consume(); + root_0 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(set23), root_0); + state.errorRecovery=false; + } + else + { + MismatchedSetException mse = new MismatchedSetException(null,input); + dbg.RecognitionException( mse ); + throw mse; + } + + dbg.Location( 77, 29 ); + PushFollow(Follow._atom_in_multExpr332); + atom24=atom(); + + state._fsp--; + + adaptor.AddChild(root_0, atom24.Tree); + + } + break; + + default: + goto loop5; + } + } + + loop5: + ; + + } + finally + { + dbg.ExitSubRule( 5 ); + } + + + } + + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(78, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "multExpr" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "multExpr" + + public class atom_return : ParserRuleReturnScope + { + internal CommonTree tree; + public override object Tree { get { return tree; } } + } + + // $ANTLR start "atom" + // BuildOptions\\ProfileGrammar.g3:80:0: atom : ( INT | ID | '(' expr ')' -> expr | ID '(' expr ')' -> ^( CALL ID expr ) ); + private ProfileGrammarParser.atom_return atom( ) + { + ProfileGrammarParser.atom_return retval = new ProfileGrammarParser.atom_return(); + retval.start = input.LT(1); + + CommonTree root_0 = null; + + IToken INT25=null; + IToken ID26=null; + IToken char_literal27=null; + IToken char_literal29=null; + IToken ID30=null; + IToken char_literal31=null; + IToken char_literal33=null; + ProfileGrammarParser.expr_return expr28 = default(ProfileGrammarParser.expr_return); + ProfileGrammarParser.expr_return expr32 = default(ProfileGrammarParser.expr_return); + + CommonTree INT25_tree=null; + CommonTree ID26_tree=null; + CommonTree char_literal27_tree=null; + CommonTree char_literal29_tree=null; + CommonTree ID30_tree=null; + CommonTree char_literal31_tree=null; + CommonTree char_literal33_tree=null; + RewriteRuleITokenStream stream_12=new RewriteRuleITokenStream(adaptor,"token 12"); + RewriteRuleITokenStream stream_13=new RewriteRuleITokenStream(adaptor,"token 13"); + RewriteRuleITokenStream stream_ID=new RewriteRuleITokenStream(adaptor,"token ID"); + RewriteRuleSubtreeStream stream_expr=new RewriteRuleSubtreeStream(adaptor,"rule expr"); + try + { + dbg.EnterRule( GrammarFileName, "atom" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 80, -1 ); + + try + { + // BuildOptions\\ProfileGrammar.g3:80:9: ( INT | ID | '(' expr ')' -> expr | ID '(' expr ')' -> ^( CALL ID expr ) ) + int alt6=4; + try + { + dbg.EnterDecision( 6 ); + + switch ( input.LA(1) ) + { + case INT: + { + alt6=1; + } + break; + case ID: + { + int LA6_2 = input.LA(2); + + if ( (LA6_2==12) ) + { + alt6=4; + } + else if ( (LA6_2==NEWLINE||(LA6_2>=10 && LA6_2<=11)||(LA6_2>=13 && LA6_2<=16)) ) + { + alt6=2; + } + else + { + NoViableAltException nvae = new NoViableAltException("", 6, 2, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + break; + case 12: + { + alt6=3; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 6, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + + } + finally + { + dbg.ExitDecision( 6 ); + } + + switch ( alt6 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileGrammar.g3:80:9: INT + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 80, 8 ); + INT25=(IToken)Match(input,INT,Follow._INT_in_atom348); + INT25_tree = (CommonTree)adaptor.Create(INT25); + adaptor.AddChild(root_0, INT25_tree); + + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\ProfileGrammar.g3:81:9: ID + { + root_0 = (CommonTree)adaptor.Nil(); + + dbg.Location( 81, 8 ); + ID26=(IToken)Match(input,ID,Follow._ID_in_atom358); + ID26_tree = (CommonTree)adaptor.Create(ID26); + adaptor.AddChild(root_0, ID26_tree); + + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\ProfileGrammar.g3:82:9: '(' expr ')' + { + dbg.Location( 82, 8 ); + char_literal27=(IToken)Match(input,12,Follow._12_in_atom368); + stream_12.Add(char_literal27); + + dbg.Location( 82, 12 ); + PushFollow(Follow._expr_in_atom370); + expr28=expr(); + + state._fsp--; + + stream_expr.Add(expr28.Tree); + dbg.Location( 82, 17 ); + char_literal29=(IToken)Match(input,13,Follow._13_in_atom372); + stream_13.Add(char_literal29); + + + + { + // AST REWRITE + // elements: expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 82:25: -> expr + { + dbg.Location( 82, 27 ); + adaptor.AddChild(root_0, stream_expr.NextTree()); + + } + + retval.tree = root_0; + } + + } + break; + case 4: + dbg.EnterAlt( 4 ); + + // BuildOptions\\ProfileGrammar.g3:83:9: ID '(' expr ')' + { + dbg.Location( 83, 8 ); + ID30=(IToken)Match(input,ID,Follow._ID_in_atom389); + stream_ID.Add(ID30); + + dbg.Location( 83, 11 ); + char_literal31=(IToken)Match(input,12,Follow._12_in_atom391); + stream_12.Add(char_literal31); + + dbg.Location( 83, 15 ); + PushFollow(Follow._expr_in_atom393); + expr32=expr(); + + state._fsp--; + + stream_expr.Add(expr32.Tree); + dbg.Location( 83, 20 ); + char_literal33=(IToken)Match(input,13,Follow._13_in_atom395); + stream_13.Add(char_literal33); + + + + { + // AST REWRITE + // elements: ID, expr + // token labels: + // rule labels: retval + // token list labels: + // rule list labels: + // wildcard labels: + retval.tree = root_0; + RewriteRuleSubtreeStream stream_retval=new RewriteRuleSubtreeStream(adaptor,"rule retval",retval!=null?retval.tree:null); + + root_0 = (CommonTree)adaptor.Nil(); + // 83:25: -> ^( CALL ID expr ) + { + dbg.Location( 83, 27 ); + // BuildOptions\\ProfileGrammar.g3:83:28: ^( CALL ID expr ) + { + CommonTree root_1 = (CommonTree)adaptor.Nil(); + dbg.Location( 83, 29 ); + root_1 = (CommonTree)adaptor.BecomeRoot((CommonTree)adaptor.Create(CALL, "CALL"), root_1); + + dbg.Location( 83, 34 ); + adaptor.AddChild(root_1, stream_ID.NextNode()); + dbg.Location( 83, 37 ); + adaptor.AddChild(root_1, stream_expr.NextTree()); + + adaptor.AddChild(root_0, root_1); + } + + } + + retval.tree = root_0; + } + + } + break; + + } + retval.stop = input.LT(-1); + + retval.tree = (CommonTree)adaptor.RulePostProcessing(root_0); + adaptor.SetTokenBoundaries(retval.tree, retval.start, retval.stop); + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + retval.tree = (CommonTree)adaptor.ErrorNode(input, retval.start, input.LT(-1), re); + + } + finally + { + } + dbg.Location(84, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "atom" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return retval; + } + // $ANTLR end "atom" + #endregion Rules + + + #region DFA + DFA2 dfa2; + + protected override void InitDFAs() + { + base.InitDFAs(); + dfa2 = new DFA2( this ); + } + + class DFA2 : DFA + { + + const string DFA2_eotS = + "\xA\xFFFF"; + const string DFA2_eofS = + "\xA\xFFFF"; + const string DFA2_minS = + "\x1\x6\x1\xFFFF\x1\x8\x1\xFFFF\x1\x6\x1\xFFFF\x2\xA\x1\x8\x1\xFFFF"; + const string DFA2_maxS = + "\x1\xC\x1\xFFFF\x1\x11\x1\xFFFF\x1\xC\x1\xFFFF\x2\x10\x1\x11\x1\xFFFF"; + const string DFA2_acceptS = + "\x1\xFFFF\x1\x1\x1\xFFFF\x1\x4\x1\xFFFF\x1\x2\x3\xFFFF\x1\x3"; + const string DFA2_specialS = + "\xA\xFFFF}>"; + static readonly string[] DFA2_transitionS = + { + "\x1\x2\x1\x1\x1\x3\x3\xFFFF\x1\x1", + "", + "\x1\x1\x1\xFFFF\x2\x1\x1\x4\x1\xFFFF\x3\x1\x1\x5", + "", + "\x1\x7\x1\x6\x4\xFFFF\x1\x1", + "", + "\x2\x1\x1\xFFFF\x1\x8\x3\x1", + "\x3\x1\x1\x8\x3\x1", + "\x1\x1\x1\xFFFF\x2\x1\x2\xFFFF\x3\x1\x1\x9", + "" + }; + + static readonly short[] DFA2_eot = DFA.UnpackEncodedString(DFA2_eotS); + static readonly short[] DFA2_eof = DFA.UnpackEncodedString(DFA2_eofS); + static readonly char[] DFA2_min = DFA.UnpackEncodedStringToUnsignedChars(DFA2_minS); + static readonly char[] DFA2_max = DFA.UnpackEncodedStringToUnsignedChars(DFA2_maxS); + static readonly short[] DFA2_accept = DFA.UnpackEncodedString(DFA2_acceptS); + static readonly short[] DFA2_special = DFA.UnpackEncodedString(DFA2_specialS); + static readonly short[][] DFA2_transition; + + static DFA2() + { + int numStates = DFA2_transitionS.Length; + DFA2_transition = new short[numStates][]; + for ( int i=0; i < numStates; i++ ) + { + DFA2_transition[i] = DFA.UnpackEncodedString(DFA2_transitionS[i]); + } + } + + public DFA2( BaseRecognizer recognizer ) + { + this.recognizer = recognizer; + this.decisionNumber = 2; + this.eot = DFA2_eot; + this.eof = DFA2_eof; + this.min = DFA2_min; + this.max = DFA2_max; + this.accept = DFA2_accept; + this.special = DFA2_special; + this.transition = DFA2_transition; + } + public override string GetDescription() + { + return "53:0: stat : ( expr NEWLINE -> expr | ID '=' expr NEWLINE -> ^( '=' ID expr ) | func NEWLINE -> func | NEWLINE ->);"; + } + public override void Error( NoViableAltException nvae ) + { + ((DebugParser)recognizer).dbg.RecognitionException( nvae ); + } + } + + + #endregion DFA + + #region Follow sets + private static class Follow + { + public static readonly BitSet _stat_in_prog53 = new BitSet(new ulong[]{0x11C2UL}); + public static readonly BitSet _expr_in_stat70 = new BitSet(new ulong[]{0x100UL}); + public static readonly BitSet _NEWLINE_in_stat72 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_stat105 = new BitSet(new ulong[]{0x20000UL}); + public static readonly BitSet _17_in_stat107 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_stat109 = new BitSet(new ulong[]{0x100UL}); + public static readonly BitSet _NEWLINE_in_stat111 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _func_in_stat143 = new BitSet(new ulong[]{0x100UL}); + public static readonly BitSet _NEWLINE_in_stat145 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _NEWLINE_in_stat178 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_func219 = new BitSet(new ulong[]{0x1000UL}); + public static readonly BitSet _12_in_func222 = new BitSet(new ulong[]{0xC0UL}); + public static readonly BitSet _formalPar_in_func224 = new BitSet(new ulong[]{0x2000UL}); + public static readonly BitSet _13_in_func226 = new BitSet(new ulong[]{0x20000UL}); + public static readonly BitSet _17_in_func228 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_func230 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _set_in_formalPar267 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _multExpr_in_expr288 = new BitSet(new ulong[]{0x10402UL}); + public static readonly BitSet _16_in_expr292 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _10_in_expr295 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _multExpr_in_expr299 = new BitSet(new ulong[]{0x10402UL}); + public static readonly BitSet _atom_in_multExpr320 = new BitSet(new ulong[]{0xC802UL}); + public static readonly BitSet _set_in_multExpr323 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _atom_in_multExpr332 = new BitSet(new ulong[]{0xC802UL}); + public static readonly BitSet _INT_in_atom348 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_atom358 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _12_in_atom368 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_atom370 = new BitSet(new ulong[]{0x2000UL}); + public static readonly BitSet _13_in_atom372 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _ID_in_atom389 = new BitSet(new ulong[]{0x1000UL}); + public static readonly BitSet _12_in_atom391 = new BitSet(new ulong[]{0x10C0UL}); + public static readonly BitSet _expr_in_atom393 = new BitSet(new ulong[]{0x2000UL}); + public static readonly BitSet _13_in_atom395 = new BitSet(new ulong[]{0x2UL}); + + } + #endregion Follow sets +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarParserHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarParserHelper.cs new file mode 100644 index 0000000..ddd7533 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileGrammarParserHelper.cs @@ -0,0 +1,40 @@ +/* + * [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. + */ + +using System.Collections.Generic; +using Antlr.Runtime.Tree; + +partial class ProfileGrammarParser +{ + /** List of function definitions. Must point at the FUNC nodes. */ + List<CommonTree> functionDefinitions = new List<CommonTree>(); +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammar.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammar.cs new file mode 100644 index 0000000..3608faf --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammar.cs @@ -0,0 +1,850 @@ +// $ANTLR 3.1.2 BuildOptions\\ProfileTreeGrammar.g3 2009-09-30 13:18:19 + +// The variable 'variable' is assigned but its value is never used. +#pragma warning disable 219 +// Unreachable code detected. +#pragma warning disable 162 + + +//import java.util.Map; +//import java.util.HashMap; +using BigInteger = java.math.BigInteger; +using Console = System.Console; + + +using System.Collections.Generic; +using Antlr.Runtime; +using Antlr.Runtime.Tree; +using RewriteRuleITokenStream = Antlr.Runtime.Tree.RewriteRuleTokenStream;using Stack = System.Collections.Generic.Stack<object>; +using List = System.Collections.IList; +using ArrayList = System.Collections.Generic.List<object>; + +using Antlr.Runtime.Debug; +using IOException = System.IO.IOException; +[System.CodeDom.Compiler.GeneratedCode("ANTLR", "3.1.2")] +[System.CLSCompliant(false)] +public partial class ProfileTreeGrammar : DebugTreeParser +{ + internal static readonly string[] tokenNames = new string[] { + "<invalid>", "<EOR>", "<DOWN>", "<UP>", "CALL", "FUNC", "ID", "INT", "NEWLINE", "WS", "'-'", "'%'", "'('", "')'", "'*'", "'/'", "'+'", "'='" + }; + public const int EOF=-1; + public const int T__10=10; + public const int T__11=11; + public const int T__12=12; + public const int T__13=13; + public const int T__14=14; + public const int T__15=15; + public const int T__16=16; + public const int T__17=17; + public const int CALL=4; + public const int FUNC=5; + public const int ID=6; + public const int INT=7; + public const int NEWLINE=8; + public const int WS=9; + + // delegates + // delegators + + public static readonly string[] ruleNames = + new string[] + { + "invalidRule", "call", "expr", "prog", "stat" + }; + + int ruleLevel = 0; + public virtual int RuleLevel { get { return ruleLevel; } } + public virtual void IncRuleLevel() { ruleLevel++; } + public virtual void DecRuleLevel() { ruleLevel--; } + public ProfileTreeGrammar( ITreeNodeStream input ) + : this( input, new Profiler(null), new RecognizerSharedState() ) + { + } + public ProfileTreeGrammar( ITreeNodeStream input, IDebugEventListener dbg, RecognizerSharedState state ) + : base( input, dbg, state ) + { + Profiler p = (Profiler)dbg; + p.setParser(this); + } + + public ProfileTreeGrammar( ITreeNodeStream input, IDebugEventListener dbg ) + : base( input, dbg, new RecognizerSharedState() ) + { + Profiler p = (Profiler)dbg; + p.setParser(this); + } + public virtual bool AlreadyParsedRule( IIntStream input, int ruleIndex ) + { + ((Profiler)dbg).ExamineRuleMemoization(input, ruleIndex, ProfileTreeGrammar.ruleNames[ruleIndex]); + return super.AlreadyParsedRule(input, ruleIndex); + } + + public virtual void Memoize( IIntStream input, int ruleIndex, int ruleStartIndex ) + { + ((Profiler)dbg).Memoize(input, ruleIndex, ruleStartIndex, ProfileTreeGrammar.ruleNames[ruleIndex]); + super.Memoize(input, ruleIndex, ruleStartIndex); + } + protected virtual bool EvalPredicate( bool result, string predicate ) + { + dbg.SemanticPredicate( result, predicate ); + return result; + } + + + public override string[] TokenNames { get { return ProfileTreeGrammar.tokenNames; } } + public override string GrammarFileName { get { return "BuildOptions\\ProfileTreeGrammar.g3"; } } + + + #region Rules + + // $ANTLR start "prog" + // BuildOptions\\ProfileTreeGrammar.g3:53:0: prog : ( stat )* ; + private void prog( ) + { + try + { + dbg.EnterRule( GrammarFileName, "prog" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 53, -1 ); + + try + { + // BuildOptions\\ProfileTreeGrammar.g3:53:9: ( ( stat )* ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileTreeGrammar.g3:53:9: ( stat )* + { + dbg.Location( 53, 8 ); + // BuildOptions\\ProfileTreeGrammar.g3:53:9: ( stat )* + try + { + dbg.EnterSubRule( 1 ); + + for ( ; ; ) + { + int alt1=2; + try + { + dbg.EnterDecision( 1 ); + + int LA1_0 = input.LA(1); + + if ( ((LA1_0>=CALL && LA1_0<=INT)||(LA1_0>=10 && LA1_0<=11)||(LA1_0>=14 && LA1_0<=17)) ) + { + alt1=1; + } + + + } + finally + { + dbg.ExitDecision( 1 ); + } + + switch ( alt1 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileTreeGrammar.g3:53:0: stat + { + dbg.Location( 53, 8 ); + PushFollow(Follow._stat_in_prog48); + stat(); + + state._fsp--; + + + } + break; + + default: + goto loop1; + } + } + + loop1: + ; + + } + finally + { + dbg.ExitSubRule( 1 ); + } + + + } + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(54, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "prog" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return ; + } + // $ANTLR end "prog" + + + // $ANTLR start "stat" + // BuildOptions\\ProfileTreeGrammar.g3:56:0: stat : ( expr | ^( '=' ID expr ) | ^( FUNC ( . )+ ) ); + private void stat( ) + { + CommonTree ID2=null; + BigInteger expr1 = default(BigInteger); + BigInteger expr3 = default(BigInteger); + + try + { + dbg.EnterRule( GrammarFileName, "stat" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 56, -1 ); + + try + { + // BuildOptions\\ProfileTreeGrammar.g3:56:9: ( expr | ^( '=' ID expr ) | ^( FUNC ( . )+ ) ) + int alt3=3; + try + { + dbg.EnterDecision( 3 ); + + switch ( input.LA(1) ) + { + case CALL: + case ID: + case INT: + case 10: + case 11: + case 14: + case 15: + case 16: + { + alt3=1; + } + break; + case 17: + { + alt3=2; + } + break; + case FUNC: + { + alt3=3; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 3, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + + } + finally + { + dbg.ExitDecision( 3 ); + } + + switch ( alt3 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileTreeGrammar.g3:56:9: expr + { + dbg.Location( 56, 8 ); + PushFollow(Follow._expr_in_stat63); + expr1=expr(); + + state._fsp--; + + dbg.Location( 56, 35 ); + string result = expr1.ToString(); + Console.Out.WriteLine(expr1 + " (about " + result[0] + "*10^" + (result.Length-1) + ")"); + + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\ProfileTreeGrammar.g3:59:9: ^( '=' ID expr ) + { + dbg.Location( 59, 8 ); + dbg.Location( 59, 10 ); + Match(input,17,Follow._17_in_stat98); + + Match(input, TokenTypes.Down, null); + dbg.Location( 59, 14 ); + ID2=(CommonTree)Match(input,ID,Follow._ID_in_stat100); + dbg.Location( 59, 17 ); + PushFollow(Follow._expr_in_stat102); + expr3=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 59, 35 ); + globalMemory[(ID2!=null?ID2.Text:null)] = expr3; + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\ProfileTreeGrammar.g3:60:9: ^( FUNC ( . )+ ) + { + dbg.Location( 60, 8 ); + dbg.Location( 60, 10 ); + Match(input,FUNC,Follow._FUNC_in_stat128); + + Match(input, TokenTypes.Down, null); + dbg.Location( 60, 15 ); + // BuildOptions\\ProfileTreeGrammar.g3:60:16: ( . )+ + int cnt2=0; + try + { + dbg.EnterSubRule( 2 ); + + for ( ; ; ) + { + int alt2=2; + try + { + dbg.EnterDecision( 2 ); + + int LA2_0 = input.LA(1); + + if ( ((LA2_0>=CALL && LA2_0<=17)) ) + { + alt2=1; + } + else if ( (LA2_0==UP) ) + { + alt2=2; + } + + + } + finally + { + dbg.ExitDecision( 2 ); + } + + switch ( alt2 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileTreeGrammar.g3:60:0: . + { + dbg.Location( 60, 15 ); + MatchAny(input); + + } + break; + + default: + if ( cnt2 >= 1 ) + goto loop2; + + EarlyExitException eee2 = new EarlyExitException( 2, input ); + dbg.RecognitionException( eee2 ); + + throw eee2; + } + cnt2++; + } + loop2: + ; + + } + finally + { + dbg.ExitSubRule( 2 ); + } + + + Match(input, TokenTypes.Up, null); + + } + break; + + } + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(61, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "stat" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return ; + } + // $ANTLR end "stat" + + + // $ANTLR start "expr" + // BuildOptions\\ProfileTreeGrammar.g3:63:0: expr returns [BigInteger value] : ( ^( '+' a= expr b= expr ) | ^( '-' a= expr b= expr ) | ^( '*' a= expr b= expr ) | ^( '/' a= expr b= expr ) | ^( '%' a= expr b= expr ) | ID | INT | call ); + private BigInteger expr( ) + { + BigInteger value = default(BigInteger); + + CommonTree ID4=null; + CommonTree INT5=null; + BigInteger a = default(BigInteger); + BigInteger b = default(BigInteger); + BigInteger call6 = default(BigInteger); + + try + { + dbg.EnterRule( GrammarFileName, "expr" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 63, -1 ); + + try + { + // BuildOptions\\ProfileTreeGrammar.g3:64:9: ( ^( '+' a= expr b= expr ) | ^( '-' a= expr b= expr ) | ^( '*' a= expr b= expr ) | ^( '/' a= expr b= expr ) | ^( '%' a= expr b= expr ) | ID | INT | call ) + int alt4=8; + try + { + dbg.EnterDecision( 4 ); + + switch ( input.LA(1) ) + { + case 16: + { + alt4=1; + } + break; + case 10: + { + alt4=2; + } + break; + case 14: + { + alt4=3; + } + break; + case 15: + { + alt4=4; + } + break; + case 11: + { + alt4=5; + } + break; + case ID: + { + alt4=6; + } + break; + case INT: + { + alt4=7; + } + break; + case CALL: + { + alt4=8; + } + break; + default: + { + NoViableAltException nvae = new NoViableAltException("", 4, 0, input); + + dbg.RecognitionException( nvae ); + throw nvae; + } + } + + } + finally + { + dbg.ExitDecision( 4 ); + } + + switch ( alt4 ) + { + case 1: + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileTreeGrammar.g3:64:9: ^( '+' a= expr b= expr ) + { + dbg.Location( 64, 8 ); + dbg.Location( 64, 10 ); + Match(input,16,Follow._16_in_expr172); + + Match(input, TokenTypes.Down, null); + dbg.Location( 64, 15 ); + PushFollow(Follow._expr_in_expr176); + a=expr(); + + state._fsp--; + + dbg.Location( 64, 22 ); + PushFollow(Follow._expr_in_expr180); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 64, 35 ); + value = a.add(b); + + } + break; + case 2: + dbg.EnterAlt( 2 ); + + // BuildOptions\\ProfileTreeGrammar.g3:65:9: ^( '-' a= expr b= expr ) + { + dbg.Location( 65, 8 ); + dbg.Location( 65, 10 ); + Match(input,10,Follow._10_in_expr200); + + Match(input, TokenTypes.Down, null); + dbg.Location( 65, 15 ); + PushFollow(Follow._expr_in_expr204); + a=expr(); + + state._fsp--; + + dbg.Location( 65, 22 ); + PushFollow(Follow._expr_in_expr208); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 65, 35 ); + value = a.subtract(b); + + } + break; + case 3: + dbg.EnterAlt( 3 ); + + // BuildOptions\\ProfileTreeGrammar.g3:66:9: ^( '*' a= expr b= expr ) + { + dbg.Location( 66, 8 ); + dbg.Location( 66, 10 ); + Match(input,14,Follow._14_in_expr228); + + Match(input, TokenTypes.Down, null); + dbg.Location( 66, 15 ); + PushFollow(Follow._expr_in_expr232); + a=expr(); + + state._fsp--; + + dbg.Location( 66, 22 ); + PushFollow(Follow._expr_in_expr236); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 66, 35 ); + value = a.multiply(b); + + } + break; + case 4: + dbg.EnterAlt( 4 ); + + // BuildOptions\\ProfileTreeGrammar.g3:67:9: ^( '/' a= expr b= expr ) + { + dbg.Location( 67, 8 ); + dbg.Location( 67, 10 ); + Match(input,15,Follow._15_in_expr256); + + Match(input, TokenTypes.Down, null); + dbg.Location( 67, 15 ); + PushFollow(Follow._expr_in_expr260); + a=expr(); + + state._fsp--; + + dbg.Location( 67, 22 ); + PushFollow(Follow._expr_in_expr264); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 67, 35 ); + value = a.divide(b); + + } + break; + case 5: + dbg.EnterAlt( 5 ); + + // BuildOptions\\ProfileTreeGrammar.g3:68:9: ^( '%' a= expr b= expr ) + { + dbg.Location( 68, 8 ); + dbg.Location( 68, 10 ); + Match(input,11,Follow._11_in_expr284); + + Match(input, TokenTypes.Down, null); + dbg.Location( 68, 15 ); + PushFollow(Follow._expr_in_expr288); + a=expr(); + + state._fsp--; + + dbg.Location( 68, 22 ); + PushFollow(Follow._expr_in_expr292); + b=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 68, 35 ); + value = a.remainder(b); + + } + break; + case 6: + dbg.EnterAlt( 6 ); + + // BuildOptions\\ProfileTreeGrammar.g3:69:9: ID + { + dbg.Location( 69, 8 ); + ID4=(CommonTree)Match(input,ID,Follow._ID_in_expr311); + dbg.Location( 69, 35 ); + value = getValue((ID4!=null?ID4.Text:null)); + + } + break; + case 7: + dbg.EnterAlt( 7 ); + + // BuildOptions\\ProfileTreeGrammar.g3:70:9: INT + { + dbg.Location( 70, 8 ); + INT5=(CommonTree)Match(input,INT,Follow._INT_in_expr347); + dbg.Location( 70, 35 ); + value = new BigInteger((INT5!=null?INT5.Text:null)); + + } + break; + case 8: + dbg.EnterAlt( 8 ); + + // BuildOptions\\ProfileTreeGrammar.g3:71:9: call + { + dbg.Location( 71, 8 ); + PushFollow(Follow._call_in_expr382); + call6=call(); + + state._fsp--; + + dbg.Location( 71, 35 ); + value = call6; + + } + break; + + } + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(72, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "expr" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return value; + } + // $ANTLR end "expr" + + + // $ANTLR start "call" + // BuildOptions\\ProfileTreeGrammar.g3:74:0: call returns [BigInteger value] : ^( CALL ID expr ) ; + private BigInteger call( ) + { + BigInteger value = default(BigInteger); + + CommonTree ID8=null; + BigInteger expr7 = default(BigInteger); + + try + { + dbg.EnterRule( GrammarFileName, "call" ); + if ( RuleLevel == 0 ) + { + dbg.Commence(); + } + IncRuleLevel(); + dbg.Location( 74, -1 ); + + try + { + // BuildOptions\\ProfileTreeGrammar.g3:75:9: ( ^( CALL ID expr ) ) + dbg.EnterAlt( 1 ); + + // BuildOptions\\ProfileTreeGrammar.g3:75:9: ^( CALL ID expr ) + { + dbg.Location( 75, 8 ); + dbg.Location( 75, 10 ); + Match(input,CALL,Follow._CALL_in_call430); + + Match(input, TokenTypes.Down, null); + dbg.Location( 75, 15 ); + ID8=(CommonTree)Match(input,ID,Follow._ID_in_call432); + dbg.Location( 75, 18 ); + PushFollow(Follow._expr_in_call434); + expr7=expr(); + + state._fsp--; + + + Match(input, TokenTypes.Up, null); + dbg.Location( 75, 35 ); + BigInteger p = expr7; + CommonTree funcRoot = findFunction((ID8!=null?ID8.Text:null), p); + if (funcRoot == null) { + Console.Error.WriteLine("No match found for " + (ID8!=null?ID8.Text:null) + "(" + p + ")"); + } else { + // Here we set up the local evaluator to run over the + // function definition with the parameter value. + // This re-reads a sub-AST of our input AST! + ProfileTreeGrammar e = new ProfileTreeGrammar(funcRoot, functionDefinitions, globalMemory, p); + value = e.expr(); + } + + + } + + } + catch ( RecognitionException re ) + { + ReportError(re); + Recover(input,re); + } + finally + { + } + dbg.Location(87, 4); + + } + finally + { + dbg.ExitRule( GrammarFileName, "call" ); + DecRuleLevel(); + if ( RuleLevel == 0 ) + { + dbg.Terminate(); + } + } + + return value; + } + // $ANTLR end "call" + #endregion Rules + + + #region Follow sets + private static class Follow + { + public static readonly BitSet _stat_in_prog48 = new BitSet(new ulong[]{0x3CCF2UL}); + public static readonly BitSet _expr_in_stat63 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _17_in_stat98 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _ID_in_stat100 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_stat102 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _FUNC_in_stat128 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _16_in_expr172 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr176 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr180 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _10_in_expr200 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr204 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr208 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _14_in_expr228 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr232 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr236 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _15_in_expr256 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr260 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr264 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _11_in_expr284 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _expr_in_expr288 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_expr292 = new BitSet(new ulong[]{0x8UL}); + public static readonly BitSet _ID_in_expr311 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _INT_in_expr347 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _call_in_expr382 = new BitSet(new ulong[]{0x2UL}); + public static readonly BitSet _CALL_in_call430 = new BitSet(new ulong[]{0x4UL}); + public static readonly BitSet _ID_in_call432 = new BitSet(new ulong[]{0x1CCD0UL}); + public static readonly BitSet _expr_in_call434 = new BitSet(new ulong[]{0x8UL}); + + } + #endregion Follow sets +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammar.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammar.g3 new file mode 100644 index 0000000..f6786db --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammar.g3 @@ -0,0 +1,88 @@ +/* + * [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. + */ + +tree grammar ProfileTreeGrammar; + +options +{ + language=CSharp3; + tokenVocab=ProfileGrammar; + ASTLabelType=CommonTree; +} + +// START:members +@header +{ +//import java.util.Map; +//import java.util.HashMap; +using BigInteger = java.math.BigInteger; +using Console = System.Console; +} +// END:members + +// START:rules +prog: stat* + ; + +stat: expr { string result = $expr.value.ToString(); + Console.Out.WriteLine($expr.value + " (about " + result[0] + "*10^" + (result.Length-1) + ")"); + } + | ^('=' ID expr) { globalMemory[$ID.text] = $expr.value; } + | ^(FUNC .+) // ignore FUNCs - we added them to functionDefinitions already in parser. + ; + +expr returns [BigInteger value] + : ^('+' a=expr b=expr) { $value = $a.value.add($b.value); } + | ^('-' a=expr b=expr) { $value = $a.value.subtract($b.value); } + | ^('*' a=expr b=expr) { $value = $a.value.multiply($b.value); } + | ^('/' a=expr b=expr) { $value = $a.value.divide($b.value); } + | ^('%' a=expr b=expr) { $value = $a.value.remainder($b.value); } + | ID { $value = getValue($ID.text); } + | INT { $value = new BigInteger($INT.text); } + | call { $value = $call.value; } + ; + +call returns [BigInteger value] + : ^(CALL ID expr) { BigInteger p = $expr.value; + CommonTree funcRoot = findFunction($ID.text, p); + if (funcRoot == null) { + Console.Error.WriteLine("No match found for " + $ID.text + "(" + p + ")"); + } else { + // Here we set up the local evaluator to run over the + // function definition with the parameter value. + // This re-reads a sub-AST of our input AST! + ProfileTreeGrammar e = new ProfileTreeGrammar(funcRoot, functionDefinitions, globalMemory, p); + $value = e.expr(); + } + } + ; +// END:rules diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammarHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammarHelper.cs new file mode 100644 index 0000000..47cc8a8 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/BuildOptions/ProfileTreeGrammarHelper.cs @@ -0,0 +1,116 @@ +/* + * [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. + */ + +using System.Collections.Generic; +using Antlr.Runtime.Tree; + +using BigInteger = java.math.BigInteger; +using Console = System.Console; + +partial class ProfileTreeGrammar +{ + /** Points to functions tracked by tree builder. */ + private List<CommonTree> functionDefinitions; + + /** Remember local variables. Currently, this is only the function parameter. + */ + private readonly IDictionary<string, BigInteger> localMemory = new Dictionary<string, BigInteger>(); + + /** Remember global variables set by =. */ + private IDictionary<string, BigInteger> globalMemory = new Dictionary<string, BigInteger>(); + + /** Set up an evaluator with a node stream; and a set of function definition ASTs. */ + public ProfileTreeGrammar( CommonTreeNodeStream nodes, List<CommonTree> functionDefinitions ) + : this( nodes ) + { + this.functionDefinitions = functionDefinitions; + } + + /** Set up a local evaluator for a nested function call. The evaluator gets the definition + * tree of the function; the set of all defined functions (to find locally called ones); a + * pointer to the global variable memory; and the value of the function parameter to be + * added to the local memory. + */ + private ProfileTreeGrammar( CommonTree function, + List<CommonTree> functionDefinitions, + IDictionary<string, BigInteger> globalMemory, + BigInteger paramValue ) + // Expected tree for function: ^(FUNC ID ( INT | ID ) expr) + : this( new CommonTreeNodeStream( function.GetChild( 2 ) ), functionDefinitions ) + { + this.globalMemory = globalMemory; + localMemory[function.GetChild( 1 ).Text] = paramValue; + } + + /** Find matching function definition for a function name and parameter + * value. The first definition is returned where (a) the name matches + * and (b) the formal parameter agrees if it is defined as constant. + */ + private CommonTree findFunction( string name, BigInteger paramValue ) + { + foreach ( CommonTree f in functionDefinitions ) + { + // Expected tree for f: ^(FUNC ID (ID | INT) expr) + if ( f.GetChild( 0 ).Text.Equals( name ) ) + { + // Check whether parameter matches + CommonTree formalPar = (CommonTree)f.GetChild( 1 ); + if ( formalPar.Token.Type == INT + && !new BigInteger( formalPar.Token.Text ).Equals( paramValue ) ) + { + // Constant in formalPar list does not match actual value -> no match. + continue; + } + // Parameter (value for INT formal arg) as well as fct name agrees! + return f; + } + } + return null; + } + + /** Get value of name up call stack. */ + public BigInteger getValue( string name ) + { + BigInteger value; + if ( localMemory.TryGetValue( name, out value ) && value != null ) + { + return value; + } + if ( globalMemory.TryGetValue( name, out value ) && value != null ) + { + return value; + } + // not found in local memory or global memory + Console.Error.WriteLine( "undefined variable " + name ); + return new BigInteger( "0" ); + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Program.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Program.cs new file mode 100644 index 0000000..c2aaf02 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Program.cs @@ -0,0 +1,54 @@ +namespace Antlr3.Runtime.Test.Composition +{ + using System; + using Antlr.Runtime; + using Antlr.Runtime.Tree; + + internal class Program + { + private static void _Main(string[] args) + { + // input "x = 2*(3+3)" + + ICharStream input; + if (args.Length > 0) + { + if (args[0].Equals("-i")) + { + if (args.Length > 1) + { + input = new ANTLRFileStream(args[1]); + } + else + { + throw new Exception("No input file specified."); + } + } + else + { + input = new ANTLRStringStream(args[0]); + } + } + else + { + input = new ANTLRInputStream(Console.OpenStandardInput()); + } + + var lex = new VecMathLexer(input); + var tokens = new CommonTokenStream(lex); + var g = new VecMathParser(tokens); + IAstRuleReturnScope<CommonTree> r = g.prog(); + CommonTree t = r.Tree; + Console.WriteLine("Original tree: " + t.ToStringTree()); + + var simplify = new Simplify(new CommonTreeNodeStream(t)); + t = (CommonTree)simplify.Downup(t); + + var reduce = new Reduce(new CommonTreeNodeStream(t)); + t = (CommonTree)reduce.Downup(t); + + Console.WriteLine("Simplified tree: " + t.ToStringTree()); + Console.ReadKey(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Reduce.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Reduce.g3 new file mode 100644 index 0000000..0ed570b --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Reduce.g3 @@ -0,0 +1,26 @@ +tree grammar Reduce; + +options +{ + tokenVocab=VecMath; + ASTLabelType=CommonTree; + output=AST; + filter=true; + language=CSharp3; +} + + +@members +{ + //public override IAstRuleReturnScope Topdown() { return topdown(); } + public override IAstRuleReturnScope Bottomup() { return bottomup(); } +} + + +/** Rewrite: x+x to be 2*x, 2*x to be x<<1, x<<n<<m to be x<<(n+m) */ +bottomup + : ^(PLUS i=INT j=INT {$i.int==$j.int}?) -> ^(MULT["*"] INT["2"] $j) + | ^(MULT x=INT {$x.int==2}? y=.) -> ^(SHIFT["<<"] $y INT["1"]) + | ^(SHIFT ^(SHIFT e=. n=INT) m=INT) + -> ^(SHIFT["<<"] $e INT[($n.int+$m.int).ToString()]) + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Simplify.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Simplify.g3 new file mode 100644 index 0000000..fd1fded --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/Simplify.g3 @@ -0,0 +1,25 @@ +tree grammar Simplify; + +options { + tokenVocab=VecMath; + ASTLabelType=CommonTree; + output=AST; + language=CSharp3; + filter=true; + //rewrite=true; +} + +@members +{ + public override IAstRuleReturnScope Topdown() { return topdown(); } + public override IAstRuleReturnScope Bottomup() { return bottomup(); } +} + + +topdown + : ^( MULT INT ^(VEC (e+=.)+) ) -> ^(VEC ^(MULT INT $e)+) + ; + +bottomup + : ^(MULT a=. b=INT {$b.int==0}?) -> $b // x*0 -> 0 + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath.g3 new file mode 100644 index 0000000..f61a7f8 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath.g3 @@ -0,0 +1,22 @@ +grammar VecMath; + +options +{ + ASTLabelType=CommonTree; + output=AST; + language=CSharp3; +} + +import VecMath_Lexer, VecMath_Parser; + +@lexer::namespace{Antlr3.Runtime.Test.Composition} +@parser::namespace{Antlr3.Runtime.Test.Composition} + +public +main + : prog + ; + +dummy + : 'DUMMY' // 1. If the parser or the composite grammar does not contain a token, no lexer is generated. + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath_Lexer.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath_Lexer.g3 new file mode 100644 index 0000000..fde3390 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath_Lexer.g3 @@ -0,0 +1,17 @@ +lexer grammar VecMath_Lexer; + + +PRINT : 'print'; +ID : 'a'..'z'+ ; +INT : '0'..'9'+ ; +WS : (' '|'\r'|'\n')+ {Skip();} ; +PLUS : '+'; +MINUS : '-'; +MULT : '*'; +EQUAL : '='; +DOT : '.'; +OPEN_BRACE : '('; +OPEN_SQUARE : '['; +CLOSE_BRACE : ')'; +CLOSE_SQUARE : ']'; +COMMA : ',';
\ No newline at end of file diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath_Parser.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath_Parser.g3 new file mode 100644 index 0000000..406ec13 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Composition/VecMath_Parser.g3 @@ -0,0 +1,35 @@ +parser grammar VecMath_Parser; + +options { + output=AST; +} + +tokens { + SHIFT; + VEC; +} + +public +prog + : stat+ ; + +stat + : ID EQUAL expr -> ^( EQUAL ID expr ) + | PRINT^ expr + ; + +expr + : multExpr ( PLUS^ multExpr )* + ; + +multExpr + : primary ( ( MULT^ | DOT^ ) primary )* + ; + +primary + : INT + | ID + | OPEN_SQUARE expr ( COMMA expr )* CLOSE_SQUARE -> ^( VEC expr+ ) + | OPEN_BRACE expr CLOSE_BRACE -> expr + ; + diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpression.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpression.g3 new file mode 100644 index 0000000..1c51490 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpression.g3 @@ -0,0 +1,86 @@ +/* + * [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. + */ + +grammar FastSimpleExpression; + +options +{ + language=CSharp3; + //slim=true; + output=AST; + ASTLabelType=CommonTree; +} + +@lexer::superClass{Antlr.Runtime.SlimLexer} + +public +expression + : additive_expression + EOF + ; + +additive_expression + : multiplicative_expression + ( ('+'^ | '-'^) + multiplicative_expression + )* + ; + +multiplicative_expression + : atom + ( ('*'^ | '/'^ | '%'^) + atom + )* + ; + +atom + : IDENTIFIER + | NUMBER + ; + +// +// LEXER +// + +IDENTIFIER + : ('a'..'z' | 'A'..'Z' | '_') + ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')* + ; + +NUMBER + : '0'..'9'+ + ; + +WS + : (' ' | '\t' | '\n' | '\r' | '\f') + {$channel = Hidden;} + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpressionLexerHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpressionLexerHelper.cs new file mode 100644 index 0000000..414c260 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpressionLexerHelper.cs @@ -0,0 +1,31 @@ +/* + * [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. + */ diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpressionParserHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpressionParserHelper.cs new file mode 100644 index 0000000..414c260 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/FastSimpleExpressionParserHelper.cs @@ -0,0 +1,31 @@ +/* + * [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. + */ diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/JavaCompat/Expr.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/JavaCompat/Expr.g3 new file mode 100644 index 0000000..65e7c5d --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/JavaCompat/Expr.g3 @@ -0,0 +1,110 @@ +/* + * [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. + */ + +grammar Expr; + +/* + I had to make the following changes to the basic Expr grammar to make it work with the CSharp3 target in "Java compatibility mode". + For reference, see http://www.antlr.org/wiki/display/ANTLR3/Expression+evaluator. + + Add an options section to set the language to CSharp3. + + In the @header section, add: + // 'member' is obsolete + #pragma warning disable 612 + using Antlr.Runtime.JavaExtensions; + + In the @header section, replace: + import java.util.HashMap; + with: + using HashMap = System.Collections.Generic.Dictionary<object,object>; + + Change all instances of "System.out" with "JSystem.@out". + + Change all instances of "System.err" with "JSystem.err". + + Change all instances of "skip()" with "Skip()". + */ + +options +{ + language=CSharp3; +} + +@header { +// 'member' is obsolete +#pragma warning disable 612 + +using Antlr.Runtime.JavaExtensions; +using HashMap = System.Collections.Generic.Dictionary<object,object>; +using Integer = java.lang.Integer; +} + +@members { +/** Map variable name to Integer object holding value */ +HashMap memory = new HashMap(); +} + +prog: stat+ ; + +stat: expr NEWLINE {JSystem.@out.println($expr.value);} + | ID '=' expr NEWLINE + {memory.put($ID.text, new Integer($expr.value));} + | NEWLINE + ; + +expr returns [int value] + : e=multExpr {$value = $e.value;} + ( '+' e=multExpr {$value += $e.value;} + | '-' e=multExpr {$value -= $e.value;} + )* + ; + +multExpr returns [int value] + : e=atom {$value = $e.value;} ('*' e=atom {$value *= $e.value;})* + ; + +atom returns [int value] + : INT {$value = Integer.parseInt($INT.text);} + | ID + { + Integer v = (Integer)memory.get($ID.text); + if ( v!=null ) $value = v.intValue(); + else JSystem.err.println("undefined variable "+$ID.text); + } + | '(' expr ')' {$value = $expr.value;} + ; + +ID : ('a'..'z'|'A'..'Z')+ ; +INT : '0'..'9'+ ; +NEWLINE:'\r'? '\n' ; +WS : (' '|'\t')+ {Skip();} ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Properties/AssemblyInfo.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..fd2190d --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/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.Test" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "Pixel Mine, Inc." )] +[assembly: AssemblyProduct( "Antlr3.Runtime.Test" )] +[assembly: AssemblyCopyright("Copyright © Sam Harwell 2011")] +[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( "1352b15b-eded-4380-9122-acde32f7ff38" )] + +/* 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.2.8098")] +[assembly: AssemblyFileVersion("3.3.2.8098")] diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3 new file mode 100644 index 0000000..6593039 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3 @@ -0,0 +1,23 @@ +grammar SemanticPredicateReduction; + +options { + language=CSharp3; + TokenLabelType=CommonToken; +} + +@lexer::namespace{Antlr3.Runtime.Test} +@parser::namespace{Antlr3.Runtime.Test} + +start : mainprog optional? EOF; + +mainprog : '(' args ')'; +args : ID ID*; + +optional: ':' args element ':' args element2; +element : {true}?=>args2; +element2: {false}?=>args3; +args2 : ID ID*; +args3 : ID ID* ; + +WS : (' '|'\t'|'\n'|'\r')+; +ID : ('a'..'z')+; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3.lexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3.lexer.cs new file mode 100644 index 0000000..14e37f3 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3.lexer.cs @@ -0,0 +1,6 @@ +namespace Antlr3.Runtime.Test +{ + partial class SemanticPredicateReductionLexer + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3.parser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3.parser.cs new file mode 100644 index 0000000..2bb542a --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SemanticPredicateReduction.g3.parser.cs @@ -0,0 +1,6 @@ +namespace Antlr3.Runtime.Test +{ + partial class SemanticPredicateReductionParser + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpression.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpression.g3 new file mode 100644 index 0000000..d5eb359 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpression.g3 @@ -0,0 +1,83 @@ +/* + * [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. + */ + +grammar SimpleExpression; + +options +{ + language=CSharp3; + output=AST; + ASTLabelType=CommonTree; +} + +public +expression + : additive_expression + EOF + ; + +additive_expression + : multiplicative_expression + ( ('+'^ | '-'^) + multiplicative_expression + )* + ; + +multiplicative_expression + : atom + ( ('*'^ | '/'^ | '%'^) + atom + )* + ; + +atom + : IDENTIFIER + | NUMBER + ; + +// +// LEXER +// + +IDENTIFIER + : ('a'..'z' | 'A'..'Z' | '_') + ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')* + ; + +NUMBER + : '0'..'9'+ + ; + +WS + : (' ' | '\t' | '\n' | '\r' | '\f') + {$channel = Hidden;} + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpressionLexerHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpressionLexerHelper.cs new file mode 100644 index 0000000..414c260 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpressionLexerHelper.cs @@ -0,0 +1,31 @@ +/* + * [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. + */ diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpressionParserHelper.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpressionParserHelper.cs new file mode 100644 index 0000000..414c260 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SimpleExpressionParserHelper.cs @@ -0,0 +1,31 @@ +/* + * [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. + */ diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/ITokenSource`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/ITokenSource`1.cs new file mode 100644 index 0000000..569c05f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/ITokenSource`1.cs @@ -0,0 +1,41 @@ +/* + * [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 +{ + public interface ITokenSource<T> + : ITokenSource + where T : IToken + { + new T NextToken(); + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/ITokenStream`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/ITokenStream`1.cs new file mode 100644 index 0000000..a8faca6 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/ITokenStream`1.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 +{ + public interface ITokenStream<T> + where T : IToken + { + T LT(int k); + + T Get(int i); + + ITokenSource<T> TokenSource + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimLexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimLexer.cs new file mode 100644 index 0000000..3b2ec7f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimLexer.cs @@ -0,0 +1,445 @@ +/* + * [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 +{ + public abstract class SlimLexer + : BaseRecognizer + , ITokenSource<SlimToken> + { + /** <summary>Where is the lexer drawing characters from?</summary> */ + protected SlimStringStream input; + SlimToken _token; + bool _emitted; + bool _skip; + + public SlimLexer() + { + } + + public SlimLexer( ICharStream input ) + { + this.input = (SlimStringStream)input; + } + + public SlimLexer( ICharStream input, RecognizerSharedState state ) + : base( state ) + { + this.input = (SlimStringStream)input; + } + + #region Properties + public string Text + { + /** <summary>Return the text matched so far for the current token or any text override.</summary> */ + get + { + if ( state.text != null ) + { + return state.text; + } + return input.Substring( state.tokenStartCharIndex, CharIndex - state.tokenStartCharIndex ); + } + /** <summary>Set the complete text of this token; it wipes any previous changes to the text.</summary> */ + set + { + state.text = value; + } + } + public int Line + { + get + { + return input.Line; + } + set + { + input.Line = value; + } + } + public int CharPositionInLine + { + get + { + return input.CharPositionInLine; + } + set + { + input.CharPositionInLine = value; + } + } + #endregion + + public override void Reset() + { + base.Reset(); // reset all recognizer state variables + // wack Lexer state variables + if ( input != null ) + { + input.Seek( 0 ); // rewind the input + } + if ( state == null ) + { + return; // no shared state work to do + } + _token = default( SlimToken ); + _emitted = false; + _skip = false; + //state.token = null; + state.type = TokenTypes.Invalid; + state.channel = TokenChannels.Default; + state.tokenStartCharIndex = -1; +#if TRACK_POSITION + state.tokenStartCharPositionInLine = -1; + state.tokenStartLine = -1; +#endif + state.text = null; + } + + /** <summary>Return a token from this source; i.e., match a token on the char stream.</summary> */ + public virtual SlimToken NextToken() + { + for ( ; ; ) + { + _token = default( SlimToken ); + _emitted = false; + _skip = false; + //state.token = null; + state.channel = TokenChannels.Default; + state.tokenStartCharIndex = input.Index; +#if TRACK_POSITION + state.tokenStartCharPositionInLine = input.CharPositionInLine; + state.tokenStartLine = input.Line; +#endif + state.text = null; + if ( input.LA( 1 ) == CharStreamConstants.EndOfFile ) + { + return new SlimToken(TokenTypes.EndOfFile); + } + try + { + mTokens(); + if ( _skip ) + { + continue; + } + else if ( !_emitted ) + { + Emit(); + } + + return _token; + } + catch ( NoViableAltException nva ) + { + ReportError( nva ); + Recover( nva ); // throw out current char and try again + } + catch ( RecognitionException re ) + { + ReportError( re ); + // match() routine has already called recover() + } + } + } + IToken ITokenSource.NextToken() + { + return NextToken(); + } + + /** <summary> + * Instruct the lexer to skip creating a token for current lexer rule + * and look for another token. nextToken() knows to keep looking when + * a lexer rule finishes with token set to SKIP_TOKEN. Recall that + * if token==null at end of any token rule, it creates one for you + * and emits it. + * </summary> + */ + public virtual void Skip() + { + _skip = true; + //state.token = Tokens.Skip; + } + + /** <summary>This is the lexer entry point that sets instance var 'token'</summary> */ + public abstract void mTokens(); + + public ICharStream CharStream + { + get + { + return input; + } + /** <summary>Set the char stream and reset the lexer</summary> */ + set + { + input = null; + Reset(); + input = (SlimStringStream)value; + } + } + + public override string SourceName + { + get + { + return input.SourceName; + } + } + + ///** <summary> + // * Currently does not support multiple emits per nextToken invocation + // * for efficiency reasons. Subclass and override this method and + // * nextToken (to push tokens into a list and pull from that list rather + // * than a single variable as this implementation does). + // * </summary> + // */ + //public void Emit( T token ) + //{ + // _token = token; + //} + + /** <summary> + * The standard method called to automatically emit a token at the + * outermost lexical rule. The token object should point into the + * char buffer start..stop. If there is a text override in 'text', + * use that to set the token's text. Override this method to emit + * custom Token objects. + * </summary> + * + * <remarks> + * If you are building trees, then you should also override + * Parser or TreeParser.getMissingSymbol(). + * </remarks> + */ + public void Emit() + { + _token = new SlimToken() + { + //InputStream = input, + Type = state.type, + Channel = state.channel, + //CharPositionInLine = state.tokenStartCharPositionInLine, + //Line = state.tokenStartLine, + //Text = state.text + }; + //Emit( t ); + //return t; + + //IToken t = new CommonToken( input, state.type, state.channel, state.tokenStartCharIndex, CharIndex - 1 ); + //t.Line = state.tokenStartLine; + //t.Text = state.text; + //t.CharPositionInLine = state.tokenStartCharPositionInLine; + //Emit( t ); + //return t; + } + + public void Match( string s ) + { + int i = 0; + while ( i < s.Length ) + { + if ( input.LA( 1 ) != s[i] ) + { + if ( state.backtracking > 0 ) + { + state.failed = true; + return; + } + MismatchedTokenException mte = new MismatchedTokenException(s[i], input, TokenNames); + Recover( mte ); + throw mte; + } + i++; + input.Consume(); + state.failed = false; + } + } + + public void MatchAny() + { + input.Consume(); + } + + public void Match( int c ) + { + if ( input.LA( 1 ) != c ) + { + if ( state.backtracking > 0 ) + { + state.failed = true; + return; + } + MismatchedTokenException mte = new MismatchedTokenException(c, input, TokenNames); + Recover( mte ); // don't really recover; just consume in lexer + throw mte; + } + input.Consume(); + state.failed = false; + } + + public void MatchRange( int a, int b ) + { + if ( input.LA( 1 ) < a || input.LA( 1 ) > b ) + { + if ( state.backtracking > 0 ) + { + state.failed = true; + return; + } + MismatchedRangeException mre = + new MismatchedRangeException( a, b, input ); + Recover( mre ); + throw mre; + } + input.Consume(); + state.failed = false; + } + + /** <summary>What is the index of the current character of lookahead?</summary> */ + public int CharIndex + { + get + { + return input.Index; + } + } + + public override void ReportError( RecognitionException e ) + { + /** TODO: not thought about recovery in lexer yet. + * + // if we've already reported an error and have not matched a token + // yet successfully, don't report any errors. + if ( errorRecovery ) { + //System.err.print("[SPURIOUS] "); + return; + } + errorRecovery = true; + */ + + DisplayRecognitionError( this.TokenNames, e ); + } + + public override string GetErrorMessage( RecognitionException e, string[] tokenNames ) + { + string msg = null; + if ( e is MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting " + GetCharErrorDisplay( mte.Expecting ); + } + else if ( e is NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>" + // and "(decision="+nvae.decisionNumber+") and + // "state "+nvae.stateNumber + msg = "no viable alternative at character " + GetCharErrorDisplay( e.Character ); + } + else if ( e is EarlyExitException ) + { + EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at character " + GetCharErrorDisplay( e.Character ); + } + else if ( e is MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting set " + mse.Expecting; + } + else if ( e is MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting set " + mse.Expecting; + } + else if ( e is MismatchedRangeException ) + { + MismatchedRangeException mre = (MismatchedRangeException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting set " + + GetCharErrorDisplay( mre.A ) + ".." + GetCharErrorDisplay( mre.B ); + } + else + { + msg = base.GetErrorMessage( e, tokenNames ); + } + return msg; + } + + public virtual string GetCharErrorDisplay( int c ) + { + string s = ( (char)c ).ToString(); + switch ( c ) + { + case TokenTypes.EndOfFile: + s = "<EOF>"; + break; + case '\n': + s = "\\n"; + break; + case '\t': + s = "\\t"; + break; + case '\r': + s = "\\r"; + break; + } + return "'" + s + "'"; + } + + /** <summary> + * Lexers can normally match any char in it's vocabulary after matching + * a token, so do the easy thing and just kill a character and hope + * it all works out. You can instead use the rule invocation stack + * to do sophisticated error recovery if you are in a fragment rule. + * </summary> + */ + public virtual void Recover( RecognitionException re ) + { + //System.out.println("consuming char "+(char)input.LA(1)+" during recovery"); + //re.printStackTrace(); + input.Consume(); + } + + public virtual void TraceIn( string ruleName, int ruleIndex ) + { + string inputSymbol = ( (char)input.LT( 1 ) ) + " line=" + Line + ":" + CharPositionInLine; + base.TraceIn( ruleName, ruleIndex, inputSymbol ); + } + + public virtual void TraceOut( string ruleName, int ruleIndex ) + { + string inputSymbol = ( (char)input.LT( 1 ) ) + " line=" + Line + ":" + CharPositionInLine; + base.TraceOut( ruleName, ruleIndex, inputSymbol ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimStringStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimStringStream.cs new file mode 100644 index 0000000..b2c5d54 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimStringStream.cs @@ -0,0 +1,334 @@ +/* + * [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. + */ + +// #define TRACK_POSITION + +namespace Antlr.Runtime +{ + using System.Collections.Generic; + + /** <summary> + * A pretty quick CharStream that pulls all data from an array + * directly. Every method call counts in the lexer. Java's + * strings aren't very good so I'm avoiding. + * </summary> + */ + [System.Serializable] + public class SlimStringStream : ICharStream + { + /** <summary>The data being scanned</summary> */ + protected string data; + //protected char[] data; + + /** <summary>How many characters are actually in the buffer</summary> */ + protected int n; + + /** <summary>0..n-1 index into string of next char</summary> */ + protected int p = 0; + +#if TRACK_POSITION + /** <summary>line number 1..n within the input</summary> */ + protected int line = 1; + + /** <summary>The index of the character relative to the beginning of the line 0..n-1</summary> */ + protected int charPositionInLine = 0; +#endif + + /** <summary>tracks how deep mark() calls are nested</summary> */ + protected int markDepth = 0; + + /** <summary> + * A list of CharStreamState objects that tracks the stream state + * values line, charPositionInLine, and p that can change as you + * move through the input stream. Indexed from 1..markDepth. + * A null is kept @ index 0. Create upon first call to mark(). + * </summary> + */ + protected IList<CharStreamState> markers; + + /** <summary>Track the last mark() call result value for use in rewind().</summary> */ + protected int lastMarker; + + /** <summary>What is name or source of this char stream?</summary> */ + public string name; + + public SlimStringStream() + { + } + + /** <summary>Copy data in string to a local char array</summary> */ + public SlimStringStream( string input ) + : this( input, null ) + { + } + + public SlimStringStream( string input, string sourceName ) + : this( input.ToCharArray(), input.Length, sourceName ) + { + } + + /** <summary>This is the preferred constructor as no data is copied</summary> */ + public SlimStringStream( char[] data, int numberOfActualCharsInArray ) + : this( data, numberOfActualCharsInArray, null ) + { + } + + public SlimStringStream( char[] data, int numberOfActualCharsInArray, string sourceName ) + : this() + { + //this.data = data; + this.data = new string( data ); + this.n = numberOfActualCharsInArray; + this.name = sourceName; + } + + /** <summary> + * Return the current input symbol index 0..n where n indicates the + * last symbol has been read. The index is the index of char to + * be returned from LA(1). + * </summary> + */ + public int Index + { + get + { + return p; + } + } +#if TRACK_POSITION + public int Line + { + get + { + return line; + } + set + { + line = value; + } + } + public int CharPositionInLine + { + get + { + return charPositionInLine; + } + set + { + charPositionInLine = value; + } + } +#else + public int Line + { + get + { + return -1; + } + set + { + } + } + public int CharPositionInLine + { + get + { + return -1; + } + set + { + } + } +#endif + + /** <summary> + * Reset the stream so that it's in the same state it was + * when the object was created *except* the data array is not + * touched. + * </summary> + */ + public void Reset() + { + p = 0; +#if TRACK_POSITION + line = 1; + charPositionInLine = 0; +#endif + markDepth = 0; + } + + public void Consume() + { + //System.out.println("prev p="+p+", c="+(char)data[p]); + if ( p < n ) + { +#if TRACK_POSITION + charPositionInLine++; + if ( data[p] == '\n' ) + { + /* + System.out.println("newline char found on line: "+line+ + "@ pos="+charPositionInLine); + */ + line++; + charPositionInLine = 0; + } +#endif + p++; + //System.out.println("p moves to "+p+" (c='"+(char)data[p]+"')"); + } + } + + public int LA( int i ) + { + if ( i == 0 ) + { + return 0; // undefined + } + if ( i < 0 ) + { + i++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1] + if ( ( p + i - 1 ) < 0 ) + { + return CharStreamConstants.EndOfFile; // invalid; no char before first char + } + } + + if ( ( p + i - 1 ) >= n ) + { + //System.out.println("char LA("+i+")=EOF; p="+p); + return CharStreamConstants.EndOfFile; + } + //System.out.println("char LA("+i+")="+(char)data[p+i-1]+"; p="+p); + //System.out.println("LA("+i+"); p="+p+" n="+n+" data.length="+data.length); + return data[p + i - 1]; + } + + public int LT( int i ) + { + return LA( i ); + } + + public int Count + { + get + { + return n; + } + } + + public int Mark() + { + if ( markers == null ) + { + markers = new List<CharStreamState>(); + markers.Add( null ); // depth 0 means no backtracking, leave blank + } + markDepth++; + CharStreamState state = null; + if ( markDepth >= markers.Count ) + { + state = new CharStreamState(); + markers.Add( state ); + } + else + { + state = markers[markDepth]; + } + state.p = p; +#if TRACK_POSITION + state.line = line; + state.charPositionInLine = charPositionInLine; +#endif + lastMarker = markDepth; + return markDepth; + } + + public void Rewind( int m ) + { + CharStreamState state = markers[m]; + // restore stream state + Seek( state.p ); +#if TRACK_POSITION + line = state.line; + charPositionInLine = state.charPositionInLine; +#endif + Release( m ); + } + + public void Rewind() + { + Rewind( lastMarker ); + } + + public void Release( int marker ) + { + // unwind any other markers made after m and release m + markDepth = marker; + // release this marker + markDepth--; + } + + /** <summary> + * consume() ahead until p==index; can't just set p=index as we must + * update line and charPositionInLine. + * </summary> + */ + public void Seek( int index ) + { + if ( index <= p ) + { + p = index; // just jump; don't update stream state (line, ...) + return; + } + // seek forward, consume until p hits index + while ( p < index ) + { + Consume(); + } + } + + public string Substring( int start, int length ) + { + return data.Substring( start, length ); + //return new string( data, start, stop - start + 1 ); + } + + public string SourceName + { + get + { + return name; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimToken.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimToken.cs new file mode 100644 index 0000000..d850958 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimToken.cs @@ -0,0 +1,160 @@ +/* + * [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 +{ + using System; + using System.Runtime.InteropServices; + + [StructLayout( LayoutKind.Sequential, Pack = 2 )] + public struct SlimToken + : IToken + { + private short _type; + private short _channel; + private short _startIndex; + private short _stopIndex; + + public SlimToken(int type) + : this() + { + _type = (short)type; + } + + #region IToken Members + + string IToken.Text + { + get + { + return string.Empty; + } + set + { + } + } + + public int Type + { + get + { + return _type; + } + set + { + _type = (short)value; + } + } + + int IToken.Line + { + get + { + return 0; + } + set + { + } + } + + int IToken.CharPositionInLine + { + get + { + return 0; + } + set + { + } + } + + public int Channel + { + get + { + return _channel; + } + set + { + _channel = (short)value; + } + } + + public int StartIndex + { + get + { + return _startIndex; + } + set + { + _startIndex = (short)value; + } + } + + public int StopIndex + { + get + { + return _stopIndex; + } + set + { + _stopIndex = (short)value; + } + } + + int IToken.TokenIndex + { + get + { + return 0; + } + set + { + } + } + + ICharStream IToken.InputStream + { + get + { + return null; + } + set + { + } + } + + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimTokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimTokenStream.cs new file mode 100644 index 0000000..50da1ed --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/SlimTokenStream.cs @@ -0,0 +1,438 @@ +/* + * [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 +{ + using System.Collections.Generic; + using System; + using System.Text; + + /** <summary> + * A pretty quick CharStream that pulls all data from an array + * directly. Every method call counts in the lexer. Java's + * strings aren't very good so I'm avoiding. + * </summary> + */ + [System.Serializable] + public class FastTokenStream + : ITokenStream<SlimToken> + { + [System.NonSerialized] + ITokenSource<SlimToken> _tokenSource; + + /** <summary> + * Record every single token pulled from the source so we can reproduce + * chunks of it later. + * </summary> + */ + protected List<SlimToken> tokens; + + /** <summary>Skip tokens on any channel but this one; this is how we skip whitespace...</summary> */ + protected int channel = TokenChannels.Default; + + /** <summary>Track the last mark() call result value for use in rewind().</summary> */ + protected int lastMarker; + + /** <summary> + * The index into the tokens list of the current token (next token + * to consume). p==-1 indicates that the tokens list is empty + * </summary> + */ + protected int p = -1; + + public FastTokenStream() + { + tokens = new List<SlimToken>( 500 ); + } + + public FastTokenStream( ITokenSource<SlimToken> tokenSource ) + : this() + { + this._tokenSource = tokenSource; + } + + public FastTokenStream( ITokenSource<SlimToken> tokenSource, int channel ) + : this( tokenSource ) + { + this.channel = channel; + } + + public int Index + { + get + { + return p; + } + } + + /** <summary>Reset this token stream by setting its token source.</summary> */ + public void SetTokenSource( ITokenSource<SlimToken> tokenSource ) + { + this._tokenSource = tokenSource; + tokens.Clear(); + p = -1; + channel = TokenChannels.Default; + } + + /** <summary> + * Load all tokens from the token source and put in tokens. + * This is done upon first LT request because you might want to + * set some token type / channel overrides before filling buffer. + * </summary> + */ + public void FillBuffer() + { + // fast return if the buffer is already full + if ( p != -1 ) + return; + + int index = 0; + SlimToken t = _tokenSource.NextToken(); + while ( t.Type != CharStreamConstants.EndOfFile ) + { + //t.TokenIndex = index; + tokens.Add( t ); + index++; + + t = _tokenSource.NextToken(); + } + // leave p pointing at first token on channel + p = 0; + p = SkipOffTokenChannels( p ); + } + + /** <summary> + * Move the input pointer to the next incoming token. The stream + * must become active with LT(1) available. consume() simply + * moves the input pointer so that LT(1) points at the next + * input symbol. Consume at least one token. + * </summary> + * + * <remarks> + * Walk past any token not on the channel the parser is listening to. + * </remarks> + */ + public void Consume() + { + if ( p < tokens.Count ) + { + p++; + p = SkipOffTokenChannels( p ); // leave p on valid token + } + } + + /** <summary>Given a starting index, return the index of the first on-channel token.</summary> */ + protected int SkipOffTokenChannels( int i ) + { + int n = tokens.Count; + while ( i < n && tokens[i].Channel != channel ) + { + i++; + } + return i; + } + + protected int SkipOffTokenChannelsReverse( int i ) + { + while ( i >= 0 && tokens[i].Channel != channel ) + { + i--; + } + return i; + } + + public IList<SlimToken> GetTokens() + { + if ( p == -1 ) + { + FillBuffer(); + } + return tokens; + } + + public IList<SlimToken> GetTokens( int start, int stop ) + { + return GetTokens( start, stop, (BitSet)null ); + } + + /** <summary> + * Given a start and stop index, return a List of all tokens in + * the token type BitSet. Return null if no tokens were found. This + * method looks at both on and off channel tokens. + * </summary> + */ + public IList<SlimToken> GetTokens( int start, int stop, BitSet types ) + { + if ( p == -1 ) + { + FillBuffer(); + } + if ( stop >= tokens.Count ) + { + stop = tokens.Count - 1; + } + if ( start < 0 ) + { + start = 0; + } + if ( start > stop ) + { + return null; + } + + // list = tokens[start:stop]:{Token t, t.getType() in types} + List<SlimToken> filteredTokens = new List<SlimToken>(); + for ( int i = start; i <= stop; i++ ) + { + SlimToken t = tokens[i]; + if ( types == null || types.Member( t.Type ) ) + { + filteredTokens.Add( t ); + } + } + if ( filteredTokens.Count == 0 ) + { + filteredTokens = null; + } + return filteredTokens; + } + + public IList<SlimToken> GetTokens( int start, int stop, IList<int> types ) + { + return GetTokens( start, stop, new BitSet( types ) ); + } + + public IList<SlimToken> GetTokens( int start, int stop, int ttype ) + { + return GetTokens( start, stop, BitSet.Of( ttype ) ); + } + + /** <summary> + * Get the ith token from the current position 1..n where k=1 is the + * first symbol of lookahead. + * </summary> + */ + public SlimToken LT( int k ) + { + if ( p == -1 ) + { + FillBuffer(); + } + if ( k == 0 ) + { + return default( SlimToken ); + } + if ( k < 0 ) + { + return LB( -k ); + } + //System.out.print("LT(p="+p+","+k+")="); + if ( ( p + k - 1 ) >= tokens.Count ) + { + return new SlimToken(TokenTypes.EndOfFile); + } + //System.out.println(tokens.get(p+k-1)); + int i = p; + int n = 1; + // find k good tokens + while ( n < k ) + { + // skip off-channel tokens + i = SkipOffTokenChannels( i + 1 ); // leave p on valid token + n++; + } + if ( i >= tokens.Count ) + { + return new SlimToken(TokenTypes.EndOfFile); + } + return tokens[i]; + } + + /** <summary>Look backwards k tokens on-channel tokens</summary> */ + protected SlimToken LB( int k ) + { + //System.out.print("LB(p="+p+","+k+") "); + if ( p == -1 ) + { + FillBuffer(); + } + if ( k == 0 ) + { + return default( SlimToken ); + } + if ( ( p - k ) < 0 ) + { + return default( SlimToken ); + } + + int i = p; + int n = 1; + // find k good tokens looking backwards + while ( n <= k ) + { + // skip off-channel tokens + i = SkipOffTokenChannelsReverse( i - 1 ); // leave p on valid token + n++; + } + if ( i < 0 ) + { + return default( SlimToken ); + } + return tokens[i]; + } + + /** <summary> + * Return absolute token i; ignore which channel the tokens are on; + * that is, count all tokens not just on-channel tokens. + * </summary> + */ + public SlimToken Get( int i ) + { + return tokens[i]; + } + + public int LA( int i ) + { + return LT( i ).Type; + } + + public int Mark() + { + if ( p == -1 ) + { + FillBuffer(); + } + lastMarker = Index; + return lastMarker; + } + + public void Release( int marker ) + { + // no resources to release + } + + public int Count + { + get + { + return tokens.Count; + } + } + + public void Rewind( int marker ) + { + Seek( marker ); + } + + public void Rewind() + { + Seek( lastMarker ); + } + + public void Reset() + { + p = 0; + lastMarker = 0; + } + + public void Seek( int index ) + { + p = index; + } + + public ITokenSource<SlimToken> TokenSource + { + get + { + return _tokenSource; + } + } + + public string SourceName + { + get + { + return TokenSource.SourceName; + } + } + + public override string ToString() + { + if ( p == -1 ) + { + throw new InvalidOperationException( "Buffer is not yet filled." ); + } + return ToString( 0, tokens.Count - 1 ); + } + + public virtual string ToString( int start, int stop ) + { + if ( start < 0 || stop < 0 ) + { + return null; + } + if ( p == -1 ) + { + throw new InvalidOperationException( "Buffer is not yet filled." ); + } + if ( stop >= tokens.Count ) + { + stop = tokens.Count - 1; + } + StringBuilder buf = new StringBuilder(); + for ( int i = start; i <= stop; i++ ) + { + SlimToken t = tokens[i]; + SlimLexer lexer = _tokenSource as SlimLexer; + if ( lexer != null ) + { + SlimStringStream input = lexer.CharStream as SlimStringStream; + if ( input != null ) + { + string text = input.Substring( t.StartIndex, t.StopIndex - t.StartIndex + 1 ); + buf.Append( text ); + } + } + } + return buf.ToString(); + } + + public virtual string ToString( IToken start, IToken stop ) + { + if ( start != null && stop != null ) + { + return ToString( start.TokenIndex, stop.TokenIndex ); + } + return null; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeAdaptor`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeAdaptor`1.cs new file mode 100644 index 0000000..dfb2ecf --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeAdaptor`1.cs @@ -0,0 +1,314 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Tree +{ + public interface ITreeAdaptor<T> + { + #region Construction + + /** <summary> + * Create a tree node from Token object; for CommonTree type trees, + * then the token just becomes the payload. This is the most + * common create call. + * </summary> + * + * <remarks> + * Override if you want another kind of node to be built. + * </remarks> + */ + T Create(IToken payload); + + /** <summary>Duplicate a single tree node.</summary> + * <remarks>Override if you want another kind of node to be built.</remarks> + */ + T DupNode(T treeNode); + + /** <summary>Duplicate tree recursively, using dupNode() for each node</summary> */ + T DupTree(T tree); + + /** <summary> + * Return a nil node (an empty but non-null node) that can hold + * a list of element as the children. If you want a flat tree (a list) + * use "t=adaptor.nil(); t.addChild(x); t.addChild(y);" + * </summary> + */ + T Nil(); + + /** <summary> + * Return a tree node representing an error. This node records the + * tokens consumed during error recovery. The start token indicates the + * input symbol at which the error was detected. The stop token indicates + * the last symbol consumed during recovery. + * </summary> + * + * </remarks> + * You must specify the input stream so that the erroneous text can + * be packaged up in the error node. The exception could be useful + * to some applications; default implementation stores ptr to it in + * the CommonErrorNode. + * + * This only makes sense during token parsing, not tree parsing. + * Tree parsing should happen only when parsing and tree construction + * succeed. + * </remarks> + */ + T ErrorNode(ITokenStream input, IToken start, IToken stop, RecognitionException e); + + /** <summary>Is tree considered a nil node used to make lists of child nodes?</summary> */ + bool IsNil(T tree); + + /** <summary> + * Add a child to the tree t. If child is a flat tree (a list), make all + * in list children of t. Warning: if t has no children, but child does + * and child isNil then you can decide it is ok to move children to t via + * t.children = child.children; i.e., without copying the array. Just + * make sure that this is consistent with have the user will build + * ASTs. Do nothing if t or child is null. + * </summary> + */ + void AddChild(T t, T child); + + /** <summary> + * If oldRoot is a nil root, just copy or move the children to newRoot. + * If not a nil root, make oldRoot a child of newRoot. + * </summary> + * + * <remarks> + * old=^(nil a b c), new=r yields ^(r a b c) + * old=^(a b c), new=r yields ^(r ^(a b c)) + * + * If newRoot is a nil-rooted single child tree, use the single + * child as the new root node. + * + * old=^(nil a b c), new=^(nil r) yields ^(r a b c) + * old=^(a b c), new=^(nil r) yields ^(r ^(a b c)) + * + * If oldRoot was null, it's ok, just return newRoot (even if isNil). + * + * old=null, new=r yields r + * old=null, new=^(nil r) yields ^(nil r) + * + * Return newRoot. Throw an exception if newRoot is not a + * simple node or nil root with a single child node--it must be a root + * node. If newRoot is ^(nil x) return x as newRoot. + * + * Be advised that it's ok for newRoot to point at oldRoot's + * children; i.e., you don't have to copy the list. We are + * constructing these nodes so we should have this control for + * efficiency. + * </remarks> + */ + T BecomeRoot(T newRoot, T oldRoot); + + /** <summary> + * Given the root of the subtree created for this rule, post process + * it to do any simplifications or whatever you want. A required + * behavior is to convert ^(nil singleSubtree) to singleSubtree + * as the setting of start/stop indexes relies on a single non-nil root + * for non-flat trees. + * </summary> + * + * <remarks> + * Flat trees such as for lists like "idlist : ID+ ;" are left alone + * unless there is only one ID. For a list, the start/stop indexes + * are set in the nil node. + * + * This method is executed after all rule tree construction and right + * before setTokenBoundaries(). + * </remarks> + */ + T RulePostProcessing(T root); + + /** <summary>For identifying trees.</summary> + * + * <remarks> + * How to identify nodes so we can say "add node to a prior node"? + * Even becomeRoot is an issue. Use System.identityHashCode(node) + * usually. + * </remarks> + */ + int GetUniqueID(T node); + + + // R e w r i t e R u l e s + + /** <summary> + * Create a node for newRoot make it the root of oldRoot. + * If oldRoot is a nil root, just copy or move the children to newRoot. + * If not a nil root, make oldRoot a child of newRoot. + * </summary> + * + * <returns> + * Return node created for newRoot. + * </returns> + * + * <remarks> + * Be advised: when debugging ASTs, the DebugTreeAdaptor manually + * calls create(Token child) and then plain becomeRoot(node, node) + * because it needs to trap calls to create, but it can't since it delegates + * to not inherits from the TreeAdaptor. + * </remarks> + */ + T BecomeRoot(IToken newRoot, T oldRoot); + + /** <summary> + * Create a new node derived from a token, with a new token type. + * This is invoked from an imaginary node ref on right side of a + * rewrite rule as IMAG[$tokenLabel]. + * </summary> + * + * <remarks> + * This should invoke createToken(Token). + * </remarks> + */ + T Create(int tokenType, IToken fromToken); + + /** <summary> + * Same as create(tokenType,fromToken) except set the text too. + * This is invoked from an imaginary node ref on right side of a + * rewrite rule as IMAG[$tokenLabel, "IMAG"]. + * </summary> + * + * <remarks> + * This should invoke createToken(Token). + * </remarks> + */ + T Create(int tokenType, IToken fromToken, string text); + + /** <summary> + * Create a new node derived from a token, with a new token type. + * This is invoked from an imaginary node ref on right side of a + * rewrite rule as IMAG["IMAG"]. + * </summary> + * + * <remarks> + * This should invoke createToken(int,String). + * </remarks> + */ + T Create(int tokenType, string text); + + #endregion + + + #region Content + + /** <summary>For tree parsing, I need to know the token type of a node</summary> */ + int GetType(T t); + + /** <summary>Node constructors can set the type of a node</summary> */ + void SetType(T t, int type); + + string GetText(T t); + + /** <summary>Node constructors can set the text of a node</summary> */ + void SetText(T t, string text); + + /** <summary> + * Return the token object from which this node was created. + * Currently used only for printing an error message. + * The error display routine in BaseRecognizer needs to + * display where the input the error occurred. If your + * tree of limitation does not store information that can + * lead you to the token, you can create a token filled with + * the appropriate information and pass that back. See + * BaseRecognizer.getErrorMessage(). + * </summary> + */ + IToken GetToken(T t); + + /** <summary> + * Where are the bounds in the input token stream for this node and + * all children? Each rule that creates AST nodes will call this + * method right before returning. Flat trees (i.e., lists) will + * still usually have a nil root node just to hold the children list. + * That node would contain the start/stop indexes then. + * </summary> + */ + void SetTokenBoundaries(T t, IToken startToken, IToken stopToken); + + /** <summary>Get the token start index for this subtree; return -1 if no such index</summary> */ + int GetTokenStartIndex(T t); + + /** <summary>Get the token stop index for this subtree; return -1 if no such index</summary> */ + int GetTokenStopIndex(T t); + + #endregion + + + #region Navigation / Tree Parsing + + /** <summary>Get a child 0..n-1 node</summary> */ + T GetChild(T t, int i); + + /** <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary> */ + void SetChild(T t, int i, T child); + + /** <summary>Remove ith child and shift children down from right.</summary> */ + T DeleteChild(T t, int i); + + /** <summary>How many children? If 0, then this is a leaf node</summary> */ + int GetChildCount(T t); + + /** <summary> + * Who is the parent node of this node; if null, implies node is root. + * If your node type doesn't handle this, it's ok but the tree rewrites + * in tree parsers need this functionality. + * </summary> + */ + T GetParent(T t); + void SetParent(T t, T parent); + + /** <summary> + * What index is this node in the child list? Range: 0..n-1 + * If your node type doesn't handle this, it's ok but the tree rewrites + * in tree parsers need this functionality. + * </summary> + */ + int GetChildIndex(T t); + void SetChildIndex(T t, int index); + + /** <summary> + * Replace from start to stop child index of parent with t, which might + * be a list. Number of children may be different after this call. + * </summary> + * + * <remarks> + * If parent is null, don't do anything; must be at root of overall tree. + * Can't replace whatever points to the parent externally. Do nothing. + * </remarks> + */ + void ReplaceChildren(T parent, int startChildIndex, int stopChildIndex, T t); + + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeFactory.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeFactory.cs new file mode 100644 index 0000000..4b17634 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeFactory.cs @@ -0,0 +1,54 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Tree +{ + public interface ITreeFactory<TToken, TTree> + where TToken : IToken + where TTree : ITree + { + TTree Create( TToken payload ); + + TTree CloneTree( TTree tree ); + + TTree CloneNode( TTree node ); + + TTree Nil(); + + TTree CreateErrorNode( ITokenStream<TToken> input, TToken start, TToken stop, RecognitionException e ); + } + + public interface ITreeFactory + : ITreeFactory<IToken, ITree> + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeNodeStream`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeNodeStream`1.cs new file mode 100644 index 0000000..f23183f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/SlimParsing/Tree/ITreeNodeStream`1.cs @@ -0,0 +1,142 @@ +/* + * [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.Tree +{ + public interface ITreeNodeStream<T> + { + /** <summary> + * Get a tree node at an absolute index i; 0..n-1. + * If you don't want to buffer up nodes, then this method makes no + * sense for you. + * </summary> + */ + T this[int i] + { + get; + } + + /** <summary> + * Get tree node at current input pointer + i ahead where i=1 is next node. + * i<0 indicates nodes in the past. So LT(-1) is previous node, but + * implementations are not required to provide results for k < -1. + * LT(0) is undefined. For i>=n, return null. + * Return null for LT(0) and any index that results in an absolute address + * that is negative. + * </summary> + * + * <remarks> + * This is analogus to the LT() method of the TokenStream, but this + * returns a tree node instead of a token. Makes code gen identical + * for both parser and tree grammars. :) + * </remarks> + */ + T LT(int k); + + /** <summary> + * Where is this stream pulling nodes from? This is not the name, but + * the object that provides node objects. + * </summary> + */ + object TreeSource + { + get; + } + + /** <summary> + * If the tree associated with this stream was created from a TokenStream, + * you can specify it here. Used to do rule $text attribute in tree + * parser. Optional unless you use tree parser rule text attribute + * or output=template and rewrite=true options. + * </summary> + */ + ITokenStream TokenStream + { + get; + } + + /** <summary> + * What adaptor can tell me how to interpret/navigate nodes and + * trees. E.g., get text of a node. + * </summary> + */ + ITreeAdaptor<T> TreeAdaptor + { + get; + } + + /** <summary> + * As we flatten the tree, we use UP, DOWN nodes to represent + * the tree structure. When debugging we need unique nodes + * so we have to instantiate new ones. When doing normal tree + * parsing, it's slow and a waste of memory to create unique + * navigation nodes. Default should be false; + * </summary> + */ + bool UniqueNavigationNodes + { + get; + set; + } + + /** <summary> + * Return the text of all nodes from start to stop, inclusive. + * If the stream does not buffer all the nodes then it can still + * walk recursively from start until stop. You can always return + * null or "" too, but users should not access $ruleLabel.text in + * an action of course in that case. + * </summary> + */ + string ToString(T start, T stop); + + + #region REWRITING TREES (used by tree parser) + + /** <summary> + * Replace from start to stop child index of parent with t, which might + * be a list. Number of children may be different + * after this call. The stream is notified because it is walking the + * tree and might need to know you are monkeying with the underlying + * tree. Also, it might be able to modify the node stream to avoid + * restreaming for future phases. + * </summary> + * + * <remarks> + * If parent is null, don't do anything; must be at root of overall tree. + * Can't replace whatever points to the parent externally. Do nothing. + * </remarks> + */ + void ReplaceChildren(T parent, int startChildIndex, int stopChildIndex, T t); + + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3 new file mode 100644 index 0000000..886e48a --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3 @@ -0,0 +1,36 @@ +grammar StringTemplateOutput; + +options { + language=CSharp3; + TokenLabelType=CommonToken; + output=template; +} + +@lexer::namespace{Antlr3.Runtime.Test} +@parser::namespace{Antlr3.Runtime.Test} + +/* + * Parser Rules + */ + +public +compileUnit + : ID integer EOF + -> new(id={$ID.text}, value={$integer.st}) + ; + +integer + : i='int' -> {%{$i.text}} + ; + +/* + * Lexer Rules + */ + +ID + : 'a'..'z'* + ; + +WS + : ' ' + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3.lexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3.lexer.cs new file mode 100644 index 0000000..181f982 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3.lexer.cs @@ -0,0 +1,6 @@ +namespace Antlr3.Runtime.Test +{ + partial class StringTemplateOutputLexer + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3.parser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3.parser.cs new file mode 100644 index 0000000..5a419b2 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/StringTemplateOutput.g3.parser.cs @@ -0,0 +1,6 @@ +namespace Antlr3.Runtime.Test +{ + partial class StringTemplateOutputParser + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3 new file mode 100644 index 0000000..174526f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3 @@ -0,0 +1,65 @@ +grammar TestActionFeatures; + +options { + language=CSharp3; + TokenLabelType=CommonToken; + output=AST; + ASTLabelType=CommonTree; +} + +@lexer::namespace{Antlr3.Runtime.Test} +@parser::namespace{Antlr3.Runtime.Test} + +@parser::header{using Console = System.Console;} + +/* + * Parser Rules + */ + +public +compileUnit + : EOF + ; + +// SET_DYNAMIC_SCOPE_ATTR + +setDynamicScopeAttr +scope {int i;} + : EOF {$setDynamicScopeAttr::i=3; $setDynamicScopeAttr[0]::i=3; $setDynamicScopeAttr[-0]::i=3;} + ; + +// DYNAMIC_SCOPE_ATTR + +dynamicScopeAttr +scope {int i;} + : EOF {Console.WriteLine($dynamicScopeAttr::i);} + ; + +// DYNAMIC_NEGATIVE_INDEXED_SCOPE_ATTR + +dynamicNegativeIndexedScopeAttr +scope {int i;} + : EOF {Console.WriteLine($dynamicNegativeIndexedScopeAttr[-1]::i);} + ; + +// DYNAMIC_ABSOLUTE_INDEXED_SCOPE_ATTR + +dynamicAbsoluteIndexedScopeAttr +scope {int i;} + : EOF {Console.WriteLine($dynamicNegativeIndexedScopeAttr[0]::i);} + ; + +// ISOLATED_DYNAMIC_SCOPE + +isolatedDynamicScope +scope {int i;} + : EOF {Console.WriteLine($isolatedDynamicScope.Count);} + ; + +/* + * Lexer Rules + */ + +WS + : ' ' + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3.lexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3.lexer.cs new file mode 100644 index 0000000..e474324 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3.lexer.cs @@ -0,0 +1,6 @@ +namespace Antlr3.Runtime.Test +{ + partial class TestActionFeaturesLexer + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3.parser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3.parser.cs new file mode 100644 index 0000000..cedcf79 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestActionFeatures.g3.parser.cs @@ -0,0 +1,6 @@ +namespace Antlr3.Runtime.Test +{ + partial class TestActionFeaturesParser + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestDotTreeGenerator.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestDotTreeGenerator.cs new file mode 100644 index 0000000..b784f08 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestDotTreeGenerator.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 Antlr3.Runtime.Test +{ + using System; + using Antlr.Runtime; + using Antlr.Runtime.Tree; + using Microsoft.VisualStudio.TestTools.UnitTesting; + + [TestClass] + public class TestDotTreeGenerator + { + [TestMethod] + public void TestCreateDot() + { + ANTLRStringStream input = new ANTLRStringStream( "3 * x" ); + SimpleExpressionLexer lexer = new SimpleExpressionLexer( input ); + CommonTokenStream tokens = new CommonTokenStream( lexer ); + SimpleExpressionParser parser = new SimpleExpressionParser( tokens ); + var result = parser.expression(); + + var tree = result.Tree; + var adaptor = parser.TreeAdaptor; + + DotTreeGenerator gen = new DotTreeGenerator(); + string output = gen.ToDot( tree, adaptor ); + string newline = Environment.NewLine; + string expected = + @"digraph {" + newline + + newline + + @" ordering=out;" + newline + + @" ranksep=.4;" + newline + + @" bgcolor=""lightgrey""; node [shape=box, fixedsize=false, fontsize=12, fontname=""Helvetica-bold"", fontcolor=""blue""" + newline + + @" width=.25, height=.25, color=""black"", fillcolor=""white"", style=""filled, solid, bold""];" + newline + + @" edge [arrowsize=.5, color=""black"", style=""bold""]" + newline + + newline + + @" n0 [label=""""];" + newline + + @" n1 [label=""*""];" + newline + + @" n1 [label=""*""];" + newline + + @" n2 [label=""3""];" + newline + + @" n3 [label=""x""];" + newline + + @" n4 [label=""""];" + newline + + newline + + @" n0 -> n1 // """" -> ""*""" + newline + + @" n1 -> n2 // ""*"" -> ""3""" + newline + + @" n1 -> n3 // ""*"" -> ""x""" + newline + + @" n0 -> n4 // """" -> """"" + newline + + newline + + @"}" + newline + + @""; + + Assert.AreEqual( expected, output ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3 b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3 new file mode 100644 index 0000000..4fb0ae2 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3 @@ -0,0 +1,160 @@ +/* + * [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. + */ + +grammar TestExpressionFeatures; + +options { + language=CSharp3; + TokenLabelType=CommonToken; + output=AST; + ASTLabelType=CommonTree; +} + +tokens { + LPAREN = '('; + RPAREN = ')'; + DOT = '.'; + LBRACK = '['; + RBRACK = ']'; + INC = '++'; + DEC = '--'; + PLUS = '+'; + MINUS = '-'; + TILDE = '~'; + NOT = '!'; + //LSHIFT = '<<'; + //RSHIFT = '>>'; + //RUSHIFT = '>>>'; + EQUALS = '=='; + NOTEQ = '!='; + MOD = '%'; + CARET = '^'; + GT = '>'; + LT = '<'; + GE = '>='; + LE = '<='; + BITAND = '&'; + BITOR = '|'; + AND = '&&'; + OR = '||'; + + KW_THIS = 'this'; + KW_SUPER = 'super'; + KW_CLASS = 'class'; + KW_NEW = 'new'; + KW_INSTANCEOF = 'instanceof'; + KW_INT = 'int'; +} + +@lexer::namespace{Antlr3.Runtime.Test} +@parser::namespace{Antlr3.Runtime.Test} + +@parser::header{using Console = System.Console;} + +/* + * Parser Rules + */ + +public +compileUnit + : e EOF + ; + +e : '('! e ')'! + | 'this' + | 'super' + | INT + | ID + | type '.'^ 'class' + | e '.'^ ID + | e '.'^ 'this' + | e '.'^ 'super' '('^ expressionList? ')'! + | e '.'^ 'new'^ ID '('! expressionList? ')'! + | 'new'^ type ( '(' expressionList? ')'! | (options {k=1;}:'[' e ']'!)+) + | e '['^ e ']'! + | '('^ type ')'! e + | e ('++'^ | '--'^) + | e '('^ expressionList? ')'! + | ('+'^|'-'^|'++'^|'--'^) e + | ('~'^|'!'^) e + | e ('*'^|'/'^|'%'^) e + | e ('+'^|'-'^) e + | e ('<' '<' | '>' '>' '>' | '>' '>') e + | e ('<='^ | '>='^ | '>'^ | '<'^) e + | e 'instanceof'^ e + | e ('=='^ | '!='^) e + | e '&'^ e + | e '^'<assoc=right>^ e + | e '|'^ e + | e '&&'^ e + | e '||'^ e +// | e '?' e ':' e + | e ('='<assoc=right>^ + |'+='<assoc=right>^ + |'-='<assoc=right>^ + |'*='<assoc=right>^ + |'/='<assoc=right>^ + |'&='<assoc=right>^ + |'|='<assoc=right>^ + |'^='<assoc=right>^ + |'>>='<assoc=right>^ + |'>>>='<assoc=right>^ + |'<<='<assoc=right>^ + |'<<<='<assoc=right>^ + |'%='<assoc=right>^) e + ; + +expressionList + : e (','! e)* + ; + +type: ID + | ID '['^ ']'! + | 'int' + | 'int' '['^ ']'! + ; + +/* + * Lexer Rules + */ + +WS + : (' ' | '\t' | '\n' | '\r') {Skip();} + ; + +ID + : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '0'..'9' | '_')* + ; + +INT + : '0'..'9'+ + ; diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3.lexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3.lexer.cs new file mode 100644 index 0000000..3ad3d8e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3.lexer.cs @@ -0,0 +1,38 @@ +/* + * [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 Antlr3.Runtime.Test +{ + partial class TestExpressionFeaturesLexer + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3.parser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3.parser.cs new file mode 100644 index 0000000..e452e7c --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestExpressionFeatures.g3.parser.cs @@ -0,0 +1,38 @@ +/* + * [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 Antlr3.Runtime.Test +{ + partial class TestExpressionFeaturesParser + { + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestFastLexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestFastLexer.cs new file mode 100644 index 0000000..4edc329 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.Test/TestFastLexer.cs @@ -0,0 +1,94 @@ +/* + * [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 Antlr3.Runtime.Test +{ + using System; + using Antlr.Runtime; + using Antlr.Runtime.Tree; + using Microsoft.VisualStudio.TestTools.UnitTesting; + using System.Text; + + [TestClass] + public class TestFastLexer + { + [TestMethod] + public void TestBasicFastLexer() + { + string inputElement = "x-2356*Abte+32+eno/6623+y"; + StringBuilder builder = new StringBuilder( inputElement, 1000000 * inputElement.Length ); + for ( int i = 0; i < 999999; i++ ) + builder.Append( inputElement ); + + string text = builder.ToString(); + int iterations = 5; + // warmup + IterateFast( text, iterations ); + Iterate( text, iterations ); + + var time = Iterate( text, iterations ); + var timeFast = IterateFast( text, iterations ); + + Console.WriteLine( "Elapsed time (norm): {0} seconds.", time.TotalSeconds ); + Console.WriteLine( "Elapsed time (fast): {0} seconds.", timeFast.TotalSeconds ); + } + + TimeSpan Iterate( string text, int count ) + { + DateTime start = DateTime.Now; + + for ( int i = 0; i < count; i++ ) + { + SimpleExpressionLexer lexer = new SimpleExpressionLexer( new ANTLRStringStream( text ) ); + CommonTokenStream tokens = new CommonTokenStream( lexer ); + tokens.Fill(); + } + + return DateTime.Now - start; + } + + TimeSpan IterateFast( string text, int count ) + { + DateTime start = DateTime.Now; + + for ( int i = 0; i < count; i++ ) + { + FastSimpleExpressionLexer lexer = new FastSimpleExpressionLexer( new SlimStringStream( text ) ); + FastTokenStream tokens = new FastTokenStream( lexer ); + //FastTokenStream<SlimToken> tokens = new FastTokenStream<SlimToken>( lexer ); + tokens.FillBuffer(); + } + + return DateTime.Now - start; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.sln b/runtime/CSharp3/Sources/Antlr3.Runtime.sln new file mode 100644 index 0000000..1550134 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.sln @@ -0,0 +1,36 @@ + +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Antlr3.Runtime", "Antlr3.Runtime\Antlr3.Runtime.csproj", "{8FDC0A87-9005-4D5A-AB75-E55CEB575559}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Antlr3.Runtime.Debug", "Antlr3.Runtime.Debug\Antlr3.Runtime.Debug.csproj", "{5EE27A90-B023-42C9-AAF1-52B0424C5D0B}" +EndProject +Global + GlobalSection(SourceCodeControl) = preSolution + SccNumberOfProjects = 3 + SccLocalPath0 = . + SccProjectUniqueName1 = Antlr3.Runtime\\Antlr3.Runtime.csproj + SccLocalPath1 = . + SccProjectFilePathRelativizedFromConnection1 = Antlr3.Runtime\\ + SccProjectUniqueName2 = Antlr3.Runtime.Debug\\Antlr3.Runtime.Debug.csproj + SccLocalPath2 = . + SccProjectFilePathRelativizedFromConnection2 = Antlr3.Runtime.Debug\\ + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8FDC0A87-9005-4D5A-AB75-E55CEB575559}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8FDC0A87-9005-4D5A-AB75-E55CEB575559}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8FDC0A87-9005-4D5A-AB75-E55CEB575559}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8FDC0A87-9005-4D5A-AB75-E55CEB575559}.Release|Any CPU.Build.0 = Release|Any CPU + {5EE27A90-B023-42C9-AAF1-52B0424C5D0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5EE27A90-B023-42C9-AAF1-52B0424C5D0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5EE27A90-B023-42C9-AAF1-52B0424C5D0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5EE27A90-B023-42C9-AAF1-52B0424C5D0B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime.vssscc b/runtime/CSharp3/Sources/Antlr3.Runtime.vssscc new file mode 100644 index 0000000..6cb031b --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime.vssscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRFileStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRFileStream.cs new file mode 100644 index 0000000..b4725e3 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRFileStream.cs @@ -0,0 +1,88 @@ +/* + * [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 +{ + using Encoding = System.Text.Encoding; + using File = System.IO.File; + + /** <summary> + * This is a char buffer stream that is loaded from a file + * all at once when you construct the object. This looks very + * much like an ANTLReader or ANTLRInputStream, but it's a special case + * since we know the exact size of the object to load. We can avoid lots + * of data copying. + * </summary> + */ + [System.Serializable] + [System.Security.Permissions.FileIOPermission(System.Security.Permissions.SecurityAction.Demand, Unrestricted = true)] + public class ANTLRFileStream : ANTLRStringStream + { + protected string fileName; + + public ANTLRFileStream( string fileName ) + : this( fileName, null ) + { + } + + public ANTLRFileStream( string fileName, Encoding encoding ) + { + this.fileName = fileName; + Load( fileName, encoding ); + } + + public virtual void Load( string fileName, Encoding encoding ) + { + if ( fileName == null ) + { + return; + } + + string text; + if (encoding == null) + text = File.ReadAllText(fileName); + else + text = File.ReadAllText(fileName, encoding); + + data = text.ToCharArray(); + n = data.Length; + } + + public override string SourceName + { + get + { + return fileName; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRInputStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRInputStream.cs new file mode 100644 index 0000000..16b6b61 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRInputStream.cs @@ -0,0 +1,79 @@ +/* + * [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 +{ + using Encoding = System.Text.Encoding; + using Stream = System.IO.Stream; + using StreamReader = System.IO.StreamReader; + + /** <summary> + * A kind of ReaderStream that pulls from an InputStream. + * Useful for reading from stdin and specifying file encodings etc... + * </summary> + */ + [System.Serializable] + public class ANTLRInputStream : ANTLRReaderStream + { + public ANTLRInputStream( Stream input ) + : this( input, null ) + { + } + + public ANTLRInputStream( Stream input, int size ) + : this( input, size, null ) + { + } + + public ANTLRInputStream( Stream input, Encoding encoding ) + : this( input, InitialBufferSize, encoding ) + { + } + + public ANTLRInputStream( Stream input, int size, Encoding encoding ) + : this( input, size, ReadBufferSize, encoding ) + { + } + + public ANTLRInputStream( Stream input, int size, int readBufferSize, Encoding encoding ) + : base(GetStreamReader(input, encoding), size, readBufferSize) + { + } + + private static StreamReader GetStreamReader(Stream input, Encoding encoding) + { + if (encoding != null) + return new StreamReader(input, encoding); + return new StreamReader(input); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRReaderStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRReaderStream.cs new file mode 100644 index 0000000..b8ecc26 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRReaderStream.cs @@ -0,0 +1,93 @@ +/* + * [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 +{ + using TextReader = System.IO.TextReader; + + /** <summary> + * Vacuum all input from a Reader and then treat it like a StringStream. + * Manage the buffer manually to avoid unnecessary data copying. + * </summary> + * + * <remarks> + * If you need encoding, use ANTLRInputStream. + * </remarks> + */ + [System.Serializable] + public class ANTLRReaderStream : ANTLRStringStream + { + public const int ReadBufferSize = 1024; + public const int InitialBufferSize = 1024; + + public ANTLRReaderStream( TextReader r ) + : this( r, InitialBufferSize, ReadBufferSize ) + { + } + + public ANTLRReaderStream( TextReader r, int size ) + : this( r, size, ReadBufferSize ) + { + } + + public ANTLRReaderStream( TextReader r, int size, int readChunkSize ) + { + Load( r, size, readChunkSize ); + } + + public virtual void Load( TextReader r, int size, int readChunkSize ) + { + if ( r == null ) + { + return; + } + if ( size <= 0 ) + { + size = InitialBufferSize; + } + if ( readChunkSize <= 0 ) + { + readChunkSize = ReadBufferSize; + } + // System.out.println("load "+size+" in chunks of "+readChunkSize); + try + { + data = r.ReadToEnd().ToCharArray(); + base.n = data.Length; + } + finally + { + r.Close(); + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRStringStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRStringStream.cs new file mode 100644 index 0000000..9904680 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ANTLRStringStream.cs @@ -0,0 +1,327 @@ +/* + * [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 +{ + using System.Collections.Generic; + using ArgumentException = System.ArgumentException; + using ArgumentOutOfRangeException = System.ArgumentOutOfRangeException; + using ArgumentNullException = System.ArgumentNullException; + + /** <summary> + * A pretty quick CharStream that pulls all data from an array + * directly. Every method call counts in the lexer. Java's + * strings aren't very good so I'm avoiding. + * </summary> + */ + [System.Serializable] + public class ANTLRStringStream : ICharStream + { + /** <summary>The data being scanned</summary> */ + protected char[] data; + + /** <summary>How many characters are actually in the buffer</summary> */ + protected int n; + + /** <summary>0..n-1 index into string of next char</summary> */ + protected int p = 0; + + /** <summary>line number 1..n within the input</summary> */ + int line = 1; + + /** <summary>The index of the character relative to the beginning of the line 0..n-1</summary> */ + int charPositionInLine = 0; + + /** <summary>tracks how deep mark() calls are nested</summary> */ + protected int markDepth = 0; + + /** <summary> + * A list of CharStreamState objects that tracks the stream state + * values line, charPositionInLine, and p that can change as you + * move through the input stream. Indexed from 1..markDepth. + * A null is kept @ index 0. Create upon first call to mark(). + * </summary> + */ + protected IList<CharStreamState> markers; + + /** <summary>Track the last mark() call result value for use in rewind().</summary> */ + protected int lastMarker; + + /** <summary>What is name or source of this char stream?</summary> */ + public string name; + + /** <summary>Copy data in string to a local char array</summary> */ + public ANTLRStringStream( string input ) + : this( input, null ) + { + } + + public ANTLRStringStream( string input, string sourceName ) + : this( input.ToCharArray(), input.Length, sourceName ) + { + } + + /** <summary>This is the preferred constructor as no data is copied</summary> */ + public ANTLRStringStream( char[] data, int numberOfActualCharsInArray ) + : this( data, numberOfActualCharsInArray, null ) + { + } + + public ANTLRStringStream( char[] data, int numberOfActualCharsInArray, string sourceName ) + { + if (data == null) + throw new ArgumentNullException("data"); + if (numberOfActualCharsInArray < 0) + throw new ArgumentOutOfRangeException(); + if (numberOfActualCharsInArray > data.Length) + throw new ArgumentException(); + + this.data = data; + this.n = numberOfActualCharsInArray; + this.name = sourceName; + } + + protected ANTLRStringStream() + { + this.data = new char[0]; + } + + /** <summary> + * Return the current input symbol index 0..n where n indicates the + * last symbol has been read. The index is the index of char to + * be returned from LA(1). + * </summary> + */ + public virtual int Index + { + get + { + return p; + } + } + public virtual int Line + { + get + { + return line; + } + set + { + line = value; + } + } + public virtual int CharPositionInLine + { + get + { + return charPositionInLine; + } + set + { + charPositionInLine = value; + } + } + + /** <summary> + * Reset the stream so that it's in the same state it was + * when the object was created *except* the data array is not + * touched. + * </summary> + */ + public virtual void Reset() + { + p = 0; + line = 1; + charPositionInLine = 0; + markDepth = 0; + } + + public virtual void Consume() + { + //System.out.println("prev p="+p+", c="+(char)data[p]); + if ( p < n ) + { + charPositionInLine++; + if ( data[p] == '\n' ) + { + /* + System.out.println("newline char found on line: "+line+ + "@ pos="+charPositionInLine); + */ + line++; + charPositionInLine = 0; + } + p++; + //System.out.println("p moves to "+p+" (c='"+(char)data[p]+"')"); + } + } + + public virtual int LA( int i ) + { + if ( i == 0 ) + { + return 0; // undefined + } + if ( i < 0 ) + { + i++; // e.g., translate LA(-1) to use offset i=0; then data[p+0-1] + if ( ( p + i - 1 ) < 0 ) + { + return CharStreamConstants.EndOfFile; // invalid; no char before first char + } + } + + if ( ( p + i - 1 ) >= n ) + { + //System.out.println("char LA("+i+")=EOF; p="+p); + return CharStreamConstants.EndOfFile; + } + //System.out.println("char LA("+i+")="+(char)data[p+i-1]+"; p="+p); + //System.out.println("LA("+i+"); p="+p+" n="+n+" data.length="+data.length); + return data[p + i - 1]; + } + + public virtual int LT( int i ) + { + return LA( i ); + } + + public virtual int Count + { + get + { + return n; + } + } + + public virtual int Mark() + { + if ( markers == null ) + { + markers = new List<CharStreamState>(); + markers.Add( null ); // depth 0 means no backtracking, leave blank + } + markDepth++; + CharStreamState state = null; + if ( markDepth >= markers.Count ) + { + state = new CharStreamState(); + markers.Add( state ); + } + else + { + state = markers[markDepth]; + } + state.p = p; + state.line = line; + state.charPositionInLine = charPositionInLine; + lastMarker = markDepth; + return markDepth; + } + + public virtual void Rewind( int m ) + { + if (m < 0) + throw new ArgumentOutOfRangeException(); + + //if (m > markDepth) + // throw new ArgumentException(); + + CharStreamState state = markers[m]; + // restore stream state + Seek( state.p ); + line = state.line; + charPositionInLine = state.charPositionInLine; + Release( m ); + } + + public virtual void Rewind() + { + Rewind( lastMarker ); + } + + public virtual void Release( int marker ) + { + // unwind any other markers made after m and release m + markDepth = marker; + // release this marker + markDepth--; + } + + /** <summary> + * consume() ahead until p==index; can't just set p=index as we must + * update line and charPositionInLine. + * </summary> + */ + public virtual void Seek( int index ) + { + if ( index <= p ) + { + p = index; // just jump; don't update stream state (line, ...) + return; + } + // seek forward, consume until p hits index + while ( p < index ) + { + Consume(); + } + } + + public virtual string Substring( int start, int length ) + { + if (start < 0) + throw new ArgumentOutOfRangeException(); + if (length < 0) + throw new ArgumentOutOfRangeException(); + if (start + length > data.Length) + throw new ArgumentException(); + + if (length == 0) + return string.Empty; + + return new string( data, start, length ); + } + + public virtual string SourceName + { + get + { + return name; + } + } + + public override string ToString() + { + return new string(data); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Antlr3.Runtime.csproj b/runtime/CSharp3/Sources/Antlr3.Runtime/Antlr3.Runtime.csproj new file mode 100644 index 0000000..6de4bf7 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Antlr3.Runtime.csproj @@ -0,0 +1,146 @@ +<?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>{8FDC0A87-9005-4D5A-AB75-E55CEB575559}</ProjectGuid> + <OutputType>Library</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <RootNamespace>Antlr.Runtime</RootNamespace> + <AssemblyName>Antlr3.Runtime</AssemblyName> + <TargetFrameworkVersion>v2.0</TargetFrameworkVersion> + <FileAlignment>512</FileAlignment> + <SccProjectName>SAK</SccProjectName> + <SccLocalPath>SAK</SccLocalPath> + <SccAuxPath>SAK</SccAuxPath> + <SccProvider>SAK</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="ANTLRFileStream.cs" /> + <Compile Include="ANTLRInputStream.cs" /> + <Compile Include="ANTLRReaderStream.cs" /> + <Compile Include="ANTLRStringStream.cs" /> + <Compile Include="AstParserRuleReturnScope`2.cs" /> + <Compile Include="BaseRecognizer.cs" /> + <Compile Include="BitSet.cs" /> + <Compile Include="BufferedTokenStream.cs" /> + <Compile Include="CharStreamConstants.cs" /> + <Compile Include="CharStreamState.cs" /> + <Compile Include="ClassicToken.cs" /> + <Compile Include="CommonToken.cs" /> + <Compile Include="CommonTokenStream.cs" /> + <Compile Include="Debug\IDebugEventListener.cs" /> + <Compile Include="DFA.cs" /> + <Compile Include="EarlyExitException.cs" /> + <Compile Include="FailedPredicateException.cs" /> + <Compile Include="GrammarRuleAttribute.cs" /> + <Compile Include="IAstRuleReturnScope.cs" /> + <Compile Include="IAstRuleReturnScope`1.cs" /> + <Compile Include="ICharStream.cs" /> + <Compile Include="IIntStream.cs" /> + <Compile Include="IRuleReturnScope.cs" /> + <Compile Include="IRuleReturnScope`1.cs" /> + <Compile Include="ITemplateRuleReturnScope.cs" /> + <Compile Include="ITemplateRuleReturnScope`1.cs" /> + <Compile Include="IToken.cs" /> + <Compile Include="ITokenSource.cs" /> + <Compile Include="ITokenStream.cs" /> + <Compile Include="ITokenStreamInformation.cs" /> + <Compile Include="LegacyCommonTokenStream.cs" /> + <Compile Include="Lexer.cs" /> + <Compile Include="Misc\FastQueue.cs" /> + <Compile Include="Misc\FunctionDelegates.cs" /> + <Compile Include="Misc\ListStack`1.cs" /> + <Compile Include="Misc\LookaheadStream.cs" /> + <Compile Include="MismatchedNotSetException.cs" /> + <Compile Include="MismatchedRangeException.cs" /> + <Compile Include="MismatchedSetException.cs" /> + <Compile Include="MismatchedTokenException.cs" /> + <Compile Include="MismatchedTreeNodeException.cs" /> + <Compile Include="MissingTokenException.cs" /> + <Compile Include="NoViableAltException.cs" /> + <Compile Include="Parser.cs" /> + <Compile Include="ParserRuleReturnScope.cs" /> + <Compile Include="Properties\AssemblyInfo.cs" /> + <Compile Include="RecognitionException.cs" /> + <Compile Include="RecognizerSharedState.cs" /> + <Compile Include="TemplateParserRuleReturnScope`2.cs" /> + <Compile Include="TokenChannels.cs" /> + <Compile Include="TokenRewriteStream.cs" /> + <Compile Include="Tokens.cs" /> + <Compile Include="TokenTypes.cs" /> + <Compile Include="Tree\AstTreeRuleReturnScope`2.cs" /> + <Compile Include="Tree\BaseTree.cs" /> + <Compile Include="Tree\BaseTreeAdaptor.cs" /> + <Compile Include="Tree\AntlrRuntime_BaseTreeDebugView.cs" /> + <Compile Include="Tree\BufferedTreeNodeStream.cs" /> + <Compile Include="Tree\CommonErrorNode.cs" /> + <Compile Include="Tree\CommonTree.cs" /> + <Compile Include="Tree\CommonTreeAdaptor.cs" /> + <Compile Include="Tree\CommonTreeNodeStream.cs" /> + <Compile Include="Tree\DotTreeGenerator.cs" /> + <Compile Include="Tree\ITree.cs" /> + <Compile Include="Tree\ITreeAdaptor.cs" /> + <Compile Include="Tree\ITreeNodeStream.cs" /> + <Compile Include="Tree\ITreeVisitorAction.cs" /> + <Compile Include="Tree\ParseTree.cs" /> + <Compile Include="Tree\RewriteCardinalityException.cs" /> + <Compile Include="Tree\RewriteEarlyExitException.cs" /> + <Compile Include="Tree\RewriteEmptyStreamException.cs" /> + <Compile Include="Tree\RewriteRuleElementStream.cs" /> + <Compile Include="Tree\RewriteRuleNodeStream.cs" /> + <Compile Include="Tree\RewriteRuleSubtreeStream.cs" /> + <Compile Include="Tree\RewriteRuleTokenStream.cs" /> + <Compile Include="Tree\TemplateTreeRuleReturnScope`2.cs" /> + <Compile Include="Tree\TreeFilter.cs" /> + <Compile Include="Tree\TreeIterator.cs" /> + <Compile Include="Tree\TreeParser.cs" /> + <Compile Include="Tree\TreePatternLexer.cs" /> + <Compile Include="Tree\TreePatternParser.cs" /> + <Compile Include="Tree\TreeRewriter.cs" /> + <Compile Include="Tree\TreeRuleReturnScope`1.cs" /> + <Compile Include="Tree\TreeVisitor.cs" /> + <Compile Include="Tree\TreeWizard.cs" /> + <Compile Include="UnbufferedTokenStream.cs" /> + <Compile Include="UnwantedTokenException.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="..\..\..\..\..\..\..\keys\antlr\Key.snk"> + <Link>Key.snk</Link> + </None> + </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/Antlr3.Runtime.csproj.vspscc b/runtime/CSharp3/Sources/Antlr3.Runtime/Antlr3.Runtime.csproj.vspscc new file mode 100644 index 0000000..b6d3289 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Antlr3.Runtime.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/AstParserRuleReturnScope`2.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/AstParserRuleReturnScope`2.cs new file mode 100644 index 0000000..0ebe32d --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/AstParserRuleReturnScope`2.cs @@ -0,0 +1,60 @@ +/* + * [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 +{ + public class AstParserRuleReturnScope<TTree, TToken> : ParserRuleReturnScope<TToken>, IAstRuleReturnScope<TTree>, IAstRuleReturnScope + { + private TTree _tree; + + public TTree Tree + { + get + { + return _tree; + } + + set + { + _tree = value; + } + } + + object IAstRuleReturnScope.Tree + { + get + { + return Tree; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/BaseRecognizer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/BaseRecognizer.cs new file mode 100644 index 0000000..5ba18f5 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/BaseRecognizer.cs @@ -0,0 +1,1184 @@ +/* + * [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 +{ + using System.Collections.Generic; + + using ArgumentNullException = System.ArgumentNullException; + using Array = System.Array; + using Conditional = System.Diagnostics.ConditionalAttribute; + using Exception = System.Exception; + using IDebugEventListener = Antlr.Runtime.Debug.IDebugEventListener; + using MethodBase = System.Reflection.MethodBase; + using NotSupportedException = System.NotSupportedException; + using Regex = System.Text.RegularExpressions.Regex; + using StackFrame = System.Diagnostics.StackFrame; + using StackTrace = System.Diagnostics.StackTrace; + using TextWriter = System.IO.TextWriter; + using Type = System.Type; + + /** <summary> + * A generic recognizer that can handle recognizers generated from + * lexer, parser, and tree grammars. This is all the parsing + * support code essentially; most of it is error recovery stuff and + * backtracking. + * </summary> + */ + public abstract class BaseRecognizer + { + public const int MemoRuleFailed = -2; + public const int MemoRuleUnknown = -1; + public const int InitialFollowStackSize = 100; + + // copies from Token object for convenience in actions + public const int DefaultTokenChannel = TokenChannels.Default; + public const int Hidden = TokenChannels.Hidden; + + public const string NextTokenRuleName = "nextToken"; + + /** <summary> + * State of a lexer, parser, or tree parser are collected into a state + * object so the state can be shared. This sharing is needed to + * have one grammar import others and share same error variables + * and other state variables. It's a kind of explicit multiple + * inheritance via delegation of methods and shared state. + * </summary> + */ + protected internal RecognizerSharedState state; + + public BaseRecognizer() + : this(new RecognizerSharedState()) + { + } + + public BaseRecognizer( RecognizerSharedState state ) + { + if ( state == null ) + { + state = new RecognizerSharedState(); + } + this.state = state; + InitDFAs(); + } + + public TextWriter TraceDestination + { + get; + set; + } + + protected virtual void InitDFAs() + { + } + + /** <summary>reset the parser's state; subclasses must rewinds the input stream</summary> */ + public virtual void Reset() + { + // wack everything related to error recovery + if ( state == null ) + { + return; // no shared state work to do + } + state._fsp = -1; + state.errorRecovery = false; + state.lastErrorIndex = -1; + state.failed = false; + state.syntaxErrors = 0; + // wack everything related to backtracking and memoization + state.backtracking = 0; + for ( int i = 0; state.ruleMemo != null && i < state.ruleMemo.Length; i++ ) + { // wipe cache + state.ruleMemo[i] = null; + } + } + + + /** <summary> + * Match current input symbol against ttype. Attempt + * single token insertion or deletion error recovery. If + * that fails, throw MismatchedTokenException. + * </summary> + * + * <remarks> + * To turn off single token insertion or deletion error + * recovery, override recoverFromMismatchedToken() and have it + * throw an exception. See TreeParser.recoverFromMismatchedToken(). + * This way any error in a rule will cause an exception and + * immediate exit from rule. Rule would recover by resynchronizing + * to the set of symbols that can follow rule ref. + * </remarks> + */ + public virtual object Match( IIntStream input, int ttype, BitSet follow ) + { + //System.out.println("match "+((TokenStream)input).LT(1)); + object matchedSymbol = GetCurrentInputSymbol( input ); + if ( input.LA( 1 ) == ttype ) + { + input.Consume(); + state.errorRecovery = false; + state.failed = false; + return matchedSymbol; + } + if ( state.backtracking > 0 ) + { + state.failed = true; + return matchedSymbol; + } + matchedSymbol = RecoverFromMismatchedToken( input, ttype, follow ); + return matchedSymbol; + } + + /** <summary>Match the wildcard: in a symbol</summary> */ + public virtual void MatchAny( IIntStream input ) + { + state.errorRecovery = false; + state.failed = false; + input.Consume(); + } + + public virtual bool MismatchIsUnwantedToken( IIntStream input, int ttype ) + { + return input.LA( 2 ) == ttype; + } + + public virtual bool MismatchIsMissingToken( IIntStream input, BitSet follow ) + { + if ( follow == null ) + { + // we have no information about the follow; we can only consume + // a single token and hope for the best + return false; + } + // compute what can follow this grammar element reference + if ( follow.Member( TokenTypes.EndOfRule ) ) + { + BitSet viableTokensFollowingThisRule = ComputeContextSensitiveRuleFOLLOW(); + follow = follow.Or( viableTokensFollowingThisRule ); + if ( state._fsp >= 0 ) + { // remove EOR if we're not the start symbol + follow.Remove( TokenTypes.EndOfRule ); + } + } + // if current token is consistent with what could come after set + // then we know we're missing a token; error recovery is free to + // "insert" the missing token + + //System.out.println("viable tokens="+follow.toString(getTokenNames())); + //System.out.println("LT(1)="+((TokenStream)input).LT(1)); + + // BitSet cannot handle negative numbers like -1 (EOF) so I leave EOR + // in follow set to indicate that the fall of the start symbol is + // in the set (EOF can follow). + if ( follow.Member( input.LA( 1 ) ) || follow.Member( TokenTypes.EndOfRule ) ) + { + //System.out.println("LT(1)=="+((TokenStream)input).LT(1)+" is consistent with what follows; inserting..."); + return true; + } + return false; + } + + /** <summary>Report a recognition problem.</summary> + * + * <remarks> + * This method sets errorRecovery to indicate the parser is recovering + * not parsing. Once in recovery mode, no errors are generated. + * To get out of recovery mode, the parser must successfully match + * a token (after a resync). So it will go: + * + * 1. error occurs + * 2. enter recovery mode, report error + * 3. consume until token found in resynch set + * 4. try to resume parsing + * 5. next match() will reset errorRecovery mode + * + * If you override, make sure to update syntaxErrors if you care about that. + * </remarks> + */ + public virtual void ReportError( RecognitionException e ) + { + // if we've already reported an error and have not matched a token + // yet successfully, don't report any errors. + if ( state.errorRecovery ) + { + //System.err.print("[SPURIOUS] "); + return; + } + state.syntaxErrors++; // don't count spurious + state.errorRecovery = true; + + DisplayRecognitionError( this.TokenNames, e ); + } + + public virtual void DisplayRecognitionError( string[] tokenNames, + RecognitionException e ) + { + string hdr = GetErrorHeader( e ); + string msg = GetErrorMessage( e, tokenNames ); + EmitErrorMessage( hdr + " " + msg ); + } + + /** <summary>What error message should be generated for the various exception types?</summary> + * + * <remarks> + * Not very object-oriented code, but I like having all error message + * generation within one method rather than spread among all of the + * exception classes. This also makes it much easier for the exception + * handling because the exception classes do not have to have pointers back + * to this object to access utility routines and so on. Also, changing + * the message for an exception type would be difficult because you + * would have to subclassing exception, but then somehow get ANTLR + * to make those kinds of exception objects instead of the default. + * This looks weird, but trust me--it makes the most sense in terms + * of flexibility. + * + * For grammar debugging, you will want to override this to add + * more information such as the stack frame with + * getRuleInvocationStack(e, this.getClass().getName()) and, + * for no viable alts, the decision description and state etc... + * + * Override this to change the message generated for one or more + * exception types. + * </remarks> + */ + public virtual string GetErrorMessage( RecognitionException e, string[] tokenNames ) + { + string msg = e.Message; + if ( e is UnwantedTokenException ) + { + UnwantedTokenException ute = (UnwantedTokenException)e; + string tokenName = "<unknown>"; + if ( ute.Expecting == TokenTypes.EndOfFile ) + { + tokenName = "EndOfFile"; + } + else + { + tokenName = tokenNames[ute.Expecting]; + } + msg = "extraneous input " + GetTokenErrorDisplay( ute.UnexpectedToken ) + + " expecting " + tokenName; + } + else if ( e is MissingTokenException ) + { + MissingTokenException mte = (MissingTokenException)e; + string tokenName = "<unknown>"; + if ( mte.Expecting == TokenTypes.EndOfFile ) + { + tokenName = "EndOfFile"; + } + else + { + tokenName = tokenNames[mte.Expecting]; + } + msg = "missing " + tokenName + " at " + GetTokenErrorDisplay( e.Token ); + } + else if ( e is MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + string tokenName = "<unknown>"; + if ( mte.Expecting == TokenTypes.EndOfFile ) + { + tokenName = "EndOfFile"; + } + else + { + tokenName = tokenNames[mte.Expecting]; + } + msg = "mismatched input " + GetTokenErrorDisplay( e.Token ) + + " expecting " + tokenName; + } + else if ( e is MismatchedTreeNodeException ) + { + MismatchedTreeNodeException mtne = (MismatchedTreeNodeException)e; + string tokenName = "<unknown>"; + if ( mtne.Expecting == TokenTypes.EndOfFile ) + { + tokenName = "EndOfFile"; + } + else + { + tokenName = tokenNames[mtne.Expecting]; + } + // workaround for a .NET framework bug (NullReferenceException) + string nodeText = ( mtne.Node != null ) ? mtne.Node.ToString() ?? string.Empty : string.Empty; + msg = "mismatched tree node: " + nodeText + " expecting " + tokenName; + } + else if ( e is NoViableAltException ) + { + //NoViableAltException nvae = (NoViableAltException)e; + // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>" + // and "(decision="+nvae.decisionNumber+") and + // "state "+nvae.stateNumber + msg = "no viable alternative at input " + GetTokenErrorDisplay( e.Token ); + } + else if ( e is EarlyExitException ) + { + //EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at input " + + GetTokenErrorDisplay( e.Token ); + } + else if ( e is MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched input " + GetTokenErrorDisplay( e.Token ) + + " expecting set " + mse.Expecting; + } + else if ( e is MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched input " + GetTokenErrorDisplay( e.Token ) + + " expecting set " + mse.Expecting; + } + else if ( e is FailedPredicateException ) + { + FailedPredicateException fpe = (FailedPredicateException)e; + msg = "rule " + fpe.RuleName + " failed predicate: {" + + fpe.PredicateText + "}?"; + } + return msg; + } + + /** <summary> + * Get number of recognition errors (lexer, parser, tree parser). Each + * recognizer tracks its own number. So parser and lexer each have + * separate count. Does not count the spurious errors found between + * an error and next valid token match + * </summary> + * + * <seealso cref="reportError()"/> + */ + public virtual int NumberOfSyntaxErrors + { + get + { + return state.syntaxErrors; + } + } + + /** <summary>What is the error header, normally line/character position information?</summary> */ + public virtual string GetErrorHeader( RecognitionException e ) + { + string prefix = SourceName ?? string.Empty; + if (prefix.Length > 0) + prefix += ' '; + + return string.Format("{0}line {1}:{2}", prefix, e.Line, e.CharPositionInLine + 1); + } + + /** <summary> + * How should a token be displayed in an error message? The default + * is to display just the text, but during development you might + * want to have a lot of information spit out. Override in that case + * to use t.ToString() (which, for CommonToken, dumps everything about + * the token). This is better than forcing you to override a method in + * your token objects because you don't have to go modify your lexer + * so that it creates a new Java type. + * </summary> + */ + public virtual string GetTokenErrorDisplay( IToken t ) + { + string s = t.Text; + if ( s == null ) + { + if ( t.Type == TokenTypes.EndOfFile ) + { + s = "<EOF>"; + } + else + { + s = "<" + t.Type + ">"; + } + } + s = Regex.Replace( s, "\n", "\\\\n" ); + s = Regex.Replace( s, "\r", "\\\\r" ); + s = Regex.Replace( s, "\t", "\\\\t" ); + return "'" + s + "'"; + } + + /** <summary>Override this method to change where error messages go</summary> */ + public virtual void EmitErrorMessage( string msg ) + { + if (TraceDestination != null) + TraceDestination.WriteLine( msg ); + } + + /** <summary> + * Recover from an error found on the input stream. This is + * for NoViableAlt and mismatched symbol exceptions. If you enable + * single token insertion and deletion, this will usually not + * handle mismatched symbol exceptions but there could be a mismatched + * token that the match() routine could not recover from. + * </summary> + */ + public virtual void Recover( IIntStream input, RecognitionException re ) + { + if ( state.lastErrorIndex == input.Index ) + { + // uh oh, another error at same token index; must be a case + // where LT(1) is in the recovery token set so nothing is + // consumed; consume a single token so at least to prevent + // an infinite loop; this is a failsafe. + input.Consume(); + } + state.lastErrorIndex = input.Index; + BitSet followSet = ComputeErrorRecoverySet(); + BeginResync(); + ConsumeUntil( input, followSet ); + EndResync(); + } + + /** <summary> + * A hook to listen in on the token consumption during error recovery. + * The DebugParser subclasses this to fire events to the listenter. + * </summary> + */ + public virtual void BeginResync() + { + } + + public virtual void EndResync() + { + } + + /* Compute the error recovery set for the current rule. During + * rule invocation, the parser pushes the set of tokens that can + * follow that rule reference on the stack; this amounts to + * computing FIRST of what follows the rule reference in the + * enclosing rule. This local follow set only includes tokens + * from within the rule; i.e., the FIRST computation done by + * ANTLR stops at the end of a rule. + * + * EXAMPLE + * + * When you find a "no viable alt exception", the input is not + * consistent with any of the alternatives for rule r. The best + * thing to do is to consume tokens until you see something that + * can legally follow a call to r *or* any rule that called r. + * You don't want the exact set of viable next tokens because the + * input might just be missing a token--you might consume the + * rest of the input looking for one of the missing tokens. + * + * Consider grammar: + * + * a : '[' b ']' + * | '(' b ')' + * ; + * b : c '^' INT ; + * c : ID + * | INT + * ; + * + * At each rule invocation, the set of tokens that could follow + * that rule is pushed on a stack. Here are the various "local" + * follow sets: + * + * FOLLOW(b1_in_a) = FIRST(']') = ']' + * FOLLOW(b2_in_a) = FIRST(')') = ')' + * FOLLOW(c_in_b) = FIRST('^') = '^' + * + * Upon erroneous input "[]", the call chain is + * + * a -> b -> c + * + * and, hence, the follow context stack is: + * + * depth local follow set after call to rule + * 0 <EOF> a (from main()) + * 1 ']' b + * 3 '^' c + * + * Notice that ')' is not included, because b would have to have + * been called from a different context in rule a for ')' to be + * included. + * + * For error recovery, we cannot consider FOLLOW(c) + * (context-sensitive or otherwise). We need the combined set of + * all context-sensitive FOLLOW sets--the set of all tokens that + * could follow any reference in the call chain. We need to + * resync to one of those tokens. Note that FOLLOW(c)='^' and if + * we resync'd to that token, we'd consume until EOF. We need to + * sync to context-sensitive FOLLOWs for a, b, and c: {']','^'}. + * In this case, for input "[]", LA(1) is in this set so we would + * not consume anything and after printing an error rule c would + * return normally. It would not find the required '^' though. + * At this point, it gets a mismatched token error and throws an + * exception (since LA(1) is not in the viable following token + * set). The rule exception handler tries to recover, but finds + * the same recovery set and doesn't consume anything. Rule b + * exits normally returning to rule a. Now it finds the ']' (and + * with the successful match exits errorRecovery mode). + * + * So, you cna see that the parser walks up call chain looking + * for the token that was a member of the recovery set. + * + * Errors are not generated in errorRecovery mode. + * + * ANTLR's error recovery mechanism is based upon original ideas: + * + * "Algorithms + Data Structures = Programs" by Niklaus Wirth + * + * and + * + * "A note on error recovery in recursive descent parsers": + * http://portal.acm.org/citation.cfm?id=947902.947905 + * + * Later, Josef Grosch had some good ideas: + * + * "Efficient and Comfortable Error Recovery in Recursive Descent + * Parsers": + * ftp://www.cocolab.com/products/cocktail/doca4.ps/ell.ps.zip + * + * Like Grosch I implemented local FOLLOW sets that are combined + * at run-time upon error to avoid overhead during parsing. + */ + protected virtual BitSet ComputeErrorRecoverySet() + { + return CombineFollows( false ); + } + + /** <summary> + * Compute the context-sensitive FOLLOW set for current rule. + * This is set of token types that can follow a specific rule + * reference given a specific call chain. You get the set of + * viable tokens that can possibly come next (lookahead depth 1) + * given the current call chain. Contrast this with the + * definition of plain FOLLOW for rule r: + * </summary> + * + * FOLLOW(r)={x | S=>*alpha r beta in G and x in FIRST(beta)} + * + * where x in T* and alpha, beta in V*; T is set of terminals and + * V is the set of terminals and nonterminals. In other words, + * FOLLOW(r) is the set of all tokens that can possibly follow + * references to r in *any* sentential form (context). At + * runtime, however, we know precisely which context applies as + * we have the call chain. We may compute the exact (rather + * than covering superset) set of following tokens. + * + * For example, consider grammar: + * + * stat : ID '=' expr ';' // FOLLOW(stat)=={EOF} + * | "return" expr '.' + * ; + * expr : atom ('+' atom)* ; // FOLLOW(expr)=={';','.',')'} + * atom : INT // FOLLOW(atom)=={'+',')',';','.'} + * | '(' expr ')' + * ; + * + * The FOLLOW sets are all inclusive whereas context-sensitive + * FOLLOW sets are precisely what could follow a rule reference. + * For input input "i=(3);", here is the derivation: + * + * stat => ID '=' expr ';' + * => ID '=' atom ('+' atom)* ';' + * => ID '=' '(' expr ')' ('+' atom)* ';' + * => ID '=' '(' atom ')' ('+' atom)* ';' + * => ID '=' '(' INT ')' ('+' atom)* ';' + * => ID '=' '(' INT ')' ';' + * + * At the "3" token, you'd have a call chain of + * + * stat -> expr -> atom -> expr -> atom + * + * What can follow that specific nested ref to atom? Exactly ')' + * as you can see by looking at the derivation of this specific + * input. Contrast this with the FOLLOW(atom)={'+',')',';','.'}. + * + * You want the exact viable token set when recovering from a + * token mismatch. Upon token mismatch, if LA(1) is member of + * the viable next token set, then you know there is most likely + * a missing token in the input stream. "Insert" one by just not + * throwing an exception. + */ + protected virtual BitSet ComputeContextSensitiveRuleFOLLOW() + { + return CombineFollows( true ); + } + + // what is exact? it seems to only add sets from above on stack + // if EOR is in set i. When it sees a set w/o EOR, it stops adding. + // Why would we ever want them all? Maybe no viable alt instead of + // mismatched token? + protected virtual BitSet CombineFollows(bool exact) + { + int top = state._fsp; + BitSet followSet = new BitSet(); + for ( int i = top; i >= 0; i-- ) + { + BitSet localFollowSet = (BitSet)state.following[i]; + /* + System.out.println("local follow depth "+i+"="+ + localFollowSet.toString(getTokenNames())+")"); + */ + followSet.OrInPlace( localFollowSet ); + if ( exact ) + { + // can we see end of rule? + if ( localFollowSet.Member( TokenTypes.EndOfRule ) ) + { + // Only leave EOR in set if at top (start rule); this lets + // us know if have to include follow(start rule); i.e., EOF + if ( i > 0 ) + { + followSet.Remove( TokenTypes.EndOfRule ); + } + } + else + { // can't see end of rule, quit + break; + } + } + } + return followSet; + } + + /** <summary>Attempt to recover from a single missing or extra token.</summary> + * + * EXTRA TOKEN + * + * LA(1) is not what we are looking for. If LA(2) has the right token, + * however, then assume LA(1) is some extra spurious token. Delete it + * and LA(2) as if we were doing a normal match(), which advances the + * input. + * + * MISSING TOKEN + * + * If current token is consistent with what could come after + * ttype then it is ok to "insert" the missing token, else throw + * exception For example, Input "i=(3;" is clearly missing the + * ')'. When the parser returns from the nested call to expr, it + * will have call chain: + * + * stat -> expr -> atom + * + * and it will be trying to match the ')' at this point in the + * derivation: + * + * => ID '=' '(' INT ')' ('+' atom)* ';' + * ^ + * match() will see that ';' doesn't match ')' and report a + * mismatched token error. To recover, it sees that LA(1)==';' + * is in the set of tokens that can follow the ')' token + * reference in rule atom. It can assume that you forgot the ')'. + */ + protected virtual object RecoverFromMismatchedToken( IIntStream input, int ttype, BitSet follow ) + { + RecognitionException e = null; + // if next token is what we are looking for then "delete" this token + if ( MismatchIsUnwantedToken( input, ttype ) ) + { + e = new UnwantedTokenException( ttype, input, TokenNames ); + /* + System.err.println("recoverFromMismatchedToken deleting "+ + ((TokenStream)input).LT(1)+ + " since "+((TokenStream)input).LT(2)+" is what we want"); + */ + BeginResync(); + input.Consume(); // simply delete extra token + EndResync(); + ReportError( e ); // report after consuming so AW sees the token in the exception + // we want to return the token we're actually matching + object matchedSymbol = GetCurrentInputSymbol( input ); + input.Consume(); // move past ttype token as if all were ok + return matchedSymbol; + } + // can't recover with single token deletion, try insertion + if ( MismatchIsMissingToken( input, follow ) ) + { + object inserted = GetMissingSymbol( input, e, ttype, follow ); + e = new MissingTokenException( ttype, input, inserted ); + ReportError( e ); // report after inserting so AW sees the token in the exception + return inserted; + } + // even that didn't work; must throw the exception + e = new MismatchedTokenException(ttype, input, TokenNames); + throw e; + } + + /** Not currently used */ + public virtual object RecoverFromMismatchedSet( IIntStream input, + RecognitionException e, + BitSet follow ) + { + if ( MismatchIsMissingToken( input, follow ) ) + { + // System.out.println("missing token"); + ReportError( e ); + // we don't know how to conjure up a token for sets yet + return GetMissingSymbol( input, e, TokenTypes.Invalid, follow ); + } + // TODO do single token deletion like above for Token mismatch + throw e; + } + + /** <summary> + * Match needs to return the current input symbol, which gets put + * into the label for the associated token ref; e.g., x=ID. Token + * and tree parsers need to return different objects. Rather than test + * for input stream type or change the IntStream interface, I use + * a simple method to ask the recognizer to tell me what the current + * input symbol is. + * </summary> + * + * <remarks>This is ignored for lexers.</remarks> + */ + protected virtual object GetCurrentInputSymbol( IIntStream input ) + { + return null; + } + + /** <summary>Conjure up a missing token during error recovery.</summary> + * + * <remarks> + * The recognizer attempts to recover from single missing + * symbols. But, actions might refer to that missing symbol. + * For example, x=ID {f($x);}. The action clearly assumes + * that there has been an identifier matched previously and that + * $x points at that token. If that token is missing, but + * the next token in the stream is what we want we assume that + * this token is missing and we keep going. Because we + * have to return some token to replace the missing token, + * we have to conjure one up. This method gives the user control + * over the tokens returned for missing tokens. Mostly, + * you will want to create something special for identifier + * tokens. For literals such as '{' and ',', the default + * action in the parser or tree parser works. It simply creates + * a CommonToken of the appropriate type. The text will be the token. + * If you change what tokens must be created by the lexer, + * override this method to create the appropriate tokens. + * </remarks> + */ + protected virtual object GetMissingSymbol( IIntStream input, + RecognitionException e, + int expectedTokenType, + BitSet follow ) + { + return null; + } + + public virtual void ConsumeUntil( IIntStream input, int tokenType ) + { + //System.out.println("consumeUntil "+tokenType); + int ttype = input.LA( 1 ); + while ( ttype != TokenTypes.EndOfFile && ttype != tokenType ) + { + input.Consume(); + ttype = input.LA( 1 ); + } + } + + /** <summary>Consume tokens until one matches the given token set</summary> */ + public virtual void ConsumeUntil( IIntStream input, BitSet set ) + { + //System.out.println("consumeUntil("+set.toString(getTokenNames())+")"); + int ttype = input.LA( 1 ); + while ( ttype != TokenTypes.EndOfFile && !set.Member( ttype ) ) + { + //System.out.println("consume during recover LA(1)="+getTokenNames()[input.LA(1)]); + input.Consume(); + ttype = input.LA( 1 ); + } + } + + /** <summary>Push a rule's follow set using our own hardcoded stack</summary> */ + protected void PushFollow( BitSet fset ) + { + if ( ( state._fsp + 1 ) >= state.following.Length ) + { + Array.Resize(ref state.following, state.following.Length * 2); + } + state.following[++state._fsp] = fset; + } + + protected void PopFollow() + { + state._fsp--; + } + + /** <summary> + * Return List<String> of the rules in your parser instance + * leading up to a call to this method. You could override if + * you want more details such as the file/line info of where + * in the parser java code a rule is invoked. + * </summary> + * + * <remarks> + * This is very useful for error messages and for context-sensitive + * error recovery. + * </remarks> + */ + public virtual IList<string> GetRuleInvocationStack() + { + return GetRuleInvocationStack( new StackTrace(true) ); + } + + /** <summary> + * A more general version of GetRuleInvocationStack where you can + * pass in the StackTrace of, for example, a RecognitionException + * to get it's rule stack trace. + * </summary> + */ + public static IList<string> GetRuleInvocationStack(StackTrace trace) + { + if (trace == null) + throw new ArgumentNullException("trace"); + + List<string> rules = new List<string>(); + StackFrame[] stack = trace.GetFrames() ?? new StackFrame[0]; + + for (int i = stack.Length - 1; i >= 0; i--) + { + StackFrame frame = stack[i]; + MethodBase method = frame.GetMethod(); + GrammarRuleAttribute[] attributes = (GrammarRuleAttribute[])method.GetCustomAttributes(typeof(GrammarRuleAttribute), true); + if (attributes != null && attributes.Length > 0) + rules.Add(attributes[0].Name); + } + + return rules; + } + + public virtual int BacktrackingLevel + { + get + { + return state.backtracking; + } + set + { + state.backtracking = value; + } + } + + /** <summary>Return whether or not a backtracking attempt failed.</summary> */ + public virtual bool Failed + { + get + { + return state.failed; + } + } + + /** <summary> + * Used to print out token names like ID during debugging and + * error reporting. The generated parsers implement a method + * that overrides this to point to their String[] tokenNames. + * </summary> + */ + public virtual string[] TokenNames + { + get + { + return null; + } + } + + /** <summary> + * For debugging and other purposes, might want the grammar name. + * Have ANTLR generate an implementation for this method. + * </summary> + */ + public virtual string GrammarFileName + { + get + { + return null; + } + } + + public abstract string SourceName + { + get; + } + + /** <summary> + * A convenience method for use most often with template rewrites. + * Convert a List<Token> to List<String> + * </summary> + */ + public virtual List<string> ToStrings( ICollection<IToken> tokens ) + { + if ( tokens == null ) + return null; + + List<string> strings = new List<string>( tokens.Count ); + foreach ( IToken token in tokens ) + { + strings.Add( token.Text ); + } + + return strings; + } + + /** <summary> + * Given a rule number and a start token index number, return + * MEMO_RULE_UNKNOWN if the rule has not parsed input starting from + * start index. If this rule has parsed input starting from the + * start index before, then return where the rule stopped parsing. + * It returns the index of the last token matched by the rule. + * </summary> + * + * <remarks> + * For now we use a hashtable and just the slow Object-based one. + * Later, we can make a special one for ints and also one that + * tosses out data after we commit past input position i. + * </remarks> + */ + public virtual int GetRuleMemoization( int ruleIndex, int ruleStartIndex ) + { + if ( state.ruleMemo[ruleIndex] == null ) + { + state.ruleMemo[ruleIndex] = new Dictionary<int, int>(); + } + + int stopIndex; + if ( !state.ruleMemo[ruleIndex].TryGetValue( ruleStartIndex, out stopIndex ) ) + return MemoRuleUnknown; + + return stopIndex; + } + + /** <summary> + * Has this rule already parsed input at the current index in the + * input stream? Return the stop token index or MEMO_RULE_UNKNOWN. + * If we attempted but failed to parse properly before, return + * MEMO_RULE_FAILED. + * </summary> + * + * <remarks> + * This method has a side-effect: if we have seen this input for + * this rule and successfully parsed before, then seek ahead to + * 1 past the stop token matched for this rule last time. + * </remarks> + */ + public virtual bool AlreadyParsedRule( IIntStream input, int ruleIndex ) + { + int stopIndex = GetRuleMemoization( ruleIndex, input.Index ); + if ( stopIndex == MemoRuleUnknown ) + { + return false; + } + if ( stopIndex == MemoRuleFailed ) + { + //System.out.println("rule "+ruleIndex+" will never succeed"); + state.failed = true; + } + else + { + //System.out.println("seen rule "+ruleIndex+" before; skipping ahead to @"+(stopIndex+1)+" failed="+state.failed); + input.Seek( stopIndex + 1 ); // jump to one past stop token + } + return true; + } + + /** <summary> + * Record whether or not this rule parsed the input at this position + * successfully. Use a standard java hashtable for now. + * </summary> + */ + public virtual void Memoize( IIntStream input, + int ruleIndex, + int ruleStartIndex ) + { + int stopTokenIndex = state.failed ? MemoRuleFailed : input.Index - 1; + if ( state.ruleMemo == null ) + { + if (TraceDestination != null) + TraceDestination.WriteLine( "!!!!!!!!! memo array is null for " + GrammarFileName ); + } + if ( ruleIndex >= state.ruleMemo.Length ) + { + if (TraceDestination != null) + TraceDestination.WriteLine("!!!!!!!!! memo size is " + state.ruleMemo.Length + ", but rule index is " + ruleIndex); + } + if ( state.ruleMemo[ruleIndex] != null ) + { + state.ruleMemo[ruleIndex][ruleStartIndex] = stopTokenIndex; + } + } + + /** <summary>return how many rule/input-index pairs there are in total.</summary> + * TODO: this includes synpreds. :( + */ + public virtual int GetRuleMemoizationCacheSize() + { + int n = 0; + for ( int i = 0; state.ruleMemo != null && i < state.ruleMemo.Length; i++ ) + { + var ruleMap = state.ruleMemo[i]; + if ( ruleMap != null ) + { + n += ruleMap.Count; // how many input indexes are recorded? + } + } + return n; + } + + public virtual void TraceIn(string ruleName, int ruleIndex, object inputSymbol) + { + if (TraceDestination == null) + return; + + TraceDestination.Write("enter " + ruleName + " " + inputSymbol); + if (state.backtracking > 0) + { + TraceDestination.Write(" backtracking=" + state.backtracking); + } + TraceDestination.WriteLine(); + } + + public virtual void TraceOut(string ruleName, int ruleIndex, object inputSymbol) + { + if (TraceDestination == null) + return; + + TraceDestination.Write("exit " + ruleName + " " + inputSymbol); + if (state.backtracking > 0) + { + TraceDestination.Write(" backtracking=" + state.backtracking); + if (state.failed) + TraceDestination.Write(" failed"); + else + TraceDestination.Write(" succeeded"); + } + TraceDestination.WriteLine(); + } + + #region Debugging support + public virtual IDebugEventListener DebugListener + { + get + { + return null; + } + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugEnterRule(string grammarFileName, string ruleName) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.EnterRule(grammarFileName, ruleName); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugExitRule(string grammarFileName, string ruleName) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.ExitRule(grammarFileName, ruleName); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugEnterSubRule(int decisionNumber) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.EnterSubRule(decisionNumber); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugExitSubRule(int decisionNumber) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.ExitSubRule(decisionNumber); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugEnterAlt(int alt) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.EnterAlt(alt); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugEnterDecision(int decisionNumber, bool couldBacktrack) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.EnterDecision(decisionNumber, couldBacktrack); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugExitDecision(int decisionNumber) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.ExitDecision(decisionNumber); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugLocation(int line, int charPositionInLine) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.Location(line, charPositionInLine); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugSemanticPredicate(bool result, string predicate) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.SemanticPredicate(result, predicate); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugBeginBacktrack(int level) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.BeginBacktrack(level); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugEndBacktrack(int level, bool successful) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.EndBacktrack(level, successful); + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugRecognitionException(RecognitionException ex) + { + IDebugEventListener dbg = DebugListener; + if (dbg != null) + dbg.RecognitionException(ex); + } + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/BitSet.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/BitSet.cs new file mode 100644 index 0000000..b18611b --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/BitSet.cs @@ -0,0 +1,380 @@ +/* + * [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 +{ + using System.Collections.Generic; + + using Array = System.Array; + using CLSCompliant = System.CLSCompliantAttribute; + using ICloneable = System.ICloneable; + using Math = System.Math; + using StringBuilder = System.Text.StringBuilder; + + /** <summary> + * A stripped-down version of org.antlr.misc.BitSet that is just + * good enough to handle runtime requirements such as FOLLOW sets + * for automatic error recovery. + * </summary> + */ + [System.Serializable] + public sealed class BitSet : ICloneable + { + private const int BITS = 64; // number of bits / long + private const int LOG_BITS = 6; // 2^6 == 64 + + /** <summary> + * We will often need to do a mod operator (i mod nbits). Its + * turns out that, for powers of two, this mod operation is + * same as (i & (nbits-1)). Since mod is slow, we use a + * precomputed mod mask to do the mod instead. + * </summary> + */ + private const int MOD_MASK = BITS - 1; + + /** <summary>The actual data bits</summary> */ + ulong[] _bits; + + /** <summary>Construct a bitset of size one word (64 bits)</summary> */ + public BitSet() + : this( BITS ) + { + } + + /** <summary>Construction from a static array of longs</summary> */ + [CLSCompliant( false )] + public BitSet( ulong[] bits ) + { + _bits = bits; + } + + /** <summary>Construction from a list of integers</summary> */ + public BitSet( IEnumerable<int> items ) + : this() + { + foreach ( int i in items ) + Add( i ); + } + + /** <summary>Construct a bitset given the size</summary> + * <param name="nbits">The size of the bitset in bits</param> + */ + public BitSet( int nbits ) + { + _bits = new ulong[( ( nbits - 1 ) >> LOG_BITS ) + 1]; + } + + public static BitSet Of( int el ) + { + BitSet s = new BitSet( el + 1 ); + s.Add( el ); + return s; + } + + public static BitSet Of( int a, int b ) + { + BitSet s = new BitSet( Math.Max( a, b ) + 1 ); + s.Add( a ); + s.Add( b ); + return s; + } + + public static BitSet Of( int a, int b, int c ) + { + BitSet s = new BitSet(); + s.Add( a ); + s.Add( b ); + s.Add( c ); + return s; + } + + public static BitSet Of( int a, int b, int c, int d ) + { + BitSet s = new BitSet(); + s.Add( a ); + s.Add( b ); + s.Add( c ); + s.Add( d ); + return s; + } + + /** <summary>return this | a in a new set</summary> */ + public BitSet Or( BitSet a ) + { + if ( a == null ) + { + return this; + } + BitSet s = (BitSet)this.Clone(); + s.OrInPlace( a ); + return s; + } + + /** <summary>or this element into this set (grow as necessary to accommodate)</summary> */ + public void Add( int el ) + { + int n = WordNumber( el ); + if ( n >= _bits.Length ) + { + GrowToInclude( el ); + } + _bits[n] |= BitMask( el ); + } + + /** <summary>Grows the set to a larger number of bits.</summary> + * <param name="bit">element that must fit in set</param> + */ + public void GrowToInclude( int bit ) + { + int newSize = Math.Max( _bits.Length << 1, NumWordsToHold( bit ) ); + SetSize(newSize); + } + + public void OrInPlace( BitSet a ) + { + if ( a == null ) + { + return; + } + // If this is smaller than a, grow this first + if ( a._bits.Length > _bits.Length ) + { + SetSize( a._bits.Length ); + } + int min = Math.Min( _bits.Length, a._bits.Length ); + for ( int i = min - 1; i >= 0; i-- ) + { + _bits[i] |= a._bits[i]; + } + } + + /** <summary>Sets the size of a set.</summary> + * <param name="nwords">how many words the new set should be</param> + */ + private void SetSize( int nwords ) + { + Array.Resize(ref _bits, nwords); + } + + private static ulong BitMask( int bitNumber ) + { + int bitPosition = bitNumber & MOD_MASK; // bitNumber mod BITS + return 1UL << bitPosition; + } + + public object Clone() + { + return new BitSet( (ulong[])_bits.Clone() ); + } + + public int Size() + { + int deg = 0; + for ( int i = _bits.Length - 1; i >= 0; i-- ) + { + ulong word = _bits[i]; + if ( word != 0L ) + { + for ( int bit = BITS - 1; bit >= 0; bit-- ) + { + if ( ( word & ( 1UL << bit ) ) != 0 ) + { + deg++; + } + } + } + } + return deg; + } + + public override int GetHashCode() + { + throw new System.NotImplementedException(); + } + + public override bool Equals( object other ) + { + if ( other == null || !( other is BitSet ) ) + { + return false; + } + + BitSet otherSet = (BitSet)other; + + int n = Math.Min( this._bits.Length, otherSet._bits.Length ); + + // for any bits in common, compare + for ( int i = 0; i < n; i++ ) + { + if ( this._bits[i] != otherSet._bits[i] ) + { + return false; + } + } + + // make sure any extra bits are off + + if ( this._bits.Length > n ) + { + for ( int i = n + 1; i < this._bits.Length; i++ ) + { + if ( this._bits[i] != 0 ) + { + return false; + } + } + } + else if ( otherSet._bits.Length > n ) + { + for ( int i = n + 1; i < otherSet._bits.Length; i++ ) + { + if ( otherSet._bits[i] != 0 ) + { + return false; + } + } + } + + return true; + } + + public bool Member( int el ) + { + if ( el < 0 ) + { + return false; + } + int n = WordNumber( el ); + if ( n >= _bits.Length ) + return false; + return ( _bits[n] & BitMask( el ) ) != 0; + } + + // remove this element from this set + public void Remove( int el ) + { + int n = WordNumber( el ); + if ( n < _bits.Length ) + { + _bits[n] &= ~BitMask( el ); + } + } + + public bool IsNil() + { + for ( int i = _bits.Length - 1; i >= 0; i-- ) + { + if ( _bits[i] != 0 ) + return false; + } + return true; + } + + private static int NumWordsToHold( int el ) + { + return ( el >> LOG_BITS ) + 1; + } + + public int NumBits() + { + return _bits.Length << LOG_BITS; // num words * bits per word + } + + /** <summary>return how much space is being used by the bits array not how many actually have member bits on.</summary> */ + public int LengthInLongWords() + { + return _bits.Length; + } + + /**Is this contained within a? */ + /* + public boolean subset(BitSet a) { + if (a == null || !(a instanceof BitSet)) return false; + return this.and(a).equals(this); + } + */ + + public int[] ToArray() + { + int[] elems = new int[Size()]; + int en = 0; + for ( int i = 0; i < ( _bits.Length << LOG_BITS ); i++ ) + { + if ( Member( i ) ) + { + elems[en++] = i; + } + } + return elems; + } + + private static int WordNumber( int bit ) + { + return bit >> LOG_BITS; // bit / BITS + } + + public override string ToString() + { + return ToString( null ); + } + + public string ToString( string[] tokenNames ) + { + StringBuilder buf = new StringBuilder(); + string separator = ","; + bool havePrintedAnElement = false; + buf.Append( '{' ); + + for ( int i = 0; i < ( _bits.Length << LOG_BITS ); i++ ) + { + if ( Member( i ) ) + { + if ( i > 0 && havePrintedAnElement ) + { + buf.Append( separator ); + } + if ( tokenNames != null ) + { + buf.Append( tokenNames[i] ); + } + else + { + buf.Append( i ); + } + havePrintedAnElement = true; + } + } + buf.Append( '}' ); + return buf.ToString(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/BufferedTokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/BufferedTokenStream.cs new file mode 100644 index 0000000..517e64a --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/BufferedTokenStream.cs @@ -0,0 +1,425 @@ +/* + * [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 +{ + using System.Collections.Generic; + using CLSCompliant = System.CLSCompliantAttribute; + using IndexOutOfRangeException = System.IndexOutOfRangeException; + using StringBuilder = System.Text.StringBuilder; + + /** Buffer all input tokens but do on-demand fetching of new tokens from + * lexer. Useful when the parser or lexer has to set context/mode info before + * proper lexing of future tokens. The ST template parser needs this, + * for example, because it has to constantly flip back and forth between + * inside/output templates. E.g., <names:{hi, <it>}> has to parse names + * as part of an expression but "hi, <it>" as a nested template. + * + * You can't use this stream if you pass whitespace or other off-channel + * tokens to the parser. The stream can't ignore off-channel tokens. + * (UnbufferedTokenStream is the same way.) + * + * This is not a subclass of UnbufferedTokenStream because I don't want + * to confuse small moving window of tokens it uses for the full buffer. + */ + [System.Serializable] + public class BufferedTokenStream : ITokenStream, ITokenStreamInformation + { + private ITokenSource _tokenSource; + + /** Record every single token pulled from the source so we can reproduce + * chunks of it later. The buffer in LookaheadStream overlaps sometimes + * as its moving window moves through the input. This list captures + * everything so we can access complete input text. + */ + [CLSCompliant(false)] + protected List<IToken> _tokens = new List<IToken>(100); + + /** Track the last mark() call result value for use in rewind(). */ + private int _lastMarker; + + /** The index into the tokens list of the current token (next token + * to consume). tokens[p] should be LT(1). p=-1 indicates need + * to initialize with first token. The ctor doesn't get a token. + * First call to LT(1) or whatever gets the first token and sets p=0; + */ + [CLSCompliant(false)] + protected int _p = -1; + + public BufferedTokenStream() + { + } + + public BufferedTokenStream(ITokenSource tokenSource) + { + this._tokenSource = tokenSource; + } + + public virtual ITokenSource TokenSource + { + get + { + return _tokenSource; + } + set + { + this._tokenSource = value; + _tokens.Clear(); + _p = -1; + } + } + + public virtual int Index + { + get + { + return _p; + } + } + + /// <summary> + /// How deep have we gone? + /// </summary> + public virtual int Range + { + get; + protected set; + } + + public virtual int Count + { + get + { + return _tokens.Count; + } + } + + public virtual string SourceName + { + get + { + return _tokenSource.SourceName; + } + } + + public virtual IToken LastToken + { + get + { + return LB(1); + } + } + + public virtual IToken LastRealToken + { + get + { + int i = 0; + IToken token; + do + { + i++; + token = LB(i); + } while (token != null && token.Line <= 0); + + return token; + } + } + + public virtual int MaxLookBehind + { + get + { + return int.MaxValue; + } + } + + public virtual int Mark() + { + if (_p == -1) + Setup(); + _lastMarker = Index; + return _lastMarker; + } + + public virtual void Release(int marker) + { + // no resources to release + } + + public virtual void Rewind(int marker) + { + Seek(marker); + } + + public virtual void Rewind() + { + Seek(_lastMarker); + } + + public virtual void Reset() + { + _p = 0; + _lastMarker = 0; + } + + public virtual void Seek(int index) + { + _p = index; + } + + /** Move the input pointer to the next incoming token. The stream + * must become active with LT(1) available. consume() simply + * moves the input pointer so that LT(1) points at the next + * input symbol. Consume at least one token. + * + * Walk past any token not on the channel the parser is listening to. + */ + public virtual void Consume() + { + if (_p == -1) + Setup(); + _p++; + Sync(_p); + } + + /** Make sure index i in tokens has a token. */ + protected virtual void Sync(int i) + { + int n = i - _tokens.Count + 1; // how many more elements we need? + if (n > 0) + Fetch(n); + } + + /** add n elements to buffer */ + protected virtual void Fetch(int n) + { + for (int i = 0; i < n; i++) + { + IToken t = TokenSource.NextToken(); + t.TokenIndex = _tokens.Count; + _tokens.Add(t); + if (t.Type == CharStreamConstants.EndOfFile) + break; + } + } + + public virtual IToken Get(int i) + { + if (i < 0 || i >= _tokens.Count) + { + throw new IndexOutOfRangeException("token index " + i + " out of range 0.." + (_tokens.Count - 1)); + } + return _tokens[i]; + } + +#if false // why is this different from GetTokens(start, count) ? + /// <summary> + /// Get all tokens from start..(start+count-1) inclusively + /// </summary> + public virtual List<IToken> Get(int start, int count) + { + if (start < 0) + throw new ArgumentOutOfRangeException("start"); + if (count < 0) + throw new ArgumentOutOfRangeException("count"); + if (start + count >= _tokens.Count) + throw new ArgumentException(); + + if (_p == -1) + Setup(); + + List<IToken> subset = new List<IToken>(count); + for (int i = 0; i < count; i++) + { + IToken token = _tokens[i]; + if (token.Type == TokenTypes.EndOfFile) + break; + + subset.Add(token); + } + + return subset; + } +#endif + + public virtual int LA(int i) + { + return LT(i).Type; + } + + protected virtual IToken LB(int k) + { + if ((_p - k) < 0) + return null; + + return _tokens[_p - k]; + } + + public virtual IToken LT(int k) + { + if (_p == -1) + Setup(); + if (k == 0) + return null; + if (k < 0) + return LB(-k); + + int i = _p + k - 1; + Sync(i); + if (i >= _tokens.Count) + { + // EOF must be last token + return _tokens[_tokens.Count - 1]; + } + + if (i > Range) + Range = i; + + return _tokens[_p + k - 1]; + } + + protected virtual void Setup() + { + Sync(0); + _p = 0; + } + + public virtual List<IToken> GetTokens() + { + return _tokens; + } + + public virtual List<IToken> GetTokens(int start, int stop) + { + return GetTokens(start, stop, default(BitSet)); + } + + /** Given a start and stop index, return a List of all tokens in + * the token type BitSet. Return null if no tokens were found. This + * method looks at both on and off channel tokens. + */ + public virtual List<IToken> GetTokens(int start, int stop, BitSet types) + { + if (_p == -1) + Setup(); + if (stop >= _tokens.Count) + stop = _tokens.Count - 1; + if (start < 0) + start = 0; + if (start > stop) + return null; + + // list = tokens[start:stop]:{Token t, t.getType() in types} + List<IToken> filteredTokens = new List<IToken>(); + for (int i = start; i <= stop; i++) + { + IToken t = _tokens[i]; + if (types == null || types.Member(t.Type)) + { + filteredTokens.Add(t); + } + } + if (filteredTokens.Count == 0) + { + filteredTokens = null; + } + return filteredTokens; + } + + public virtual List<IToken> GetTokens(int start, int stop, IEnumerable<int> types) + { + return GetTokens(start, stop, new BitSet(types)); + } + + public virtual List<IToken> GetTokens(int start, int stop, int ttype) + { + return GetTokens(start, stop, BitSet.Of(ttype)); + } + + public override string ToString() + { + if (_p == -1) + Setup(); + + Fill(); + return ToString(0, _tokens.Count - 1); + } + + public virtual string ToString(int start, int stop) + { + if (start < 0 || stop < 0) + return null; + if (_p == -1) + Setup(); + if (stop >= _tokens.Count) + stop = _tokens.Count - 1; + + StringBuilder buf = new StringBuilder(); + for (int i = start; i <= stop; i++) + { + IToken t = _tokens[i]; + if (t.Type == CharStreamConstants.EndOfFile) + break; + buf.Append(t.Text); + } + + return buf.ToString(); + } + + public virtual string ToString(IToken start, IToken stop) + { + if (start != null && stop != null) + { + return ToString(start.TokenIndex, stop.TokenIndex); + } + return null; + } + + public virtual void Fill() + { + if (_p == -1) + Setup(); + + if (_tokens[_p].Type == CharStreamConstants.EndOfFile) + return; + + int i = _p + 1; + Sync(i); + while (_tokens[i].Type != CharStreamConstants.EndOfFile) + { + i++; + Sync(i); + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/CharStreamConstants.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/CharStreamConstants.cs new file mode 100644 index 0000000..aad127e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/CharStreamConstants.cs @@ -0,0 +1,41 @@ +/* + * [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 +{ + + public static class CharStreamConstants + { + public const int EndOfFile = -1; + } + +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/CharStreamState.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/CharStreamState.cs new file mode 100644 index 0000000..b595710 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/CharStreamState.cs @@ -0,0 +1,56 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + + /** <summary> + * When walking ahead with cyclic DFA or for syntactic predicates, + * we need to record the state of the input stream (char index, + * line, etc...) so that we can rewind the state after scanning ahead. + * </summary> + * + * <remarks>This is the complete state of a stream.</remarks> + */ + [System.Serializable] + public class CharStreamState + { + /** <summary>Index into the char stream of next lookahead char</summary> */ + public int p; + + /** <summary>What line number is the scanner at before processing buffer[p]?</summary> */ + public int line; + + /** <summary>What char position 0..n-1 in line is scanner before processing buffer[p]?</summary> */ + public int charPositionInLine; + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ClassicToken.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ClassicToken.cs new file mode 100644 index 0000000..1b1e59b --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ClassicToken.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 +{ + /** <summary> + * A Token object like we'd use in ANTLR 2.x; has an actual string created + * and associated with this object. These objects are needed for imaginary + * tree nodes that have payload objects. We need to create a Token object + * that has a string; the tree node will point at this token. CommonToken + * has indexes into a char stream and hence cannot be used to introduce + * new strings. + * </summary> + */ + [System.Serializable] + public class ClassicToken : IToken + { + string text; + int type; + int line; + int charPositionInLine; + int channel = TokenChannels.Default; + + /** <summary>What token number is this from 0..n-1 tokens</summary> */ + int index; + + public ClassicToken( int type ) + { + this.type = type; + } + + public ClassicToken( IToken oldToken ) + { + text = oldToken.Text; + type = oldToken.Type; + line = oldToken.Line; + charPositionInLine = oldToken.CharPositionInLine; + channel = oldToken.Channel; + } + + public ClassicToken( int type, string text ) + { + this.type = type; + this.text = text; + } + + public ClassicToken( int type, string text, int channel ) + { + this.type = type; + this.text = text; + this.channel = channel; + } + + #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 charPositionInLine; + } + set + { + charPositionInLine = 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 > 0 ) + { + channelStr = ",channel=" + channel; + } + string txt = Text; + if ( txt != null ) + { + txt = txt.Replace( "\n", "\\\\n" ); + txt = txt.Replace( "\r", "\\\\r" ); + txt = txt.Replace( "\t", "\\\\t" ); + } + else + { + txt = "<no text>"; + } + return "[@" + TokenIndex + ",'" + txt + "',<" + type + ">" + channelStr + "," + line + ":" + CharPositionInLine + "]"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/CommonToken.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/CommonToken.cs new file mode 100644 index 0000000..5797ca8 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/CommonToken.cs @@ -0,0 +1,260 @@ +/* + * [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 +{ + using NonSerialized = System.NonSerializedAttribute; + using Regex = System.Text.RegularExpressions.Regex; + using Serializable = System.SerializableAttribute; + + [Serializable] + public class CommonToken : IToken + { + int type; + int line; + int charPositionInLine = -1; // set to invalid position + int channel = TokenChannels.Default; + [NonSerialized] + ICharStream input; + + /** <summary> + * We need to be able to change the text once in a while. If + * this is non-null, then getText should return this. Note that + * start/stop are not affected by changing this. + * </summary> + */ + string text; + + /** <summary>What token number is this from 0..n-1 tokens; < 0 implies invalid index</summary> */ + int index = -1; + + /** <summary>The char position into the input buffer where this token starts</summary> */ + int start; + + /** <summary>The char position into the input buffer where this token stops</summary> */ + int stop; + + public CommonToken() + { + } + + public CommonToken( int type ) + { + this.type = type; + } + + public CommonToken( ICharStream input, int type, int channel, int start, int stop ) + { + this.input = input; + this.type = type; + this.channel = channel; + this.start = start; + this.stop = stop; + } + + public CommonToken( int type, string text ) + { + this.type = type; + this.channel = TokenChannels.Default; + this.text = text; + } + + public CommonToken( IToken oldToken ) + { + text = oldToken.Text; + type = oldToken.Type; + line = oldToken.Line; + index = oldToken.TokenIndex; + charPositionInLine = oldToken.CharPositionInLine; + channel = oldToken.Channel; + input = oldToken.InputStream; + if ( oldToken is CommonToken ) + { + start = ( (CommonToken)oldToken ).start; + stop = ( (CommonToken)oldToken ).stop; + } + } + + #region IToken Members + public string Text + { + get + { + if ( text != null ) + return text; + if ( input == null ) + return null; + + if (start <= stop && stop < input.Count) + return input.Substring( start, stop - start + 1 ); + + return "<EOF>"; + } + + set + { + /** Override the text for this token. getText() will return this text + * rather than pulling from the buffer. Note that this does not mean + * that start/stop indexes are not valid. It means that that input + * was converted to a new string in the token object. + */ + 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 charPositionInLine; + } + set + { + charPositionInLine = value; + } + } + + public int Channel + { + get + { + return channel; + } + set + { + channel = value; + } + } + + public int StartIndex + { + get + { + return start; + } + set + { + start = value; + } + } + + public int StopIndex + { + get + { + return stop; + } + set + { + stop = value; + } + } + + public int TokenIndex + { + get + { + return index; + } + set + { + index = value; + } + } + + public ICharStream InputStream + { + get + { + return input; + } + set + { + input = value; + } + } + + #endregion + + public override string ToString() + { + string channelStr = ""; + if ( channel > 0 ) + { + channelStr = ",channel=" + channel; + } + string txt = Text; + if ( txt != null ) + { + txt = Regex.Replace( txt, "\n", "\\\\n" ); + txt = Regex.Replace( txt, "\r", "\\\\r" ); + txt = Regex.Replace( txt, "\t", "\\\\t" ); + } + else + { + txt = "<no text>"; + } + return "[@" + TokenIndex + "," + start + ":" + stop + "='" + txt + "',<" + type + ">" + channelStr + "," + line + ":" + CharPositionInLine + "]"; + } + + [System.Runtime.Serialization.OnSerializing] + internal void OnSerializing( System.Runtime.Serialization.StreamingContext context ) + { + if ( text == null ) + text = Text; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/CommonTokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/CommonTokenStream.cs new file mode 100644 index 0000000..a1e4a29 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/CommonTokenStream.cs @@ -0,0 +1,175 @@ +/* + * [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 +{ + using System.Collections.Generic; + + using InvalidOperationException = System.InvalidOperationException; + using StringBuilder = System.Text.StringBuilder; + + /** <summary> + * The most common stream of tokens is one where every token is buffered up + * and tokens are prefiltered for a certain channel (the parser will only + * see these tokens and cannot change the filter channel number during the + * parse). + * </summary> + * + * <remarks>TODO: how to access the full token stream? How to track all tokens matched per rule?</remarks> + */ + [System.Serializable] + public class CommonTokenStream : BufferedTokenStream + { + /** Skip tokens on any channel but this one; this is how we skip whitespace... */ + private int _channel; + + public CommonTokenStream() + { + } + + public CommonTokenStream(ITokenSource tokenSource) + : this(tokenSource, TokenChannels.Default) + { + } + + public CommonTokenStream(ITokenSource tokenSource, int channel) + : base(tokenSource) + { + this._channel = channel; + } + + public int Channel + { + get + { + return _channel; + } + } + + /** Reset this token stream by setting its token source. */ + public override ITokenSource TokenSource + { + get + { + return base.TokenSource; + } + set + { + base.TokenSource = value; + _channel = TokenChannels.Default; + } + } + + /** Always leave p on an on-channel token. */ + public override void Consume() + { + if (_p == -1) + Setup(); + _p++; + _p = SkipOffTokenChannels(_p); + } + + protected override IToken LB(int k) + { + if (k == 0 || (_p - k) < 0) + return null; + + int i = _p; + int n = 1; + // find k good tokens looking backwards + while (n <= k) + { + // skip off-channel tokens + i = SkipOffTokenChannelsReverse(i - 1); + n++; + } + if (i < 0) + return null; + return _tokens[i]; + } + + public override IToken LT(int k) + { + if (_p == -1) + Setup(); + if (k == 0) + return null; + if (k < 0) + return LB(-k); + int i = _p; + int n = 1; // we know tokens[p] is a good one + // find k good tokens + while (n < k) + { + // skip off-channel tokens + i = SkipOffTokenChannels(i + 1); + n++; + } + + if (i > Range) + Range = i; + + return _tokens[i]; + } + + /** Given a starting index, return the index of the first on-channel + * token. + */ + protected virtual int SkipOffTokenChannels(int i) + { + Sync(i); + while (_tokens[i].Channel != _channel) + { + // also stops at EOF (it's on channel) + i++; + Sync(i); + } + return i; + } + + protected virtual int SkipOffTokenChannelsReverse(int i) + { + while (i >= 0 && ((IToken)_tokens[i]).Channel != _channel) + { + i--; + } + + return i; + } + + protected override void Setup() + { + _p = 0; + _p = SkipOffTokenChannels(_p); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/DFA.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/DFA.cs new file mode 100644 index 0000000..37e2d06 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/DFA.cs @@ -0,0 +1,305 @@ +/* + * [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 +{ + using ConditionalAttribute = System.Diagnostics.ConditionalAttribute; + using Console = System.Console; + using IDebugEventListener = Antlr.Runtime.Debug.IDebugEventListener; + + public delegate int SpecialStateTransitionHandler( DFA dfa, int s, IIntStream input ); + + /** <summary>A DFA implemented as a set of transition tables.</summary> + * + * <remarks> + * Any state that has a semantic predicate edge is special; those states + * are generated with if-then-else structures in a specialStateTransition() + * which is generated by cyclicDFA template. + * + * There are at most 32767 states (16-bit signed short). + * Could get away with byte sometimes but would have to generate different + * types and the simulation code too. For a point of reference, the Java + * lexer's Tokens rule DFA has 326 states roughly. + * </remarks> + */ + public class DFA + { + protected short[] eot; + protected short[] eof; + protected char[] min; + protected char[] max; + protected short[] accept; + protected short[] special; + protected short[][] transition; + + protected int decisionNumber; + + /** <summary>Which recognizer encloses this DFA? Needed to check backtracking</summary> */ + protected BaseRecognizer recognizer; + + public readonly bool debug = false; + + public DFA() + : this( new SpecialStateTransitionHandler( SpecialStateTransitionDefault ) ) + { + } + + public DFA( SpecialStateTransitionHandler specialStateTransition ) + { + this.SpecialStateTransition = specialStateTransition ?? new SpecialStateTransitionHandler( SpecialStateTransitionDefault ); + } + + public virtual string Description + { + get + { + return "n/a"; + } + } + + /** <summary> + * From the input stream, predict what alternative will succeed + * using this DFA (representing the covering regular approximation + * to the underlying CFL). Return an alternative number 1..n. Throw + * an exception upon error. + * </summary> + */ + public virtual int Predict( IIntStream input ) + { + if ( debug ) + { + Console.Error.WriteLine( "Enter DFA.predict for decision " + decisionNumber ); + } + int mark = input.Mark(); // remember where decision started in input + int s = 0; // we always start at s0 + try + { + for ( ; ; ) + { + if ( debug ) + Console.Error.WriteLine( "DFA " + decisionNumber + " state " + s + " LA(1)=" + (char)input.LA( 1 ) + "(" + input.LA( 1 ) + + "), index=" + input.Index ); + int specialState = special[s]; + if ( specialState >= 0 ) + { + if ( debug ) + { + Console.Error.WriteLine( "DFA " + decisionNumber + + " state " + s + " is special state " + specialState ); + } + s = SpecialStateTransition( this, specialState, input ); + if ( debug ) + { + Console.Error.WriteLine( "DFA " + decisionNumber + + " returns from special state " + specialState + " to " + s ); + } + if ( s == -1 ) + { + NoViableAlt( s, input ); + return 0; + } + input.Consume(); + continue; + } + if ( accept[s] >= 1 ) + { + if ( debug ) + Console.Error.WriteLine( "accept; predict " + accept[s] + " from state " + s ); + return accept[s]; + } + // look for a normal char transition + char c = (char)input.LA( 1 ); // -1 == \uFFFF, all tokens fit in 65000 space + if ( c >= min[s] && c <= max[s] ) + { + int snext = transition[s][c - min[s]]; // move to next state + if ( snext < 0 ) + { + // was in range but not a normal transition + // must check EOT, which is like the else clause. + // eot[s]>=0 indicates that an EOT edge goes to another + // state. + if ( eot[s] >= 0 ) + { // EOT Transition to accept state? + if ( debug ) + Console.Error.WriteLine( "EOT transition" ); + s = eot[s]; + input.Consume(); + // TODO: I had this as return accept[eot[s]] + // which assumed here that the EOT edge always + // went to an accept...faster to do this, but + // what about predicated edges coming from EOT + // target? + continue; + } + NoViableAlt( s, input ); + return 0; + } + s = snext; + input.Consume(); + continue; + } + if ( eot[s] >= 0 ) + { // EOT Transition? + if ( debug ) + Console.Error.WriteLine( "EOT transition" ); + s = eot[s]; + input.Consume(); + continue; + } + if ( c == unchecked( (char)TokenTypes.EndOfFile ) && eof[s] >= 0 ) + { // EOF Transition to accept state? + if ( debug ) + Console.Error.WriteLine( "accept via EOF; predict " + accept[eof[s]] + " from " + eof[s] ); + return accept[eof[s]]; + } + // not in range and not EOF/EOT, must be invalid symbol + if ( debug ) + { + Console.Error.WriteLine( "min[" + s + "]=" + min[s] ); + Console.Error.WriteLine( "max[" + s + "]=" + max[s] ); + Console.Error.WriteLine( "eot[" + s + "]=" + eot[s] ); + Console.Error.WriteLine( "eof[" + s + "]=" + eof[s] ); + for ( int p = 0; p < transition[s].Length; p++ ) + { + Console.Error.Write( transition[s][p] + " " ); + } + Console.Error.WriteLine(); + } + NoViableAlt( s, input ); + return 0; + } + } + finally + { + input.Rewind( mark ); + } + } + + protected virtual void NoViableAlt( int s, IIntStream input ) + { + if ( recognizer.state.backtracking > 0 ) + { + recognizer.state.failed = true; + return; + } + NoViableAltException nvae = + new NoViableAltException( Description, + decisionNumber, + s, + input ); + Error( nvae ); + throw nvae; + } + + /** <summary>A hook for debugging interface</summary> */ + public virtual void Error( NoViableAltException nvae ) + { + } + + public SpecialStateTransitionHandler SpecialStateTransition + { + get; + private set; + } + //public virtual int specialStateTransition( int s, IntStream input ) + //{ + // return -1; + //} + + static int SpecialStateTransitionDefault( DFA dfa, int s, IIntStream input ) + { + return -1; + } + + /** <summary> + * Given a String that has a run-length-encoding of some unsigned shorts + * like "\1\2\3\9", convert to short[] {2,9,9,9}. We do this to avoid + * static short[] which generates so much init code that the class won't + * compile. :( + * </summary> + */ + public static short[] UnpackEncodedString( string encodedString ) + { + // walk first to find how big it is. + int size = 0; + for ( int i = 0; i < encodedString.Length; i += 2 ) + { + size += encodedString[i]; + } + short[] data = new short[size]; + int di = 0; + for ( int i = 0; i < encodedString.Length; i += 2 ) + { + char n = encodedString[i]; + char v = encodedString[i + 1]; + // add v n times to data + for ( int j = 1; j <= n; j++ ) + { + data[di++] = (short)v; + } + } + return data; + } + + /** <summary>Hideous duplication of code, but I need different typed arrays out :(</summary> */ + public static char[] UnpackEncodedStringToUnsignedChars( string encodedString ) + { + // walk first to find how big it is. + int size = 0; + for ( int i = 0; i < encodedString.Length; i += 2 ) + { + size += encodedString[i]; + } + char[] data = new char[size]; + int di = 0; + for ( int i = 0; i < encodedString.Length; i += 2 ) + { + char n = encodedString[i]; + char v = encodedString[i + 1]; + // add v n times to data + for ( int j = 1; j <= n; j++ ) + { + data[di++] = v; + } + } + return data; + } + + [Conditional("ANTLR_DEBUG")] + protected virtual void DebugRecognitionException(RecognitionException ex) + { + IDebugEventListener dbg = recognizer.DebugListener; + if (dbg != null) + dbg.RecognitionException(ex); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs new file mode 100644 index 0000000..0f5d2c5 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Debug/IDebugEventListener.cs @@ -0,0 +1,387 @@ +/* + * [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>All debugging events that a recognizer can trigger.</summary> + * + * <remarks> + * I did not create a separate AST debugging interface as it would create + * lots of extra classes and DebugParser has a dbg var defined, which makes + * it hard to change to ASTDebugEventListener. I looked hard at this issue + * and it is easier to understand as one monolithic event interface for all + * possible events. Hopefully, adding ST debugging stuff won't be bad. Leave + * for future. 4/26/2006. + * </remarks> + */ + public interface IDebugEventListener + { + void Initialize(); + + /** <summary> + * The parser has just entered a rule. No decision has been made about + * which alt is predicted. This is fired AFTER init actions have been + * executed. Attributes are defined and available etc... + * The grammarFileName allows composite grammars to jump around among + * multiple grammar files. + * </summary> + */ + void EnterRule( string grammarFileName, string ruleName ); + + /** <summary> + * Because rules can have lots of alternatives, it is very useful to + * know which alt you are entering. This is 1..n for n alts. + * </summary> + */ + void EnterAlt( int alt ); + + /** <summary> + * This is the last thing executed before leaving a rule. It is + * executed even if an exception is thrown. This is triggered after + * error reporting and recovery have occurred (unless the exception is + * not caught in this rule). This implies an "exitAlt" event. + * The grammarFileName allows composite grammars to jump around among + * multiple grammar files. + * </summary> + */ + void ExitRule( string grammarFileName, string ruleName ); + + /** <summary>Track entry into any (...) subrule other EBNF construct</summary> */ + void EnterSubRule( int decisionNumber ); + + void ExitSubRule( int decisionNumber ); + + /** <summary> + * Every decision, fixed k or arbitrary, has an enter/exit event + * so that a GUI can easily track what LT/consume events are + * associated with prediction. You will see a single enter/exit + * subrule but multiple enter/exit decision events, one for each + * loop iteration. + * </summary> + */ + void EnterDecision(int decisionNumber, bool couldBacktrack); + + void ExitDecision( int decisionNumber ); + + /** <summary> + * An input token was consumed; matched by any kind of element. + * Trigger after the token was matched by things like match(), matchAny(). + * </summary> + */ + void ConsumeToken( IToken t ); + + /** <summary> + * An off-channel input token was consumed. + * Trigger after the token was matched by things like match(), matchAny(). + * (unless of course the hidden token is first stuff in the input stream). + * </summary> + */ + void ConsumeHiddenToken( IToken t ); + + /** <summary> + * Somebody (anybody) looked ahead. Note that this actually gets + * triggered by both LA and LT calls. The debugger will want to know + * which Token object was examined. Like consumeToken, this indicates + * what token was seen at that depth. A remote debugger cannot look + * ahead into a file it doesn't have so LT events must pass the token + * even if the info is redundant. + * </summary> + */ + void LT( int i, IToken t ); + + /** <summary> + * The parser is going to look arbitrarily ahead; mark this location, + * the token stream's marker is sent in case you need it. + * </summary> + */ + void Mark( int marker ); + + /** <summary> + * After an arbitrairly long lookahead as with a cyclic DFA (or with + * any backtrack), this informs the debugger that stream should be + * rewound to the position associated with marker. + * </summary> + */ + void Rewind( int marker ); + + /** <summary> + * Rewind to the input position of the last marker. + * Used currently only after a cyclic DFA and just + * before starting a sem/syn predicate to get the + * input position back to the start of the decision. + * Do not "pop" the marker off the state. mark(i) + * and rewind(i) should balance still. + * </summary> + */ + void Rewind(); + + void BeginBacktrack( int level ); + + void EndBacktrack( int level, bool successful ); + + /** <summary> + * To watch a parser move through the grammar, the parser needs to + * inform the debugger what line/charPos it is passing in the grammar. + * For now, this does not know how to switch from one grammar to the + * other and back for island grammars etc... + * </summary> + * + * <remarks> + * This should also allow breakpoints because the debugger can stop + * the parser whenever it hits this line/pos. + * </remarks> + */ + void Location( int line, int pos ); + + /** <summary> + * A recognition exception occurred such as NoViableAltException. I made + * this a generic event so that I can alter the exception hierachy later + * without having to alter all the debug objects. + * </summary> + * + * <remarks> + * Upon error, the stack of enter rule/subrule must be properly unwound. + * If no viable alt occurs it is within an enter/exit decision, which + * also must be rewound. Even the rewind for each mark must be unwount. + * In the Java target this is pretty easy using try/finally, if a bit + * ugly in the generated code. The rewind is generated in DFA.predict() + * actually so no code needs to be generated for that. For languages + * w/o this "finally" feature (C++?), the target implementor will have + * to build an event stack or something. + * + * Across a socket for remote debugging, only the RecognitionException + * data fields are transmitted. The token object or whatever that + * caused the problem was the last object referenced by LT. The + * immediately preceding LT event should hold the unexpected Token or + * char. + * + * Here is a sample event trace for grammar: + * + * b : C ({;}A|B) // {;} is there to prevent A|B becoming a set + * | D + * ; + * + * The sequence for this rule (with no viable alt in the subrule) for + * input 'c c' (there are 3 tokens) is: + * + * commence + * LT(1) + * enterRule b + * location 7 1 + * enter decision 3 + * LT(1) + * exit decision 3 + * enterAlt1 + * location 7 5 + * LT(1) + * consumeToken [c/<4>,1:0] + * location 7 7 + * enterSubRule 2 + * enter decision 2 + * LT(1) + * LT(1) + * recognitionException NoViableAltException 2 1 2 + * exit decision 2 + * exitSubRule 2 + * beginResync + * LT(1) + * consumeToken [c/<4>,1:1] + * LT(1) + * endResync + * LT(-1) + * exitRule b + * terminate + * </remarks> + */ + void RecognitionException( RecognitionException e ); + + /** <summary> + * Indicates the recognizer is about to consume tokens to resynchronize + * the parser. Any consume events from here until the recovered event + * are not part of the parse--they are dead tokens. + * </summary> + */ + void BeginResync(); + + /** <summary> + * Indicates that the recognizer has finished consuming tokens in order + * to resychronize. There may be multiple beginResync/endResync pairs + * before the recognizer comes out of errorRecovery mode (in which + * multiple errors are suppressed). This will be useful + * in a gui where you want to probably grey out tokens that are consumed + * but not matched to anything in grammar. Anything between + * a beginResync/endResync pair was tossed out by the parser. + * </summary> + */ + void EndResync(); + + /** <summary>A semantic predicate was evaluate with this result and action text</summary> */ + void SemanticPredicate( bool result, string predicate ); + + /** <summary> + * Announce that parsing has begun. Not technically useful except for + * sending events over a socket. A GUI for example will launch a thread + * to connect and communicate with a remote parser. The thread will want + * to notify the GUI when a connection is made. ANTLR parsers + * trigger this upon entry to the first rule (the ruleLevel is used to + * figure this out). + * </summary> + */ + void Commence(); + + /** <summary> + * Parsing is over; successfully or not. Mostly useful for telling + * remote debugging listeners that it's time to quit. When the rule + * invocation level goes to zero at the end of a rule, we are done + * parsing. + * </summary> + */ + void Terminate(); + + + #region Tree Parsing + + /** <summary> + * Input for a tree parser is an AST, but we know nothing for sure + * about a node except its type and text (obtained from the adaptor). + * This is the analog of the consumeToken method. Again, the ID is + * the hashCode usually of the node so it only works if hashCode is + * not implemented. If the type is UP or DOWN, then + * the ID is not really meaningful as it's fixed--there is + * just one UP node and one DOWN navigation node. + * </summary> + * + * <param name="t" /> + */ + void ConsumeNode( object t ); + + /** <summary> + * The tree parser lookedahead. If the type is UP or DOWN, + * then the ID is not really meaningful as it's fixed--there is + * just one UP node and one DOWN navigation node. + * </summary> + */ + void LT( int i, object t ); + + #endregion + + + #region AST Events + + /** <summary> + * A nil was created (even nil nodes have a unique ID... + * they are not "null" per se). As of 4/28/2006, this + * seems to be uniquely triggered when starting a new subtree + * such as when entering a subrule in automatic mode and when + * building a tree in rewrite mode. + * </summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only t.ID is set. + * </remarks> + */ + void NilNode( object t ); + + /** <summary> + * Upon syntax error, recognizers bracket the error with an error node + * if they are building ASTs. + * </summary> + * + * <param name="t"/> + */ + void ErrorNode( object t ); + + /** <summary>Announce a new node built from token elements such as type etc...</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only t.ID, type, text are + * set. + * </remarks> + */ + void CreateNode( object t ); + + /** <summary>Announce a new node built from an existing token.</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only node.ID and token.tokenIndex + * are set. + * </remarks> + */ + void CreateNode( object node, IToken token ); + + /** <summary>Make a node the new root of an existing root. See</summary> + * + * <remarks> + * Note: the newRootID parameter is possibly different + * than the TreeAdaptor.becomeRoot() newRoot parameter. + * In our case, it will always be the result of calling + * TreeAdaptor.becomeRoot() and not root_n or whatever. + * + * The listener should assume that this event occurs + * only when the current subrule (or rule) subtree is + * being reset to newRootID. + * + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only IDs are set. + * </remarks> + * + * <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.becomeRoot()"/> + */ + void BecomeRoot( object newRoot, object oldRoot ); + + /** <summary>Make childID a child of rootID.</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only IDs are set. + * </remarks> + * + * <seealso cref="Antlr.Runtime.Tree.TreeAdaptor.addChild()"/> + */ + void AddChild( object root, object child ); + + /** <summary>Set the token start/stop token index for a subtree root or node.</summary> + * + * <remarks> + * If you are receiving this event over a socket via + * RemoteDebugEventSocketListener then only t.ID is set. + * </remarks> + */ + void SetTokenBoundaries( object t, int tokenStartIndex, int tokenStopIndex ); + + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/EarlyExitException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/EarlyExitException.cs new file mode 100644 index 0000000..f2f6e81 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/EarlyExitException.cs @@ -0,0 +1,104 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary>The recognizer did not match anything for a (..)+ loop.</summary> */ + [System.Serializable] + public class EarlyExitException : RecognitionException + { + private readonly int _decisionNumber; + + public EarlyExitException() + { + } + + public EarlyExitException(string message) + : base(message) + { + } + + public EarlyExitException(string message, Exception innerException) + : base(message, innerException) + { + } + + public EarlyExitException(int decisionNumber, IIntStream input) + : base(input) + { + this._decisionNumber = decisionNumber; + } + + public EarlyExitException(string message, int decisionNumber, IIntStream input) + : base(message, input) + { + this._decisionNumber = decisionNumber; + } + + public EarlyExitException(string message, int decisionNumber, IIntStream input, Exception innerException) + : base(message, input, innerException) + { + this._decisionNumber = decisionNumber; + } + + protected EarlyExitException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + this._decisionNumber = info.GetInt32("DecisionNumber"); + } + + public int DecisionNumber + { + get + { + return _decisionNumber; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("DecisionNumber", DecisionNumber); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/FailedPredicateException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/FailedPredicateException.cs new file mode 100644 index 0000000..add3f58 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/FailedPredicateException.cs @@ -0,0 +1,129 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary> + * A semantic predicate failed during validation. Validation of predicates + * occurs when normally parsing the alternative just like matching a token. + * Disambiguating predicate evaluation occurs when we hoist a predicate into + * a prediction decision. + * </summary> + */ + [System.Serializable] + public class FailedPredicateException : RecognitionException + { + private readonly string _ruleName; + private readonly string _predicateText; + + public FailedPredicateException() + { + } + + public FailedPredicateException(string message) + : base(message) + { + } + + public FailedPredicateException(string message, Exception innerException) + : base(message, innerException) + { + } + + public FailedPredicateException(IIntStream input, string ruleName, string predicateText) + : base(input) + { + this._ruleName = ruleName; + this._predicateText = predicateText; + } + + public FailedPredicateException(string message, IIntStream input, string ruleName, string predicateText) + : base(message, input) + { + this._ruleName = ruleName; + this._predicateText = predicateText; + } + + public FailedPredicateException(string message, IIntStream input, string ruleName, string predicateText, Exception innerException) + : base(message, input, innerException) + { + this._ruleName = ruleName; + this._predicateText = predicateText; + } + + protected FailedPredicateException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + this._ruleName = info.GetString("RuleName"); + this._predicateText = info.GetString("PredicateText"); + } + + public string RuleName + { + get + { + return _ruleName; + } + } + + public string PredicateText + { + get + { + return _predicateText; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("RuleName", _ruleName); + info.AddValue("PredicateText", _predicateText); + } + + public override string ToString() + { + return "FailedPredicateException(" + RuleName + ",{" + PredicateText + "}?)"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/GrammarRuleAttribute.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/GrammarRuleAttribute.cs new file mode 100644 index 0000000..20708b9 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/GrammarRuleAttribute.cs @@ -0,0 +1,57 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2010 Sam Harwell + * 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 +{ + using Attribute = System.Attribute; + using AttributeTargets = System.AttributeTargets; + using AttributeUsageAttribute = System.AttributeUsageAttribute; + + [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)] + public sealed class GrammarRuleAttribute : Attribute + { + private readonly string _name; + + public GrammarRuleAttribute(string name) + { + this._name = name; + } + + public string Name + { + get + { + return _name; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/IAstRuleReturnScope.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/IAstRuleReturnScope.cs new file mode 100644 index 0000000..3dd8823 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/IAstRuleReturnScope.cs @@ -0,0 +1,44 @@ +/* + * [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 +{ + /** <summary>AST rules have trees</summary> */ + public interface IAstRuleReturnScope : IRuleReturnScope + { + /** <summary>Has a value potentially if output=AST;</summary> */ + object Tree + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/IAstRuleReturnScope`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/IAstRuleReturnScope`1.cs new file mode 100644 index 0000000..7e98af8 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/IAstRuleReturnScope`1.cs @@ -0,0 +1,44 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2010 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 +{ + /** <summary>AST rules have trees</summary> */ + public interface IAstRuleReturnScope<TAstLabel> : IAstRuleReturnScope + { + /** <summary>Has a value potentially if output=AST;</summary> */ + new TAstLabel Tree + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ICharStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ICharStream.cs new file mode 100644 index 0000000..12a4f8a --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ICharStream.cs @@ -0,0 +1,72 @@ +/* + * [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 +{ + + /** <summary>A source of characters for an ANTLR lexer</summary> */ + public interface ICharStream : IIntStream + { + + /** <summary> + * For infinite streams, you don't need this; primarily I'm providing + * a useful interface for action code. Just make sure actions don't + * use this on streams that don't support it. + * </summary> + */ + string Substring( int start, int length ); + + /** <summary> + * Get the ith character of lookahead. This is the same usually as + * LA(i). This will be used for labels in the generated + * lexer code. I'd prefer to return a char here type-wise, but it's + * probably better to be 32-bit clean and be consistent with LA. + * </summary> + */ + int LT( int i ); + + /** <summary>ANTLR tracks the line information automatically</summary> */ + /** <summary>Because this stream can rewind, we need to be able to reset the line</summary> */ + int Line + { + get; + set; + } + + /** <summary>The index of the character relative to the beginning of the line 0..n-1</summary> */ + int CharPositionInLine + { + get; + set; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/IIntStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/IIntStream.cs new file mode 100644 index 0000000..012f81e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/IIntStream.cs @@ -0,0 +1,161 @@ +/* + * [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 +{ + + /** <summary> + * A simple stream of integers used when all I care about is the char + * or token type sequence (such as interpretation). + * </summary> + */ + public interface IIntStream + { + void Consume(); + + /** <summary> + * Get int at current input pointer + i ahead where i=1 is next int. + * Negative indexes are allowed. LA(-1) is previous token (token + * just matched). LA(-i) where i is before first token should + * yield -1, invalid char / EOF. + * </summary> + */ + int LA( int i ); + + /** <summary> + * Tell the stream to start buffering if it hasn't already. Return + * current input position, Index, or some other marker so that + * when passed to rewind() you get back to the same spot. + * rewind(mark()) should not affect the input cursor. The Lexer + * track line/col info as well as input index so its markers are + * not pure input indexes. Same for tree node streams. + * </summary> + */ + int Mark(); + + /** <summary> + * Return the current input symbol index 0..n where n indicates the + * last symbol has been read. The index is the symbol about to be + * read not the most recently read symbol. + * </summary> + */ + int Index + { + get; + } + + /** <summary> + * Reset the stream so that next call to index would return marker. + * The marker will usually be Index but it doesn't have to be. It's + * just a marker to indicate what state the stream was in. This is + * essentially calling release() and seek(). If there are markers + * created after this marker argument, this routine must unroll them + * like a stack. Assume the state the stream was in when this marker + * was created. + * </summary> + */ + void Rewind( int marker ); + + /** <summary> + * Rewind to the input position of the last marker. + * Used currently only after a cyclic DFA and just + * before starting a sem/syn predicate to get the + * input position back to the start of the decision. + * Do not "pop" the marker off the state. mark(i) + * and rewind(i) should balance still. It is + * like invoking rewind(last marker) but it should not "pop" + * the marker off. It's like seek(last marker's input position). + * </summary> + */ + void Rewind(); + + /** <summary> + * You may want to commit to a backtrack but don't want to force the + * stream to keep bookkeeping objects around for a marker that is + * no longer necessary. This will have the same behavior as + * rewind() except it releases resources without the backward seek. + * This must throw away resources for all markers back to the marker + * argument. So if you're nested 5 levels of mark(), and then release(2) + * you have to release resources for depths 2..5. + * </summary> + */ + void Release( int marker ); + + /** <summary> + * Set the input cursor to the position indicated by index. This is + * normally used to seek ahead in the input stream. No buffering is + * required to do this unless you know your stream will use seek to + * move backwards such as when backtracking. + * </summary> + * + * <remarks> + * This is different from rewind in its multi-directional + * requirement and in that its argument is strictly an input cursor (index). + * + * For char streams, seeking forward must update the stream state such + * as line number. For seeking backwards, you will be presumably + * backtracking using the mark/rewind mechanism that restores state and + * so this method does not need to update state when seeking backwards. + * + * Currently, this method is only used for efficient backtracking using + * memoization, but in the future it may be used for incremental parsing. + * + * The index is 0..n-1. A seek to position i means that LA(1) will + * return the ith symbol. So, seeking to 0 means LA(1) will return the + * first element in the stream. + * </remarks> + */ + void Seek( int index ); + + /** <summary> + * Only makes sense for streams that buffer everything up probably, but + * might be useful to display the entire stream or for testing. This + * value includes a single EOF. + * </summary> + */ + int Count + { + get; + } + + /** <summary> + * Where are you getting symbols from? Normally, implementations will + * pass the buck all the way to the lexer who can ask its input stream + * for the file name or whatever. + * </summary> + */ + string SourceName + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/IRuleReturnScope.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/IRuleReturnScope.cs new file mode 100644 index 0000000..bd286a2 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/IRuleReturnScope.cs @@ -0,0 +1,56 @@ +/* + * [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 +{ + /// <summary> + /// Rules can have start/stop info. + /// </summary> + public interface IRuleReturnScope + { + /// <summary> + /// Gets the start element from the input stream + /// </summary> + object Start + { + get; + } + + /// <summary> + /// Gets the stop element from the input stream + /// </summary> + object Stop + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/IRuleReturnScope`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/IRuleReturnScope`1.cs new file mode 100644 index 0000000..bc64f64 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/IRuleReturnScope`1.cs @@ -0,0 +1,57 @@ +/* + * [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 +{ + /// <summary> + /// Rules can have start/stop info. + /// </summary> + /// <typeparam name="TLabel">The element type of the input stream.</typeparam> + public interface IRuleReturnScope<TLabel> : IRuleReturnScope + { + /// <summary> + /// Gets the start element from the input stream + /// </summary> + new TLabel Start + { + get; + } + + /// <summary> + /// Gets the stop element from the input stream + /// </summary> + new TLabel Stop + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ITemplateRuleReturnScope.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ITemplateRuleReturnScope.cs new file mode 100644 index 0000000..8a3de74 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ITemplateRuleReturnScope.cs @@ -0,0 +1,42 @@ +/* + * [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 +{ + public interface ITemplateRuleReturnScope + { + object Template + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ITemplateRuleReturnScope`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ITemplateRuleReturnScope`1.cs new file mode 100644 index 0000000..5c1e81e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ITemplateRuleReturnScope`1.cs @@ -0,0 +1,42 @@ +/* + * [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 +{ + public interface ITemplateRuleReturnScope<TTemplate> : ITemplateRuleReturnScope + { + new TTemplate Template + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/IToken.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/IToken.cs new file mode 100644 index 0000000..8487703 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/IToken.cs @@ -0,0 +1,106 @@ +/* + * [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 +{ + + public interface IToken + { + /** <summary>Get the text of the token</summary> */ + string Text + { + get; + set; + } + + int Type + { + get; + set; + } + + /** <summary>The line number on which this token was matched; line=1..n</summary> */ + int Line + { + get; + set; + } + + /** <summary>The index of the first character relative to the beginning of the line 0..n-1</summary> */ + int CharPositionInLine + { + get; + set; + } + + int Channel + { + get; + set; + } + + int StartIndex + { + get; + set; + } + + int StopIndex + { + get; + set; + } + + /** <summary> + * An index from 0..n-1 of the token object in the input stream. + * This must be valid in order to use the ANTLRWorks debugger. + * </summary> + */ + int TokenIndex + { + get; + set; + } + + /** <summary> + * From what character stream was this token created? You don't have to + * implement but it's nice to know where a Token comes from if you have + * include files etc... on the input. + * </summary> + */ + ICharStream InputStream + { + get; + set; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenSource.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenSource.cs new file mode 100644 index 0000000..97a9b2c --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenSource.cs @@ -0,0 +1,78 @@ +/* + * [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 +{ + + /** <summary> + * A source of tokens must provide a sequence of tokens via nextToken() + * and also must reveal it's source of characters; CommonToken's text is + * computed from a CharStream; it only store indices into the char stream. + * </summary> + * + * <remarks> + * Errors from the lexer are never passed to the parser. Either you want + * to keep going or you do not upon token recognition error. If you do not + * want to continue lexing then you do not want to continue parsing. Just + * throw an exception not under RecognitionException and Java will naturally + * toss you all the way out of the recognizers. If you want to continue + * lexing then you should not throw an exception to the parser--it has already + * requested a token. Keep lexing until you get a valid one. Just report + * errors and keep going, looking for a valid token. + * </summary> + */ + public interface ITokenSource + { + /** <summary> + * Return a Token object from your input stream (usually a CharStream). + * Do not fail/return upon lexing error; keep chewing on the characters + * until you get a good one; errors are not passed through to the parser. + * </summary> + */ + IToken NextToken(); + + /** <summary> + * Where are you getting tokens from? normally the implication will simply + * ask lexers input stream. + * </summary> + */ + string SourceName + { + get; + } + + string[] TokenNames + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenStream.cs new file mode 100644 index 0000000..a08e7f2 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenStream.cs @@ -0,0 +1,95 @@ +/* + * [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 +{ + + /** <summary>A stream of tokens accessing tokens from a TokenSource</summary> */ + public interface ITokenStream : IIntStream + { + /** <summary>Get Token at current input pointer + i ahead where i=1 is next Token. + * i<0 indicates tokens in the past. So -1 is previous token and -2 is + * two tokens ago. LT(0) is undefined. For i>=n, return Token.EOFToken. + * Return null for LT(0) and any index that results in an absolute address + * that is negative.</summary> + */ + IToken LT( int k ); + + /// <summary> + /// How far ahead has the stream been asked to look? The return + /// value is a valid index from 0..n-1. + /// </summary> + int Range + { + get; + } + + /** <summary> + * Get a token at an absolute index i; 0..n-1. This is really only + * needed for profiling and debugging and token stream rewriting. + * If you don't want to buffer up tokens, then this method makes no + * sense for you. Naturally you can't use the rewrite stream feature. + * I believe DebugTokenStream can easily be altered to not use + * this method, removing the dependency. + * </summary> + */ + IToken Get( int i ); + + /** <summary> + * Where is this stream pulling tokens from? This is not the name, but + * the object that provides Token objects. + * </summary> + */ + ITokenSource TokenSource + { + get; + } + + /** <summary> + * Return the text of all tokens from start to stop, inclusive. + * If the stream does not buffer all the tokens then it can just + * return "" or null; Users should not access $ruleLabel.text in + * an action of course in that case. + * </summary> + */ + string ToString( int start, int stop ); + + /** <summary> + * Because the user is not required to use a token with an index stored + * in it, we must provide a means for two token objects themselves to + * indicate the start/end location. Most often this will just delegate + * to the other toString(int,int). This is also parallel with + * the TreeNodeStream.toString(Object,Object). + * </summary> + */ + string ToString( IToken start, IToken stop ); + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenStreamInformation.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenStreamInformation.cs new file mode 100644 index 0000000..c72f225 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ITokenStreamInformation.cs @@ -0,0 +1,48 @@ +/* + * [The "BSD licence"] + * 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 +{ + public interface ITokenStreamInformation + { + IToken LastToken + { + get; + } + + IToken LastRealToken + { + get; + } + + int MaxLookBehind + { + get; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/LegacyCommonTokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/LegacyCommonTokenStream.cs new file mode 100644 index 0000000..936f586 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/LegacyCommonTokenStream.cs @@ -0,0 +1,526 @@ +/* + * [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 +{ + using System.Collections.Generic; + + using InvalidOperationException = System.InvalidOperationException; + using StringBuilder = System.Text.StringBuilder; + + /** <summary> + * The most common stream of tokens is one where every token is buffered up + * and tokens are prefiltered for a certain channel (the parser will only + * see these tokens and cannot change the filter channel number during the + * parse). + * </summary> + * + * <remarks>TODO: how to access the full token stream? How to track all tokens matched per rule?</remarks> + */ + [System.Serializable] + public class LegacyCommonTokenStream : ITokenStream + { + [System.NonSerialized] + ITokenSource _tokenSource; + + /** <summary> + * Record every single token pulled from the source so we can reproduce + * chunks of it later. + * </summary> + */ + protected List<IToken> tokens; + + /** <summary>Map<tokentype, channel> to override some Tokens' channel numbers</summary> */ + protected IDictionary<int, int> channelOverrideMap; + + /** <summary>Set<tokentype>; discard any tokens with this type</summary> */ + protected List<int> discardSet; + + /** <summary>Skip tokens on any channel but this one; this is how we skip whitespace...</summary> */ + protected int channel = TokenChannels.Default; + + /** <summary>By default, track all incoming tokens</summary> */ + protected bool discardOffChannelTokens = false; + + /** <summary>Track the last mark() call result value for use in rewind().</summary> */ + protected int lastMarker; + + /** <summary> + * The index into the tokens list of the current token (next token + * to consume). p==-1 indicates that the tokens list is empty + * </summary> + */ + protected int p = -1; + + public LegacyCommonTokenStream() + { + tokens = new List<IToken>( 500 ); + } + + public LegacyCommonTokenStream(ITokenSource tokenSource) + : this() + { + this._tokenSource = tokenSource; + } + + public LegacyCommonTokenStream( ITokenSource tokenSource, int channel ) + : this( tokenSource ) + { + this.channel = channel; + } + + public virtual int Index + { + get + { + return p; + } + } + + /// <summary> + /// How deep have we gone? + /// </summary> + public virtual int Range + { + get; + protected set; + } + + /** <summary>Reset this token stream by setting its token source.</summary> */ + public virtual void SetTokenSource( ITokenSource tokenSource ) + { + this._tokenSource = tokenSource; + tokens.Clear(); + p = -1; + channel = TokenChannels.Default; + } + + /** <summary> + * Load all tokens from the token source and put in tokens. + * This is done upon first LT request because you might want to + * set some token type / channel overrides before filling buffer. + * </summary> + */ + public virtual void FillBuffer() + { + // fast return if the buffer is already full + if ( p != -1 ) + return; + + int index = 0; + IToken t = _tokenSource.NextToken(); + while ( t != null && t.Type != CharStreamConstants.EndOfFile ) + { + bool discard = false; + // is there a channel override for token type? + int channelI; + if ( channelOverrideMap != null && channelOverrideMap.TryGetValue( t.Type, out channelI ) ) + t.Channel = channelI; + + //if ( channelOverrideMap != null && channelOverrideMap.ContainsKey( t.getType() ) ) + //{ + // object channelI = channelOverrideMap.get( t.getType() ); + // if ( channelI != null ) + // { + // t.setChannel( (int)channelI ); + // } + //} + if ( discardSet != null && + discardSet.Contains( t.Type ) ) + { + discard = true; + } + else if ( discardOffChannelTokens && t.Channel != this.channel ) + { + discard = true; + } + if ( !discard ) + { + t.TokenIndex = index; + tokens.Add( t ); + index++; + } + t = _tokenSource.NextToken(); + } + // leave p pointing at first token on channel + p = 0; + p = SkipOffTokenChannels( p ); + } + + /** <summary> + * Move the input pointer to the next incoming token. The stream + * must become active with LT(1) available. consume() simply + * moves the input pointer so that LT(1) points at the next + * input symbol. Consume at least one token. + * </summary> + * + * <remarks> + * Walk past any token not on the channel the parser is listening to. + * </remarks> + */ + public virtual void Consume() + { + if ( p < tokens.Count ) + { + p++; + p = SkipOffTokenChannels( p ); // leave p on valid token + } + } + + /** <summary>Given a starting index, return the index of the first on-channel token.</summary> */ + protected virtual int SkipOffTokenChannels( int i ) + { + int n = tokens.Count; + while ( i < n && ( (IToken)tokens[i] ).Channel != channel ) + { + i++; + } + return i; + } + + protected virtual int SkipOffTokenChannelsReverse( int i ) + { + while ( i >= 0 && ( (IToken)tokens[i] ).Channel != channel ) + { + i--; + } + return i; + } + + /** <summary> + * A simple filter mechanism whereby you can tell this token stream + * to force all tokens of type ttype to be on channel. For example, + * when interpreting, we cannot exec actions so we need to tell + * the stream to force all WS and NEWLINE to be a different, ignored + * channel. + * </summary> + */ + public virtual void SetTokenTypeChannel( int ttype, int channel ) + { + if ( channelOverrideMap == null ) + { + channelOverrideMap = new Dictionary<int, int>(); + } + channelOverrideMap[ttype] = channel; + } + + public virtual void DiscardTokenType( int ttype ) + { + if ( discardSet == null ) + { + discardSet = new List<int>(); + } + discardSet.Add( ttype ); + } + + public virtual void SetDiscardOffChannelTokens( bool discardOffChannelTokens ) + { + this.discardOffChannelTokens = discardOffChannelTokens; + } + + public virtual IList<IToken> GetTokens() + { + if ( p == -1 ) + { + FillBuffer(); + } + return tokens; + } + + public virtual IList<IToken> GetTokens( int start, int stop ) + { + return GetTokens( start, stop, (BitSet)null ); + } + + /** <summary> + * Given a start and stop index, return a List of all tokens in + * the token type BitSet. Return null if no tokens were found. This + * method looks at both on and off channel tokens. + * </summary> + */ + public virtual IList<IToken> GetTokens( int start, int stop, BitSet types ) + { + if ( p == -1 ) + { + FillBuffer(); + } + if ( stop >= tokens.Count ) + { + stop = tokens.Count - 1; + } + if ( start < 0 ) + { + start = 0; + } + if ( start > stop ) + { + return null; + } + + // list = tokens[start:stop]:{Token t, t.getType() in types} + IList<IToken> filteredTokens = new List<IToken>(); + for ( int i = start; i <= stop; i++ ) + { + IToken t = tokens[i]; + if ( types == null || types.Member( t.Type ) ) + { + filteredTokens.Add( t ); + } + } + if ( filteredTokens.Count == 0 ) + { + filteredTokens = null; + } + return filteredTokens; + } + + public virtual IList<IToken> GetTokens( int start, int stop, IList<int> types ) + { + return GetTokens( start, stop, new BitSet( types ) ); + } + + public virtual IList<IToken> GetTokens( int start, int stop, int ttype ) + { + return GetTokens( start, stop, BitSet.Of( ttype ) ); + } + + /** <summary> + * Get the ith token from the current position 1..n where k=1 is the + * first symbol of lookahead. + * </summary> + */ + public virtual IToken LT( int k ) + { + if ( p == -1 ) + { + FillBuffer(); + } + if ( k == 0 ) + { + return null; + } + if ( k < 0 ) + { + return LB( -k ); + } + //System.out.print("LT(p="+p+","+k+")="); + if ( ( p + k - 1 ) >= tokens.Count ) + { + return tokens[tokens.Count - 1]; + } + //System.out.println(tokens.get(p+k-1)); + int i = p; + int n = 1; + // find k good tokens + while ( n < k ) + { + // skip off-channel tokens + i = SkipOffTokenChannels( i + 1 ); // leave p on valid token + n++; + } + if ( i >= tokens.Count ) + { + return tokens[tokens.Count - 1]; + } + + if (i > Range) + Range = i; + + return (IToken)tokens[i]; + } + + /** <summary>Look backwards k tokens on-channel tokens</summary> */ + protected virtual IToken LB( int k ) + { + //System.out.print("LB(p="+p+","+k+") "); + if ( p == -1 ) + { + FillBuffer(); + } + if ( k == 0 ) + { + return null; + } + if ( ( p - k ) < 0 ) + { + return null; + } + + int i = p; + int n = 1; + // find k good tokens looking backwards + while ( n <= k ) + { + // skip off-channel tokens + i = SkipOffTokenChannelsReverse( i - 1 ); // leave p on valid token + n++; + } + if ( i < 0 ) + { + return null; + } + return (IToken)tokens[i]; + } + + /** <summary> + * Return absolute token i; ignore which channel the tokens are on; + * that is, count all tokens not just on-channel tokens. + * </summary> + */ + public virtual IToken Get( int i ) + { + return (IToken)tokens[i]; + } + +#if false + /** Get all tokens from start..stop inclusively */ + public virtual List<IToken> Get(int start, int count) + { + if (start < 0) + throw new ArgumentOutOfRangeException("start"); + if (count < 0) + throw new ArgumentOutOfRangeException("count"); + + if (p == -1) + FillBuffer(); + + return new List<IToken>(tokens.Skip(start).Take(count)); + } +#endif + + public virtual int LA( int i ) + { + return LT( i ).Type; + } + + public virtual int Mark() + { + if ( p == -1 ) + { + FillBuffer(); + } + lastMarker = Index; + return lastMarker; + } + + public virtual void Release( int marker ) + { + // no resources to release + } + + public virtual int Count + { + get + { + return tokens.Count; + } + } + + public virtual void Rewind( int marker ) + { + Seek( marker ); + } + + public virtual void Rewind() + { + Seek( lastMarker ); + } + + public virtual void Reset() + { + p = 0; + lastMarker = 0; + } + + public virtual void Seek( int index ) + { + p = index; + } + + public virtual ITokenSource TokenSource + { + get + { + return _tokenSource; + } + } + + public virtual string SourceName + { + get + { + return TokenSource.SourceName; + } + } + + public override string ToString() + { + if ( p == -1 ) + { + throw new InvalidOperationException( "Buffer is not yet filled." ); + } + return ToString( 0, tokens.Count - 1 ); + } + + public virtual string ToString( int start, int stop ) + { + if ( start < 0 || stop < 0 ) + { + return null; + } + if ( p == -1 ) + { + throw new InvalidOperationException( "Buffer is not yet filled." ); + } + if ( stop >= tokens.Count ) + { + stop = tokens.Count - 1; + } + StringBuilder buf = new StringBuilder(); + for ( int i = start; i <= stop; i++ ) + { + IToken t = tokens[i]; + buf.Append( t.Text ); + } + return buf.ToString(); + } + + public virtual string ToString( IToken start, IToken stop ) + { + if ( start != null && stop != null ) + { + return ToString( start.TokenIndex, stop.TokenIndex ); + } + return null; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Lexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Lexer.cs new file mode 100644 index 0000000..cf478c6 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Lexer.cs @@ -0,0 +1,435 @@ +/* + * [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 +{ + using ConditionalAttribute = System.Diagnostics.ConditionalAttribute; + + /** <summary> + * A lexer is recognizer that draws input symbols from a character stream. + * lexer grammars result in a subclass of this object. A Lexer object + * uses simplified match() and error recovery mechanisms in the interest + * of speed. + * </summary> + */ + public abstract class Lexer : BaseRecognizer, ITokenSource + { + /** <summary>Where is the lexer drawing characters from?</summary> */ + protected ICharStream input; + + public Lexer() + { + } + + public Lexer( ICharStream input ) + { + this.input = input; + } + + public Lexer( ICharStream input, RecognizerSharedState state ) + : base(state) + { + this.input = input; + } + + #region Properties + public string Text + { + /** <summary>Return the text matched so far for the current token or any text override.</summary> */ + get + { + if ( state.text != null ) + { + return state.text; + } + return input.Substring( state.tokenStartCharIndex, CharIndex - state.tokenStartCharIndex ); + } + /** <summary>Set the complete text of this token; it wipes any previous changes to the text.</summary> */ + set + { + state.text = value; + } + } + public int Line + { + get + { + return input.Line; + } + set + { + input.Line = value; + } + } + public int CharPositionInLine + { + get + { + return input.CharPositionInLine; + } + set + { + input.CharPositionInLine = value; + } + } + #endregion + + public override void Reset() + { + base.Reset(); // reset all recognizer state variables + // wack Lexer state variables + if ( input != null ) + { + input.Seek( 0 ); // rewind the input + } + if ( state == null ) + { + return; // no shared state work to do + } + state.token = null; + state.type = TokenTypes.Invalid; + state.channel = TokenChannels.Default; + state.tokenStartCharIndex = -1; + state.tokenStartCharPositionInLine = -1; + state.tokenStartLine = -1; + state.text = null; + } + + /** <summary>Return a token from this source; i.e., match a token on the char stream.</summary> */ + public virtual IToken NextToken() + { + for ( ; ; ) + { + state.token = null; + state.channel = TokenChannels.Default; + state.tokenStartCharIndex = input.Index; + state.tokenStartCharPositionInLine = input.CharPositionInLine; + state.tokenStartLine = input.Line; + state.text = null; + if ( input.LA( 1 ) == CharStreamConstants.EndOfFile ) + { + IToken eof = new CommonToken((ICharStream)input, CharStreamConstants.EndOfFile, TokenChannels.Default, input.Index, input.Index); + eof.Line = Line; + eof.CharPositionInLine = CharPositionInLine; + return eof; + } + try + { + ParseNextToken(); + if ( state.token == null ) + { + Emit(); + } + else if ( state.token == Tokens.Skip ) + { + continue; + } + return state.token; + } + catch (MismatchedRangeException mre) + { + ReportError(mre); + // MatchRange() routine has already called recover() + } + catch (MismatchedTokenException mte) + { + ReportError(mte); + // Match() routine has already called recover() + } + catch ( RecognitionException re ) + { + ReportError( re ); + Recover( re ); // throw out current char and try again + } + } + } + + /** <summary> + * Instruct the lexer to skip creating a token for current lexer rule + * and look for another token. nextToken() knows to keep looking when + * a lexer rule finishes with token set to SKIP_TOKEN. Recall that + * if token==null at end of any token rule, it creates one for you + * and emits it. + * </summary> + */ + public virtual void Skip() + { + state.token = Tokens.Skip; + } + + /** <summary>This is the lexer entry point that sets instance var 'token'</summary> */ + public abstract void mTokens(); + + public virtual ICharStream CharStream + { + get + { + return input; + } + /** <summary>Set the char stream and reset the lexer</summary> */ + set + { + input = null; + Reset(); + input = value; + } + } + + public override string SourceName + { + get + { + return input.SourceName; + } + } + + /** <summary> + * Currently does not support multiple emits per nextToken invocation + * for efficiency reasons. Subclass and override this method and + * nextToken (to push tokens into a list and pull from that list rather + * than a single variable as this implementation does). + * </summary> + */ + public virtual void Emit( IToken token ) + { + state.token = token; + } + + /** <summary> + * The standard method called to automatically emit a token at the + * outermost lexical rule. The token object should point into the + * char buffer start..stop. If there is a text override in 'text', + * use that to set the token's text. Override this method to emit + * custom Token objects. + * </summary> + * + * <remarks> + * If you are building trees, then you should also override + * Parser or TreeParser.getMissingSymbol(). + * </remarks> + */ + public virtual IToken Emit() + { + IToken t = new CommonToken( input, state.type, state.channel, state.tokenStartCharIndex, CharIndex - 1 ); + t.Line = state.tokenStartLine; + t.Text = state.text; + t.CharPositionInLine = state.tokenStartCharPositionInLine; + Emit( t ); + return t; + } + + public virtual void Match( string s ) + { + int i = 0; + while ( i < s.Length ) + { + if ( input.LA( 1 ) != s[i] ) + { + if ( state.backtracking > 0 ) + { + state.failed = true; + return; + } + MismatchedTokenException mte = new MismatchedTokenException(s[i], input, TokenNames); + Recover( mte ); + throw mte; + } + i++; + input.Consume(); + state.failed = false; + } + } + + public virtual void MatchAny() + { + input.Consume(); + } + + public virtual void Match( int c ) + { + if ( input.LA( 1 ) != c ) + { + if ( state.backtracking > 0 ) + { + state.failed = true; + return; + } + MismatchedTokenException mte = new MismatchedTokenException(c, input, TokenNames); + Recover( mte ); // don't really recover; just consume in lexer + throw mte; + } + input.Consume(); + state.failed = false; + } + + public virtual void MatchRange( int a, int b ) + { + if ( input.LA( 1 ) < a || input.LA( 1 ) > b ) + { + if ( state.backtracking > 0 ) + { + state.failed = true; + return; + } + MismatchedRangeException mre = new MismatchedRangeException(a, b, input); + Recover( mre ); + throw mre; + } + input.Consume(); + state.failed = false; + } + + /** <summary>What is the index of the current character of lookahead?</summary> */ + public virtual int CharIndex + { + get + { + return input.Index; + } + } + + public override void ReportError( RecognitionException e ) + { + /** TODO: not thought about recovery in lexer yet. + * + // if we've already reported an error and have not matched a token + // yet successfully, don't report any errors. + if ( errorRecovery ) { + //System.err.print("[SPURIOUS] "); + return; + } + errorRecovery = true; + */ + + DisplayRecognitionError( this.TokenNames, e ); + } + + public override string GetErrorMessage( RecognitionException e, string[] tokenNames ) + { + string msg = null; + if ( e is MismatchedTokenException ) + { + MismatchedTokenException mte = (MismatchedTokenException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting " + GetCharErrorDisplay( mte.Expecting ); + } + else if ( e is NoViableAltException ) + { + NoViableAltException nvae = (NoViableAltException)e; + // for development, can add "decision=<<"+nvae.grammarDecisionDescription+">>" + // and "(decision="+nvae.decisionNumber+") and + // "state "+nvae.stateNumber + msg = "no viable alternative at character " + GetCharErrorDisplay( e.Character ); + } + else if ( e is EarlyExitException ) + { + EarlyExitException eee = (EarlyExitException)e; + // for development, can add "(decision="+eee.decisionNumber+")" + msg = "required (...)+ loop did not match anything at character " + GetCharErrorDisplay( e.Character ); + } + else if ( e is MismatchedNotSetException ) + { + MismatchedNotSetException mse = (MismatchedNotSetException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting set " + mse.Expecting; + } + else if ( e is MismatchedSetException ) + { + MismatchedSetException mse = (MismatchedSetException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting set " + mse.Expecting; + } + else if ( e is MismatchedRangeException ) + { + MismatchedRangeException mre = (MismatchedRangeException)e; + msg = "mismatched character " + GetCharErrorDisplay( e.Character ) + " expecting set " + + GetCharErrorDisplay( mre.A ) + ".." + GetCharErrorDisplay( mre.B ); + } + else + { + msg = base.GetErrorMessage( e, tokenNames ); + } + return msg; + } + + public virtual string GetCharErrorDisplay( int c ) + { + string s = ( (char)c ).ToString(); + switch ( c ) + { + case TokenTypes.EndOfFile: + s = "<EOF>"; + break; + case '\n': + s = "\\n"; + break; + case '\t': + s = "\\t"; + break; + case '\r': + s = "\\r"; + break; + } + return "'" + s + "'"; + } + + /** <summary> + * Lexers can normally match any char in it's vocabulary after matching + * a token, so do the easy thing and just kill a character and hope + * it all works out. You can instead use the rule invocation stack + * to do sophisticated error recovery if you are in a fragment rule. + * </summary> + */ + public virtual void Recover( RecognitionException re ) + { + //System.out.println("consuming char "+(char)input.LA(1)+" during recovery"); + //re.printStackTrace(); + input.Consume(); + } + + [Conditional("ANTLR_TRACE")] + public virtual void TraceIn( string ruleName, int ruleIndex ) + { + string inputSymbol = ( (char)input.LT( 1 ) ) + " line=" + Line + ":" + CharPositionInLine; + base.TraceIn( ruleName, ruleIndex, inputSymbol ); + } + + [Conditional("ANTLR_TRACE")] + public virtual void TraceOut( string ruleName, int ruleIndex ) + { + string inputSymbol = ( (char)input.LT( 1 ) ) + " line=" + Line + ":" + CharPositionInLine; + base.TraceOut( ruleName, ruleIndex, inputSymbol ); + } + + protected virtual void ParseNextToken() + { + mTokens(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/FastQueue.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/FastQueue.cs new file mode 100644 index 0000000..2dc5bfc --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/FastQueue.cs @@ -0,0 +1,143 @@ +/* + * [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 ArgumentException = System.ArgumentException; + using InvalidOperationException = System.InvalidOperationException; + + /** A queue that can dequeue and get(i) in O(1) and grow arbitrarily large. + * A linked list is fast at dequeue but slow at get(i). An array is + * the reverse. This is O(1) for both operations. + * + * List grows until you dequeue last element at end of buffer. Then + * it resets to start filling at 0 again. If adds/removes are balanced, the + * buffer will not grow too large. + * + * No iterator stuff as that's not how we'll use it. + */ + public class FastQueue<T> + { + /** <summary>dynamically-sized buffer of elements</summary> */ + internal List<T> _data = new List<T>(); + /** <summary>index of next element to fill</summary> */ + internal int _p = 0; + + public virtual int Count + { + get + { + return _data.Count - _p; + } + } + + /// <summary> + /// How deep have we gone? + /// </summary> + public virtual int Range + { + get; + protected set; + } + + /** <summary> + * Return element i elements ahead of current element. i==0 gets + * current element. This is not an absolute index into the data list + * since p defines the start of the real list. + * </summary> + */ + public virtual T this[int i] + { + get + { + int absIndex = _p + i; + if (absIndex >= _data.Count) + throw new ArgumentException(string.Format("queue index {0} > last index {1}", absIndex, _data.Count - 1)); + if (absIndex < 0) + throw new ArgumentException(string.Format("queue index {0} < 0", absIndex)); + + if (absIndex > Range) + Range = absIndex; + + return _data[absIndex]; + } + } + + /** <summary>Get and remove first element in queue</summary> */ + public virtual T Dequeue() + { + if (Count == 0) + throw new InvalidOperationException(); + + T o = this[0]; + _p++; + // have we hit end of buffer? + if ( _p == _data.Count ) + { + // if so, it's an opportunity to start filling at index 0 again + Clear(); // size goes to 0, but retains memory + } + return o; + } + + public virtual void Enqueue( T o ) + { + _data.Add( o ); + } + + public virtual T Peek() + { + return this[0]; + } + + public virtual void Clear() + { + _p = 0; + _data.Clear(); + } + + /** <summary>Return string of current buffer contents; non-destructive</summary> */ + public override string ToString() + { + System.Text.StringBuilder buf = new System.Text.StringBuilder(); + int n = Count; + for ( int i = 0; i < n; i++ ) + { + buf.Append( this[i] ); + if ( ( i + 1 ) < n ) + buf.Append( " " ); + } + return buf.ToString(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/FunctionDelegates.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/FunctionDelegates.cs new file mode 100644 index 0000000..4fb91bf --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/FunctionDelegates.cs @@ -0,0 +1,40 @@ +/* + * [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.Misc +{ + public delegate void Action(); + + public delegate TResult Func<TResult>(); + + public delegate TResult Func<T, TResult>(T arg); +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/ListStack`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/ListStack`1.cs new file mode 100644 index 0000000..e66adcb --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/ListStack`1.cs @@ -0,0 +1,98 @@ +/* + * [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.Misc +{ + using System.Collections.Generic; + using InvalidOperationException = System.InvalidOperationException; + + public class ListStack<T> : List<T> + { + public T Peek() + { + return Peek(0); + } + + public T Peek(int depth) + { + T item; + if (!TryPeek(depth, out item)) + throw new InvalidOperationException(); + + return item; + } + + public bool TryPeek(out T item) + { + return TryPeek(0, out item); + } + + public bool TryPeek(int depth, out T item) + { + if (depth >= Count) + { + item = default(T); + return false; + } + + item = this[Count - depth - 1]; + return true; + } + + public T Pop() + { + T result; + if (!TryPop(out result)) + throw new InvalidOperationException(); + + return result; + } + + public bool TryPop(out T item) + { + if (Count == 0) + { + item = default(T); + return false; + } + + item = this[Count - 1]; + RemoveAt(Count - 1); + return true; + } + + public void Push(T item) + { + Add(item); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs new file mode 100644 index 0000000..24dc0cb --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Misc/LookaheadStream.cs @@ -0,0 +1,234 @@ +/* + * [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 ArgumentException = System.ArgumentException; + using InvalidOperationException = System.InvalidOperationException; + + /** <summary> + * A lookahead queue that knows how to mark/release locations + * in the buffer for backtracking purposes. Any markers force the FastQueue + * superclass to keep all tokens until no more markers; then can reset + * to avoid growing a huge buffer. + * </summary> + */ + public abstract class LookaheadStream<T> + : FastQueue<T> + where T : class + { + /** Absolute token index. It's the index of the symbol about to be + * read via LT(1). Goes from 0 to numtokens. + */ + private int _currentElementIndex = 0; + + private T _previousElement; + + /** Track object returned by nextElement upon end of stream; + * Return it later when they ask for LT passed end of input. + */ + T _eof = null; + + /** <summary>Track the last mark() call result value for use in rewind().</summary> */ + int _lastMarker; + + /** <summary>tracks how deep mark() calls are nested</summary> */ + int _markDepth; + + public T EndOfFile + { + get + { + return _eof; + } + protected set + { + _eof = value; + } + } + + public T PreviousElement + { + get + { + return _previousElement; + } + } + + public override void Clear() + { + base.Clear(); + _currentElementIndex = 0; + _p = 0; + _previousElement = null; + } + + /** <summary> + * Implement nextElement to supply a stream of elements to this + * lookahead buffer. Return eof upon end of the stream we're pulling from. + * </summary> + */ + public abstract T NextElement(); + + public abstract bool IsEndOfFile(T o); + + /** <summary>Get and remove first element in queue; override FastQueue.remove()</summary> */ + public override T Dequeue() + { + T o = this[0]; + _p++; + // have we hit end of buffer and not backtracking? + if ( _p == _data.Count && _markDepth == 0 ) + { + // if so, it's an opportunity to start filling at index 0 again + Clear(); // size goes to 0, but retains memory + } + return o; + } + + /** <summary>Make sure we have at least one element to remove, even if EOF</summary> */ + public virtual void Consume() + { + SyncAhead(1); + _previousElement = Dequeue(); + _currentElementIndex++; + } + + /** <summary> + * Make sure we have 'need' elements from current position p. Last valid + * p index is data.size()-1. p+need-1 is the data index 'need' elements + * ahead. If we need 1 element, (p+1-1)==p must be < data.size(). + * </summary> + */ + protected virtual void SyncAhead( int need ) + { + int n = ( _p + need - 1 ) - _data.Count + 1; // how many more elements we need? + if ( n > 0 ) + Fill( n ); // out of elements? + } + + /** <summary>add n elements to buffer</summary> */ + public virtual void Fill( int n ) + { + for ( int i = 0; i < n; i++ ) + { + T o = NextElement(); + if ( IsEndOfFile(o) ) + _eof = o; + + _data.Add( o ); + } + } + + /** <summary>Size of entire stream is unknown; we only know buffer size from FastQueue</summary> */ + public override int Count + { + get + { + throw new System.NotSupportedException( "streams are of unknown size" ); + } + } + + public virtual T LT( int k ) + { + if ( k == 0 ) + { + return null; + } + if ( k < 0 ) + { + return LB(-k); + } + + SyncAhead( k ); + if ((_p + k - 1) > _data.Count) + return _eof; + + return this[k - 1]; + } + + public virtual int Index + { + get + { + return _currentElementIndex; + } + } + + public virtual int Mark() + { + _markDepth++; + _lastMarker = _p; // track where we are in buffer, not absolute token index + return _lastMarker; + } + + public virtual void Release( int marker ) + { + if (_markDepth == 0) + throw new InvalidOperationException(); + + _markDepth--; + } + + public virtual void Rewind( int marker ) + { + Seek( marker ); + Release( marker ); + } + + public virtual void Rewind() + { + Rewind( _lastMarker ); + } + + /** <summary> + * Seek to a 0-indexed position within data buffer. Can't handle + * case where you seek beyond end of existing buffer. Normally used + * to seek backwards in the buffer. Does not force loading of nodes. + * Doesn't see to absolute position in input stream since this stream + * is unbuffered. Seeks only into our moving window of elements. + * </summary> + */ + public virtual void Seek( int index ) + { + _p = index; + } + + protected virtual T LB(int k) + { + if (k == 1) + return _previousElement; + + throw new ArgumentException("can't look backwards more than one token in this stream"); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedNotSetException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedNotSetException.cs new file mode 100644 index 0000000..b6ebc8f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedNotSetException.cs @@ -0,0 +1,81 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + [System.Serializable] + public class MismatchedNotSetException : MismatchedSetException + { + public MismatchedNotSetException() + { + } + + public MismatchedNotSetException(string message) + : base(message) + { + } + + public MismatchedNotSetException(string message, Exception innerException) + : base(message, innerException) + { + } + + public MismatchedNotSetException(BitSet expecting, IIntStream input) + : base(expecting, input) + { + } + + public MismatchedNotSetException(string message, BitSet expecting, IIntStream input) + : base(message, expecting, input) + { + } + + public MismatchedNotSetException(string message, BitSet expecting, IIntStream input, Exception innerException) + : base(message, expecting, input, innerException) + { + } + + protected MismatchedNotSetException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + + public override string ToString() + { + return "MismatchedNotSetException(" + UnexpectedType + "!=" + Expecting + ")"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedRangeException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedRangeException.cs new file mode 100644 index 0000000..c714aef --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedRangeException.cs @@ -0,0 +1,122 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + [System.Serializable] + public class MismatchedRangeException : RecognitionException + { + private readonly int _a; + private readonly int _b; + + public MismatchedRangeException() + { + } + + public MismatchedRangeException(string message) + : base(message) + { + } + + public MismatchedRangeException(string message, Exception innerException) + : base(message, innerException) + { + } + + public MismatchedRangeException(int a, int b, IIntStream input) + : base(input) + { + this._a = a; + this._b = b; + } + + public MismatchedRangeException(string message, int a, int b, IIntStream input) + : base(message, input) + { + this._a = a; + this._b = b; + } + + public MismatchedRangeException(string message, int a, int b, IIntStream input, Exception innerException) + : base(message, input, innerException) + { + this._a = a; + this._b = b; + } + + protected MismatchedRangeException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + this._a = info.GetInt32("A"); + this._b = info.GetInt32("B"); + } + + public int A + { + get + { + return _a; + } + } + + public int B + { + get + { + return _b; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("A", _a); + info.AddValue("B", _b); + } + + public override string ToString() + { + return "MismatchedRangeException(" + UnexpectedType + " not in [" + A + "," + B + "])"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedSetException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedSetException.cs new file mode 100644 index 0000000..10baecf --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedSetException.cs @@ -0,0 +1,108 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + [System.Serializable] + public class MismatchedSetException : RecognitionException + { + private readonly BitSet _expecting; + + public MismatchedSetException() + { + } + + public MismatchedSetException(string message) + : base(message) + { + } + + public MismatchedSetException(string message, Exception innerException) + : base(message, innerException) + { + } + + public MismatchedSetException( BitSet expecting, IIntStream input ) + : base( input ) + { + this._expecting = expecting; + } + + public MismatchedSetException(string message, BitSet expecting, IIntStream input) + : base(message, input) + { + this._expecting = expecting; + } + + public MismatchedSetException(string message, BitSet expecting, IIntStream input, Exception innerException) + : base(message, input, innerException) + { + this._expecting = expecting; + } + + protected MismatchedSetException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + this._expecting = (BitSet)info.GetValue("Expecting", typeof(BitSet)); + } + + public BitSet Expecting + { + get + { + return _expecting; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("Expecting", _expecting); + } + + public override string ToString() + { + return "MismatchedSetException(" + UnexpectedType + "!=" + Expecting + ")"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedTokenException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedTokenException.cs new file mode 100644 index 0000000..55c9aab --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedTokenException.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 +{ + using System.Collections.Generic; + using System.Collections.ObjectModel; + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary>A mismatched char or Token or tree node</summary> */ + [System.Serializable] + public class MismatchedTokenException : RecognitionException + { + private readonly int _expecting = TokenTypes.Invalid; + private readonly ReadOnlyCollection<string> _tokenNames; + + public MismatchedTokenException() + { + } + + public MismatchedTokenException(string message) + : base(message) + { + } + + public MismatchedTokenException(string message, Exception innerException) + : base(message, innerException) + { + } + + public MismatchedTokenException(int expecting, IIntStream input) + : this(expecting, input, null) + { + } + + public MismatchedTokenException(int expecting, IIntStream input, IList<string> tokenNames) + : base(input) + { + this._expecting = expecting; + + if (tokenNames != null) + this._tokenNames = new List<string>(tokenNames).AsReadOnly(); + } + + public MismatchedTokenException(string message, int expecting, IIntStream input, IList<string> tokenNames) + : base(message, input) + { + this._expecting = expecting; + + if (tokenNames != null) + this._tokenNames = new List<string>(tokenNames).AsReadOnly(); + } + + public MismatchedTokenException(string message, int expecting, IIntStream input, IList<string> tokenNames, Exception innerException) + : base(message, input, innerException) + { + this._expecting = expecting; + + if (tokenNames != null) + this._tokenNames = new List<string>(tokenNames).AsReadOnly(); + } + + protected MismatchedTokenException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + this._expecting = info.GetInt32("Expecting"); + this._tokenNames = new ReadOnlyCollection<string>((string[])info.GetValue("TokenNames", typeof(string[]))); + } + + public int Expecting + { + get + { + return _expecting; + } + } + + public ReadOnlyCollection<string> TokenNames + { + get + { + return _tokenNames; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("Expecting", _expecting); + info.AddValue("TokenNames", (_tokenNames != null) ? new List<string>(_tokenNames).ToArray() : default(string[])); + } + + public override string ToString() + { + int unexpectedType = UnexpectedType; + string unexpected = ( TokenNames != null && unexpectedType >= 0 && unexpectedType < TokenNames.Count ) ? TokenNames[unexpectedType] : unexpectedType.ToString(); + string expected = ( TokenNames != null && Expecting >= 0 && Expecting < TokenNames.Count ) ? TokenNames[Expecting] : Expecting.ToString(); + return "MismatchedTokenException(" + unexpected + "!=" + expected + ")"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedTreeNodeException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedTreeNodeException.cs new file mode 100644 index 0000000..2a33279 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/MismatchedTreeNodeException.cs @@ -0,0 +1,109 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using ITreeNodeStream = Antlr.Runtime.Tree.ITreeNodeStream; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + [System.Serializable] + public class MismatchedTreeNodeException : RecognitionException + { + private readonly int _expecting; + + public MismatchedTreeNodeException() + { + } + + public MismatchedTreeNodeException(string message) + : base(message) + { + } + + public MismatchedTreeNodeException(string message, Exception innerException) + : base(message, innerException) + { + } + + public MismatchedTreeNodeException( int expecting, ITreeNodeStream input ) + : base( input ) + { + this._expecting = expecting; + } + + public MismatchedTreeNodeException(string message, int expecting, ITreeNodeStream input) + : base(message, input) + { + this._expecting = expecting; + } + + public MismatchedTreeNodeException(string message, int expecting, ITreeNodeStream input, Exception innerException) + : base(message, input, innerException) + { + this._expecting = expecting; + } + + protected MismatchedTreeNodeException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + this._expecting = info.GetInt32("Expecting"); + } + + public int Expecting + { + get + { + return _expecting; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("Expecting", _expecting); + } + + public override string ToString() + { + return "MismatchedTreeNodeException(" + UnexpectedType + "!=" + Expecting + ")"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/MissingTokenException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/MissingTokenException.cs new file mode 100644 index 0000000..7a9cba1 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/MissingTokenException.cs @@ -0,0 +1,113 @@ +/* + * [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 +{ + using System.Collections.Generic; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary> + * We were expecting a token but it's not found. The current token + * is actually what we wanted next. Used for tree node errors too. + * </summary> + */ + [System.Serializable] + public class MissingTokenException : MismatchedTokenException + { + private readonly object _inserted; + + public MissingTokenException() + { + } + + public MissingTokenException(string message) + : base(message) + { + } + + public MissingTokenException(string message, Exception innerException) + : base(message, innerException) + { + } + + public MissingTokenException(int expecting, IIntStream input, object inserted) + : this(expecting, input, inserted, null) + { + } + + public MissingTokenException(int expecting, IIntStream input, object inserted, IList<string> tokenNames) + : base(expecting, input, tokenNames) + { + this._inserted = inserted; + } + + public MissingTokenException(string message, int expecting, IIntStream input, object inserted, IList<string> tokenNames) + : base(message, expecting, input, tokenNames) + { + this._inserted = inserted; + } + + public MissingTokenException(string message, int expecting, IIntStream input, object inserted, IList<string> tokenNames, Exception innerException) + : base(message, expecting, input, tokenNames, innerException) + { + this._inserted = inserted; + } + + protected MissingTokenException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + + public virtual int MissingType + { + get + { + return Expecting; + } + } + + public override string ToString() + { + if (_inserted != null && Token != null) + { + return "MissingTokenException(inserted " + _inserted + " at " + Token.Text + ")"; + } + if (Token != null) + { + return "MissingTokenException(at " + Token.Text + ")"; + } + return "MissingTokenException"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/NoViableAltException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/NoViableAltException.cs new file mode 100644 index 0000000..6478c6f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/NoViableAltException.cs @@ -0,0 +1,150 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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 +{ + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + [System.Serializable] + public class NoViableAltException : RecognitionException + { + private readonly string _grammarDecisionDescription; + private readonly int _decisionNumber; + private readonly int _stateNumber; + + public NoViableAltException() + { + } + + public NoViableAltException(string grammarDecisionDescription) + { + this._grammarDecisionDescription = grammarDecisionDescription; + } + + public NoViableAltException(string message, string grammarDecisionDescription) + : base(message) + { + this._grammarDecisionDescription = grammarDecisionDescription; + } + + public NoViableAltException(string message, string grammarDecisionDescription, Exception innerException) + : base(message, innerException) + { + this._grammarDecisionDescription = grammarDecisionDescription; + } + + public NoViableAltException(string grammarDecisionDescription, int decisionNumber, int stateNumber, IIntStream input) + : base(input) + { + this._grammarDecisionDescription = grammarDecisionDescription; + this._decisionNumber = decisionNumber; + this._stateNumber = stateNumber; + } + + public NoViableAltException(string message, string grammarDecisionDescription, int decisionNumber, int stateNumber, IIntStream input) + : base(message, input) + { + this._grammarDecisionDescription = grammarDecisionDescription; + this._decisionNumber = decisionNumber; + this._stateNumber = stateNumber; + } + + public NoViableAltException(string message, string grammarDecisionDescription, int decisionNumber, int stateNumber, IIntStream input, Exception innerException) + : base(message, input, innerException) + { + this._grammarDecisionDescription = grammarDecisionDescription; + this._decisionNumber = decisionNumber; + this._stateNumber = stateNumber; + } + + protected NoViableAltException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + this._grammarDecisionDescription = info.GetString("GrammarDecisionDescription"); + this._decisionNumber = info.GetInt32("DecisionNumber"); + this._stateNumber = info.GetInt32("StateNumber"); + } + + public int DecisionNumber + { + get + { + return _decisionNumber; + } + } + + public string GrammarDecisionDescription + { + get + { + return _grammarDecisionDescription; + } + } + + public int StateNumber + { + get + { + return _stateNumber; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("GrammarDecisionDescription", _grammarDecisionDescription); + info.AddValue("DecisionNumber", _decisionNumber); + info.AddValue("StateNumber", _stateNumber); + } + + public override string ToString() + { + if ( Input is ICharStream ) + { + return "NoViableAltException('" + (char)UnexpectedType + "'@[" + GrammarDecisionDescription + "])"; + } + else + { + return "NoViableAltException(" + UnexpectedType + "@[" + GrammarDecisionDescription + "])"; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Parser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Parser.cs new file mode 100644 index 0000000..4874140 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Parser.cs @@ -0,0 +1,131 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2011 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008-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 +{ + using ConditionalAttribute = System.Diagnostics.ConditionalAttribute; + + /** <summary> + * A parser for TokenStreams. "parser grammars" result in a subclass + * of this. + * </summary> + */ + public class Parser : BaseRecognizer + { + public ITokenStream input; + + public Parser( ITokenStream input ) + : base() + { + //super(); // highlight that we go to super to set state object + TokenStream = input; + } + + public Parser( ITokenStream input, RecognizerSharedState state ) + : base(state) // share the state object with another parser + { + this.input = input; + } + + public override void Reset() + { + base.Reset(); // reset all recognizer state variables + if ( input != null ) + { + input.Seek( 0 ); // rewind the input + } + } + + protected override object GetCurrentInputSymbol( IIntStream input ) + { + return ( (ITokenStream)input ).LT( 1 ); + } + + protected override object GetMissingSymbol( IIntStream input, + RecognitionException e, + int expectedTokenType, + BitSet follow ) + { + string tokenText = null; + if ( expectedTokenType == TokenTypes.EndOfFile ) + tokenText = "<missing EOF>"; + else + tokenText = "<missing " + TokenNames[expectedTokenType] + ">"; + CommonToken t = new CommonToken( expectedTokenType, tokenText ); + IToken current = ( (ITokenStream)input ).LT( 1 ); + if ( current.Type == TokenTypes.EndOfFile ) + { + current = ( (ITokenStream)input ).LT( -1 ); + } + t.Line = current.Line; + t.CharPositionInLine = current.CharPositionInLine; + t.Channel = DefaultTokenChannel; + t.InputStream = current.InputStream; + return t; + } + + /** <summary>Gets or sets the token stream; resets the parser upon a set.</summary> */ + public virtual ITokenStream TokenStream + { + get + { + return input; + } + set + { + input = null; + Reset(); + input = value; + } + } + + public override string SourceName + { + get + { + return input.SourceName; + } + } + + [Conditional("ANTLR_TRACE")] + public virtual void TraceIn( string ruleName, int ruleIndex ) + { + base.TraceIn( ruleName, ruleIndex, input.LT( 1 ) ); + } + + [Conditional("ANTLR_TRACE")] + public virtual void TraceOut( string ruleName, int ruleIndex ) + { + base.TraceOut( ruleName, ruleIndex, input.LT( 1 ) ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/ParserRuleReturnScope.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/ParserRuleReturnScope.cs new file mode 100644 index 0000000..7a0d58a --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/ParserRuleReturnScope.cs @@ -0,0 +1,106 @@ +/* + * [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 +{ + using CLSCompliant = System.CLSCompliantAttribute; + + /** <summary> + * Rules that return more than a single value must return an object + * containing all the values. Besides the properties defined in + * RuleLabelScope.predefinedRulePropertiesScope there may be user-defined + * return values. This class simply defines the minimum properties that + * are always defined and methods to access the others that might be + * available depending on output option such as template and tree. + * </summary> + * + * <remarks> + * Note text is not an actual property of the return value, it is computed + * from start and stop using the input stream's toString() method. I + * could add a ctor to this so that we can pass in and store the input + * stream, but I'm not sure we want to do that. It would seem to be undefined + * to get the .text property anyway if the rule matches tokens from multiple + * input streams. + * + * I do not use getters for fields of objects that are used simply to + * group values such as this aggregate. The getters/setters are there to + * satisfy the superclass interface. + * </remarks> + */ + public class ParserRuleReturnScope<TToken> : IRuleReturnScope<TToken> + { + private TToken _start; + private TToken _stop; + + public TToken Start + { + get + { + return _start; + } + + set + { + _start = value; + } + } + + public TToken Stop + { + get + { + return _stop; + } + + set + { + _stop = value; + } + } + + object IRuleReturnScope.Start + { + get + { + return Start; + } + } + + object IRuleReturnScope.Stop + { + get + { + return Stop; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Properties/AssemblyInfo.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..1489fde --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Properties/AssemblyInfo.cs @@ -0,0 +1,72 @@ +/* + * [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; +using System.Security; + +// 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" )] +[assembly: AssemblyDescription( "" )] +[assembly: AssemblyConfiguration( "" )] +[assembly: AssemblyCompany( "Pixel Mine, Inc." )] +[assembly: AssemblyProduct( "Antlr3.Runtime" )] +[assembly: AssemblyCopyright("Copyright © Sam Harwell 2011")] +[assembly: AssemblyTrademark( "" )] +[assembly: AssemblyCulture( "" )] +[assembly: CLSCompliant( true )] +[assembly: AllowPartiallyTrustedCallers] + +// 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( "7a0b4db7-f127-4cf5-ac2c-e294957efcd6" )] + +/* 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/RecognitionException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/RecognitionException.cs new file mode 100644 index 0000000..f0c5662 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/RecognitionException.cs @@ -0,0 +1,404 @@ +/* + * [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 +{ + using Antlr.Runtime.Tree; + + using ArgumentException = System.ArgumentException; + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary>The root of the ANTLR exception hierarchy.</summary> + * + * <remarks> + * To avoid English-only error messages and to generally make things + * as flexible as possible, these exceptions are not created with strings, + * but rather the information necessary to generate an error. Then + * the various reporting methods in Parser and Lexer can be overridden + * to generate a localized error message. For example, MismatchedToken + * exceptions are built with the expected token type. + * So, don't expect getMessage() to return anything. + * + * Note that as of Java 1.4, you can access the stack trace, which means + * that you can compute the complete trace of rules from the start symbol. + * This gives you considerable context information with which to generate + * useful error messages. + * + * ANTLR generates code that throws exceptions upon recognition error and + * also generates code to catch these exceptions in each rule. If you + * want to quit upon first error, you can turn off the automatic error + * handling mechanism using rulecatch action, but you still need to + * override methods mismatch and recoverFromMismatchSet. + * + * In general, the recognition exceptions can track where in a grammar a + * problem occurred and/or what was the expected input. While the parser + * knows its state (such as current input symbol and line info) that + * state can change before the exception is reported so current token index + * is computed and stored at exception time. From this info, you can + * perhaps print an entire line of input not just a single token, for example. + * Better to just say the recognizer had a problem and then let the parser + * figure out a fancy report. + * </remarks> + */ + [System.Serializable] + public class RecognitionException : Exception + { + /** <summary>What input stream did the error occur in?</summary> */ + private IIntStream _input; + + /** <summary>What is index of token/char were we looking at when the error occurred?</summary> */ + private int _index; + + /** <summary> + * The current Token when an error occurred. Since not all streams + * can retrieve the ith Token, we have to track the Token object. + * For parsers. Even when it's a tree parser, token might be set. + * </summary> + */ + private IToken _token; + + /** <summary> + * If this is a tree parser exception, node is set to the node with + * the problem. + * </summary> + */ + private object _node; + + /** <summary>The current char when an error occurred. For lexers.</summary> */ + private int _c; + + /** <summary> + * Track the line (1-based) at which the error occurred in case this is + * generated from a lexer. We need to track this since the + * unexpected char doesn't carry the line info. + * </summary> + */ + private int _line; + + /// <summary> + /// The 0-based index into the line where the error occurred. + /// </summary> + private int _charPositionInLine; + + /** <summary> + * If you are parsing a tree node stream, you will encounter som + * imaginary nodes w/o line/col info. We now search backwards looking + * for most recent token with line/col info, but notify getErrorHeader() + * that info is approximate. + * </summary> + */ + private bool _approximateLineInfo; + + /** <summary>Used for remote debugger deserialization</summary> */ + public RecognitionException() + : this("A recognition error occurred.", null, null) + { + } + + public RecognitionException( IIntStream input ) + : this("A recognition error occurred.", input, null) + { + } + + public RecognitionException(string message) + : this(message, null, null) + { + } + + public RecognitionException(string message, IIntStream input) + : this(message, input, null) + { + } + + public RecognitionException(string message, Exception innerException) + : this(message, null, innerException) + { + } + + public RecognitionException(string message, IIntStream input, Exception innerException) + : base(message, innerException) + { + this._input = input; + if (input != null) + { + this._index = input.Index; + if (input is ITokenStream) + { + this._token = ((ITokenStream)input).LT(1); + this._line = _token.Line; + this._charPositionInLine = _token.CharPositionInLine; + } + + ITreeNodeStream tns = input as ITreeNodeStream; + if (tns != null) + { + ExtractInformationFromTreeNodeStream(tns); + } + else + { + ICharStream charStream = input as ICharStream; + if (charStream != null) + { + this._c = input.LA(1); + this._line = ((ICharStream)input).Line; + this._charPositionInLine = ((ICharStream)input).CharPositionInLine; + } + else + { + this._c = input.LA(1); + } + } + } + } + + protected RecognitionException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + _index = info.GetInt32("Index"); + _c = info.GetInt32("C"); + _line = info.GetInt32("Line"); + _charPositionInLine = info.GetInt32("CharPositionInLine"); + _approximateLineInfo = info.GetBoolean("ApproximateLineInfo"); + } + + /** <summary>Return the token type or char of the unexpected input element</summary> */ + public virtual int UnexpectedType + { + get + { + if ( _input is ITokenStream ) + { + return _token.Type; + } + + ITreeNodeStream treeNodeStream = _input as ITreeNodeStream; + if ( treeNodeStream != null ) + { + ITreeAdaptor adaptor = treeNodeStream.TreeAdaptor; + return adaptor.GetType( _node ); + } + + return _c; + } + } + + public bool ApproximateLineInfo + { + get + { + return _approximateLineInfo; + } + protected set + { + _approximateLineInfo = value; + } + } + + public IIntStream Input + { + get + { + return _input; + } + protected set + { + _input = value; + } + } + + public IToken Token + { + get + { + return _token; + } + set + { + _token = value; + } + } + + public object Node + { + get + { + return _node; + } + protected set + { + _node = value; + } + } + + public int Character + { + get + { + return _c; + } + protected set + { + _c = value; + } + } + + public int Index + { + get + { + return _index; + } + protected set + { + _index = value; + } + } + + public int Line + { + get + { + return _line; + } + set + { + _line = value; + } + } + + public int CharPositionInLine + { + get + { + return _charPositionInLine; + } + set + { + _charPositionInLine = value; + } + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("Index", _index); + info.AddValue("C", _c); + info.AddValue("Line", _line); + info.AddValue("CharPositionInLine", _charPositionInLine); + info.AddValue("ApproximateLineInfo", _approximateLineInfo); + } + + protected virtual void ExtractInformationFromTreeNodeStream(ITreeNodeStream input) + { + this._node = input.LT(1); + ITokenStreamInformation streamInformation = input as ITokenStreamInformation; + if (streamInformation != null) + { + IToken lastToken = streamInformation.LastToken; + IToken lastRealToken = streamInformation.LastRealToken; + if (lastRealToken != null) + { + this._token = lastRealToken; + this._line = lastRealToken.Line; + this._charPositionInLine = lastRealToken.CharPositionInLine; + this._approximateLineInfo = lastRealToken.Equals(lastToken); + } + } + else + { + ITreeAdaptor adaptor = input.TreeAdaptor; + IToken payload = adaptor.GetToken(_node); + if (payload != null) + { + this._token = payload; + if (payload.Line <= 0) + { + // imaginary node; no line/pos info; scan backwards + int i = -1; + object priorNode = input.LT(i); + while (priorNode != null) + { + IToken priorPayload = adaptor.GetToken(priorNode); + if (priorPayload != null && priorPayload.Line > 0) + { + // we found the most recent real line / pos info + this._line = priorPayload.Line; + this._charPositionInLine = priorPayload.CharPositionInLine; + this._approximateLineInfo = true; + break; + } + --i; + try + { + priorNode = input.LT(i); + } + catch (ArgumentException) + { + priorNode = null; + } + } + } + else + { + // node created from real token + this._line = payload.Line; + this._charPositionInLine = payload.CharPositionInLine; + } + } + else if (this._node is Tree.ITree) + { + this._line = ((Tree.ITree)this._node).Line; + this._charPositionInLine = ((Tree.ITree)this._node).CharPositionInLine; + if (this._node is CommonTree) + { + this._token = ((CommonTree)this._node).Token; + } + } + else + { + int type = adaptor.GetType(this._node); + string text = adaptor.GetText(this._node); + this._token = new CommonToken(type, text); + } + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/RecognizerSharedState.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/RecognizerSharedState.cs new file mode 100644 index 0000000..2b7c6cf --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/RecognizerSharedState.cs @@ -0,0 +1,186 @@ +/* + * [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 +{ + using System.Collections.Generic; + using CLSCompliant = System.CLSCompliantAttribute; + using ArgumentNullException = System.ArgumentNullException; + + /** <summary> + * The set of fields needed by an abstract recognizer to recognize input + * and recover from errors etc... As a separate state object, it can be + * shared among multiple grammars; e.g., when one grammar imports another. + * </summary> + * + * <remarks> + * These fields are publically visible but the actual state pointer per + * parser is protected. + * </remarks> + */ + public class RecognizerSharedState + { + /** <summary> + * Track the set of token types that can follow any rule invocation. + * Stack grows upwards. When it hits the max, it grows 2x in size + * and keeps going. + * </summary> + */ + //public List<BitSet> following; + public BitSet[] following; + [CLSCompliant( false )] + public int _fsp; + + /** <summary> + * This is true when we see an error and before having successfully + * matched a token. Prevents generation of more than one error message + * per error. + * </summary> + */ + public bool errorRecovery; + + /** <summary> + * The index into the input stream where the last error occurred. + * This is used to prevent infinite loops where an error is found + * but no token is consumed during recovery...another error is found, + * ad naseum. This is a failsafe mechanism to guarantee that at least + * one token/tree node is consumed for two errors. + * </summary> + */ + public int lastErrorIndex; + + /** <summary> + * In lieu of a return value, this indicates that a rule or token + * has failed to match. Reset to false upon valid token match. + * </summary> + */ + public bool failed; + + /** <summary>Did the recognizer encounter a syntax error? Track how many.</summary> */ + public int syntaxErrors; + + /** <summary> + * If 0, no backtracking is going on. Safe to exec actions etc... + * If >0 then it's the level of backtracking. + * </summary> + */ + public int backtracking; + + /** <summary> + * An array[size num rules] of Map<Integer,Integer> that tracks + * the stop token index for each rule. ruleMemo[ruleIndex] is + * the memoization table for ruleIndex. For key ruleStartIndex, you + * get back the stop token for associated rule or MEMO_RULE_FAILED. + * </summary> + * + * <remarks>This is only used if rule memoization is on (which it is by default).</remarks> + */ + public IDictionary<int, int>[] ruleMemo; + + + // LEXER FIELDS (must be in same state object to avoid casting + // constantly in generated code and Lexer object) :( + + + /** <summary> + * The goal of all lexer rules/methods is to create a token object. + * This is an instance variable as multiple rules may collaborate to + * create a single token. nextToken will return this object after + * matching lexer rule(s). If you subclass to allow multiple token + * emissions, then set this to the last token to be matched or + * something nonnull so that the auto token emit mechanism will not + * emit another token. + * </summary> + */ + public IToken token; + + /** <summary> + * What character index in the stream did the current token start at? + * Needed, for example, to get the text for current token. Set at + * the start of nextToken. + * </summary> + */ + public int tokenStartCharIndex; + + /** <summary>The line on which the first character of the token resides</summary> */ + public int tokenStartLine; + + /** <summary>The character position of first character within the line</summary> */ + public int tokenStartCharPositionInLine; + + /** <summary>The channel number for the current token</summary> */ + public int channel; + + /** <summary>The token type for the current token</summary> */ + public int type; + + /** <summary> + * You can set the text for the current token to override what is in + * the input char buffer. Use setText() or can set this instance var. + * </summary> + */ + public string text; + + public RecognizerSharedState() + { + //following = new List<BitSet>( BaseRecognizer.InitialFollowStackSize ); + following = new BitSet[BaseRecognizer.InitialFollowStackSize]; + _fsp = -1; + lastErrorIndex = -1; + tokenStartCharIndex = -1; + } + + public RecognizerSharedState( RecognizerSharedState state ) + { + if (state == null) + throw new ArgumentNullException("state"); + + following = (BitSet[])state.following.Clone(); + _fsp = state._fsp; + errorRecovery = state.errorRecovery; + lastErrorIndex = state.lastErrorIndex; + failed = state.failed; + syntaxErrors = state.syntaxErrors; + backtracking = state.backtracking; + + if ( state.ruleMemo != null ) + ruleMemo = (IDictionary<int, int>[])state.ruleMemo.Clone(); + + token = state.token; + tokenStartCharIndex = state.tokenStartCharIndex; + tokenStartCharPositionInLine = state.tokenStartCharPositionInLine; + channel = state.channel; + type = state.type; + text = state.text; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/TemplateParserRuleReturnScope`2.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/TemplateParserRuleReturnScope`2.cs new file mode 100644 index 0000000..1e3c185 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/TemplateParserRuleReturnScope`2.cs @@ -0,0 +1,60 @@ +/* + * [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 +{ + public class TemplateParserRuleReturnScope<TTemplate, TToken> : ParserRuleReturnScope<TToken>, ITemplateRuleReturnScope<TTemplate>, ITemplateRuleReturnScope + { + private TTemplate _template; + + public TTemplate Template + { + get + { + return _template; + } + + set + { + _template = value; + } + } + + object ITemplateRuleReturnScope.Template + { + get + { + return Template; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/TokenChannels.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/TokenChannels.cs new file mode 100644 index 0000000..429a2c0 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/TokenChannels.cs @@ -0,0 +1,52 @@ +/* + * [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 +{ + public static class TokenChannels + { + /** <summary> + * All tokens go to the parser (unless skip() is called in that rule) + * on a particular "channel". The parser tunes to a particular channel + * so that whitespace etc... can go to the parser on a "hidden" channel. + * </summary> + */ + public const int Default = 0; + + /** <summary> + * Anything on different channel than DEFAULT_CHANNEL is not parsed + * by parser. + * </summary> + */ + public const int Hidden = 99; + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/TokenRewriteStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/TokenRewriteStream.cs new file mode 100644 index 0000000..e9ab4a9 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/TokenRewriteStream.cs @@ -0,0 +1,729 @@ +/* + * [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 +{ + using System.Collections.Generic; + + using ArgumentException = System.ArgumentException; + using Console = System.Console; + using Math = System.Math; + using DebuggerDisplay = System.Diagnostics.DebuggerDisplayAttribute; + using Exception = System.Exception; + using StringBuilder = System.Text.StringBuilder; + using Type = System.Type; + + /** Useful for dumping out the input stream after doing some + * augmentation or other manipulations. + * + * You can insert stuff, replace, and delete chunks. Note that the + * operations are done lazily--only if you convert the buffer to a + * String. This is very efficient because you are not moving data around + * all the time. As the buffer of tokens is converted to strings, the + * toString() method(s) check to see if there is an operation at the + * current index. If so, the operation is done and then normal String + * rendering continues on the buffer. This is like having multiple Turing + * machine instruction streams (programs) operating on a single input tape. :) + * + * Since the operations are done lazily at toString-time, operations do not + * screw up the token index values. That is, an insert operation at token + * index i does not change the index values for tokens i+1..n-1. + * + * Because operations never actually alter the buffer, you may always get + * the original token stream back without undoing anything. Since + * the instructions are queued up, you can easily simulate transactions and + * roll back any changes if there is an error just by removing instructions. + * For example, + * + * CharStream input = new ANTLRFileStream("input"); + * TLexer lex = new TLexer(input); + * TokenRewriteStream tokens = new TokenRewriteStream(lex); + * T parser = new T(tokens); + * parser.startRule(); + * + * Then in the rules, you can execute + * Token t,u; + * ... + * input.insertAfter(t, "text to put after t");} + * input.insertAfter(u, "text after u");} + * System.out.println(tokens.toString()); + * + * Actually, you have to cast the 'input' to a TokenRewriteStream. :( + * + * You can also have multiple "instruction streams" and get multiple + * rewrites from a single pass over the input. Just name the instruction + * streams and use that name again when printing the buffer. This could be + * useful for generating a C file and also its header file--all from the + * same buffer: + * + * tokens.insertAfter("pass1", t, "text to put after t");} + * tokens.insertAfter("pass2", u, "text after u");} + * System.out.println(tokens.toString("pass1")); + * System.out.println(tokens.toString("pass2")); + * + * If you don't use named rewrite streams, a "default" stream is used as + * the first example shows. + */ + [System.Serializable] + [DebuggerDisplay( "TODO: TokenRewriteStream debugger display" )] + public class TokenRewriteStream : CommonTokenStream + { + public const string DEFAULT_PROGRAM_NAME = "default"; + public const int PROGRAM_INIT_SIZE = 100; + public const int MIN_TOKEN_INDEX = 0; + + // Define the rewrite operation hierarchy + + protected class RewriteOperation + { + /** <summary>What index into rewrites List are we?</summary> */ + public int instructionIndex; + /** <summary>Token buffer index.</summary> */ + public int index; + public object text; + // outer + protected TokenRewriteStream stream; + + protected RewriteOperation(TokenRewriteStream stream, int index) + { + this.stream = stream; + this.index = index; + } + + protected RewriteOperation( TokenRewriteStream stream, int index, object text ) + { + this.index = index; + this.text = text; + this.stream = stream; + } + + /** <summary> + * Execute the rewrite operation by possibly adding to the buffer. + * Return the index of the next token to operate on. + * </summary> + */ + public virtual int Execute( StringBuilder buf ) + { + return index; + } + + public override string ToString() + { + string opName = this.GetType().Name; + int dindex = opName.IndexOf( '$' ); + opName = opName.Substring( dindex + 1 ); + return string.Format("<{0}@{1}:\"{2}\">", opName, stream._tokens[index], text); + } + } + + private class InsertBeforeOp : RewriteOperation + { + public InsertBeforeOp( TokenRewriteStream stream, int index, object text ) : + base( stream, index, text ) + { + } + + public override int Execute( StringBuilder buf ) + { + buf.Append( text ); + if (stream._tokens[index].Type != CharStreamConstants.EndOfFile) + buf.Append(stream._tokens[index].Text); + return index + 1; + } + } + + /** <summary> + * I'm going to try replacing range from x..y with (y-x)+1 ReplaceOp + * instructions. + * </summary> + */ + private class ReplaceOp : RewriteOperation + { + public int lastIndex; + public ReplaceOp( TokenRewriteStream stream, int from, int to, object text ) + : base( stream, from, text ) + { + lastIndex = to; + } + + public override int Execute( StringBuilder buf ) + { + if ( text != null ) + { + buf.Append( text ); + } + return lastIndex + 1; + } + + public override string ToString() + { + if (text == null) + { + return string.Format("<DeleteOp@{0}..{1}>", stream._tokens[index], stream._tokens[lastIndex]); + } + + return string.Format("<ReplaceOp@{0}..{1}:\"{2}\">", stream._tokens[index], stream._tokens[lastIndex], text); + } + } + + /** <summary> + * You may have multiple, named streams of rewrite operations. + * I'm calling these things "programs." + * Maps String (name) -> rewrite (List) + * </summary> + */ + protected IDictionary<string, IList<RewriteOperation>> programs = null; + + /** <summary>Map String (program name) -> Integer index</summary> */ + protected IDictionary<string, int> lastRewriteTokenIndexes = null; + + public TokenRewriteStream() + { + Init(); + } + + protected void Init() + { + programs = new Dictionary<string, IList<RewriteOperation>>(); + programs[DEFAULT_PROGRAM_NAME] = new List<RewriteOperation>( PROGRAM_INIT_SIZE ); + lastRewriteTokenIndexes = new Dictionary<string, int>(); + } + + public TokenRewriteStream( ITokenSource tokenSource ) + : base( tokenSource ) + { + Init(); + } + + public TokenRewriteStream( ITokenSource tokenSource, int channel ) + : base( tokenSource, channel ) + { + Init(); + } + + public virtual void Rollback( int instructionIndex ) + { + Rollback( DEFAULT_PROGRAM_NAME, instructionIndex ); + } + + /** <summary> + * Rollback the instruction stream for a program so that + * the indicated instruction (via instructionIndex) is no + * longer in the stream. UNTESTED! + * </summary> + */ + public virtual void Rollback( string programName, int instructionIndex ) + { + IList<RewriteOperation> @is; + if ( programs.TryGetValue( programName, out @is ) && @is != null ) + { + List<RewriteOperation> sublist = new List<RewriteOperation>(); + for ( int i = MIN_TOKEN_INDEX; i <= instructionIndex; i++ ) + sublist.Add( @is[i] ); + + programs[programName] = sublist; + } + } + + public virtual void DeleteProgram() + { + DeleteProgram( DEFAULT_PROGRAM_NAME ); + } + + /** <summary>Reset the program so that no instructions exist</summary> */ + public virtual void DeleteProgram( string programName ) + { + Rollback( programName, MIN_TOKEN_INDEX ); + } + + public virtual void InsertAfter( IToken t, object text ) + { + InsertAfter( DEFAULT_PROGRAM_NAME, t, text ); + } + + public virtual void InsertAfter( int index, object text ) + { + InsertAfter( DEFAULT_PROGRAM_NAME, index, text ); + } + + public virtual void InsertAfter( string programName, IToken t, object text ) + { + InsertAfter( programName, t.TokenIndex, text ); + } + + public virtual void InsertAfter( string programName, int index, object text ) + { + // to insert after, just insert before next index (even if past end) + InsertBefore( programName, index + 1, text ); + } + + public virtual void InsertBefore( IToken t, object text ) + { + InsertBefore( DEFAULT_PROGRAM_NAME, t, text ); + } + + public virtual void InsertBefore( int index, object text ) + { + InsertBefore( DEFAULT_PROGRAM_NAME, index, text ); + } + + public virtual void InsertBefore( string programName, IToken t, object text ) + { + InsertBefore( programName, t.TokenIndex, text ); + } + + public virtual void InsertBefore( string programName, int index, object text ) + { + RewriteOperation op = new InsertBeforeOp( this, index, text ); + IList<RewriteOperation> rewrites = GetProgram( programName ); + op.instructionIndex = rewrites.Count; + rewrites.Add( op ); + } + + public virtual void Replace( int index, object text ) + { + Replace( DEFAULT_PROGRAM_NAME, index, index, text ); + } + + public virtual void Replace( int from, int to, object text ) + { + Replace( DEFAULT_PROGRAM_NAME, from, to, text ); + } + + public virtual void Replace( IToken indexT, object text ) + { + Replace( DEFAULT_PROGRAM_NAME, indexT, indexT, text ); + } + + public virtual void Replace( IToken from, IToken to, object text ) + { + Replace( DEFAULT_PROGRAM_NAME, from, to, text ); + } + + public virtual void Replace( string programName, int from, int to, object text ) + { + if ( from > to || from < 0 || to < 0 || to >= _tokens.Count ) + { + throw new ArgumentException( "replace: range invalid: " + from + ".." + to + "(size=" + _tokens.Count + ")" ); + } + RewriteOperation op = new ReplaceOp( this, from, to, text ); + IList<RewriteOperation> rewrites = GetProgram( programName ); + op.instructionIndex = rewrites.Count; + rewrites.Add( op ); + } + + public virtual void Replace( string programName, IToken from, IToken to, object text ) + { + Replace( programName, + from.TokenIndex, + to.TokenIndex, + text ); + } + + public virtual void Delete( int index ) + { + Delete( DEFAULT_PROGRAM_NAME, index, index ); + } + + public virtual void Delete( int from, int to ) + { + Delete( DEFAULT_PROGRAM_NAME, from, to ); + } + + public virtual void Delete( IToken indexT ) + { + Delete( DEFAULT_PROGRAM_NAME, indexT, indexT ); + } + + public virtual void Delete( IToken from, IToken to ) + { + Delete( DEFAULT_PROGRAM_NAME, from, to ); + } + + public virtual void Delete( string programName, int from, int to ) + { + Replace( programName, from, to, null ); + } + + public virtual void Delete( string programName, IToken from, IToken to ) + { + Replace( programName, from, to, null ); + } + + public virtual int GetLastRewriteTokenIndex() + { + return GetLastRewriteTokenIndex( DEFAULT_PROGRAM_NAME ); + } + + protected virtual int GetLastRewriteTokenIndex( string programName ) + { + int value; + if ( lastRewriteTokenIndexes.TryGetValue( programName, out value ) ) + return value; + + return -1; + } + + protected virtual void SetLastRewriteTokenIndex( string programName, int i ) + { + lastRewriteTokenIndexes[programName] = i; + } + + protected virtual IList<RewriteOperation> GetProgram( string name ) + { + IList<RewriteOperation> @is; + if ( !programs.TryGetValue( name, out @is ) || @is == null ) + { + @is = InitializeProgram( name ); + } + return @is; + } + + private IList<RewriteOperation> InitializeProgram( string name ) + { + IList<RewriteOperation> @is = new List<RewriteOperation>( PROGRAM_INIT_SIZE ); + programs[name] = @is; + return @is; + } + + public virtual string ToOriginalString() + { + Fill(); + return ToOriginalString( MIN_TOKEN_INDEX, Count - 1 ); + } + + public virtual string ToOriginalString( int start, int end ) + { + StringBuilder buf = new StringBuilder(); + for ( int i = start; i >= MIN_TOKEN_INDEX && i <= end && i < _tokens.Count; i++ ) + { + if (Get(i).Type != CharStreamConstants.EndOfFile) + buf.Append(Get(i).Text); + } + return buf.ToString(); + } + + public override string ToString() + { + Fill(); + return ToString( MIN_TOKEN_INDEX, Count - 1 ); + } + + public virtual string ToString( string programName ) + { + Fill(); + return ToString(programName, MIN_TOKEN_INDEX, Count - 1); + } + + public override string ToString( int start, int end ) + { + return ToString( DEFAULT_PROGRAM_NAME, start, end ); + } + + public virtual string ToString( string programName, int start, int end ) + { + IList<RewriteOperation> rewrites; + if ( !programs.TryGetValue( programName, out rewrites ) ) + rewrites = null; + + // ensure start/end are in range + if ( end > _tokens.Count - 1 ) + end = _tokens.Count - 1; + if ( start < 0 ) + start = 0; + + if ( rewrites == null || rewrites.Count == 0 ) + { + return ToOriginalString( start, end ); // no instructions to execute + } + StringBuilder buf = new StringBuilder(); + + // First, optimize instruction stream + IDictionary<int, RewriteOperation> indexToOp = ReduceToSingleOperationPerIndex( rewrites ); + + // Walk buffer, executing instructions and emitting tokens + int i = start; + while ( i <= end && i < _tokens.Count ) + { + RewriteOperation op; + bool exists = indexToOp.TryGetValue( i, out op ); + + if ( exists ) + { + // remove so any left have index size-1 + indexToOp.Remove( i ); + } + + if ( !exists || op == null ) + { + IToken t = _tokens[i]; + // no operation at that index, just dump token + if (t.Type != CharStreamConstants.EndOfFile) + buf.Append(t.Text); + i++; // move to next token + } + else + { + i = op.Execute( buf ); // execute operation and skip + } + } + + // include stuff after end if it's last index in buffer + // So, if they did an insertAfter(lastValidIndex, "foo"), include + // foo if end==lastValidIndex. + if ( end == _tokens.Count - 1 ) + { + // Scan any remaining operations after last token + // should be included (they will be inserts). + foreach ( RewriteOperation op in indexToOp.Values ) + { + if ( op.index >= _tokens.Count - 1 ) + buf.Append( op.text ); + } + } + return buf.ToString(); + } + + /** We need to combine operations and report invalid operations (like + * overlapping replaces that are not completed nested). Inserts to + * same index need to be combined etc... Here are the cases: + * + * I.i.u I.j.v leave alone, nonoverlapping + * I.i.u I.i.v combine: Iivu + * + * R.i-j.u R.x-y.v | i-j in x-y delete first R + * R.i-j.u R.i-j.v delete first R + * R.i-j.u R.x-y.v | x-y in i-j ERROR + * R.i-j.u R.x-y.v | boundaries overlap ERROR + * + * Delete special case of replace (text==null): + * D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) + * + * I.i.u R.x-y.v | i in (x+1)-y delete I (since insert before + * we're not deleting i) + * I.i.u R.x-y.v | i not in (x+1)-y leave alone, nonoverlapping + * R.x-y.v I.i.u | i in x-y ERROR + * R.x-y.v I.x.u R.x-y.uv (combine, delete I) + * R.x-y.v I.i.u | i not in x-y leave alone, nonoverlapping + * + * I.i.u = insert u before op @ index i + * R.x-y.u = replace x-y indexed tokens with u + * + * First we need to examine replaces. For any replace op: + * + * 1. wipe out any insertions before op within that range. + * 2. Drop any replace op before that is contained completely within + * that range. + * 3. Throw exception upon boundary overlap with any previous replace. + * + * Then we can deal with inserts: + * + * 1. for any inserts to same index, combine even if not adjacent. + * 2. for any prior replace with same left boundary, combine this + * insert with replace and delete this replace. + * 3. throw exception if index in same range as previous replace + * + * Don't actually delete; make op null in list. Easier to walk list. + * Later we can throw as we add to index -> op map. + * + * Note that I.2 R.2-2 will wipe out I.2 even though, technically, the + * inserted stuff would be before the replace range. But, if you + * add tokens in front of a method body '{' and then delete the method + * body, I think the stuff before the '{' you added should disappear too. + * + * Return a map from token index to operation. + */ + protected virtual IDictionary<int, RewriteOperation> ReduceToSingleOperationPerIndex( IList<RewriteOperation> rewrites ) + { + //System.out.println("rewrites="+rewrites); + + // WALK REPLACES + for ( int i = 0; i < rewrites.Count; i++ ) + { + RewriteOperation op = rewrites[i]; + if ( op == null ) + continue; + if ( !( op is ReplaceOp ) ) + continue; + ReplaceOp rop = (ReplaceOp)rewrites[i]; + // Wipe prior inserts within range + var inserts = GetKindOfOps( rewrites, typeof( InsertBeforeOp ), i ); + for ( int j = 0; j < inserts.Count; j++ ) + { + InsertBeforeOp iop = (InsertBeforeOp)inserts[j]; + if (iop.index == rop.index) + { + // E.g., insert before 2, delete 2..2; update replace + // text to include insert before, kill insert + rewrites[iop.instructionIndex] = null; + rop.text = iop.text.ToString() + (rop.text != null ? rop.text.ToString() : string.Empty); + } + else if (iop.index > rop.index && iop.index <= rop.lastIndex) + { + // delete insert as it's a no-op. + rewrites[iop.instructionIndex] = null; + } + } + // Drop any prior replaces contained within + var prevReplaces = GetKindOfOps( rewrites, typeof( ReplaceOp ), i ); + for ( int j = 0; j < prevReplaces.Count; j++ ) + { + ReplaceOp prevRop = (ReplaceOp)prevReplaces[j]; + if ( prevRop.index >= rop.index && prevRop.lastIndex <= rop.lastIndex ) + { + // delete replace as it's a no-op. + rewrites[prevRop.instructionIndex] = null; + continue; + } + // throw exception unless disjoint or identical + bool disjoint = + prevRop.lastIndex < rop.index || prevRop.index > rop.lastIndex; + bool same = + prevRop.index == rop.index && prevRop.lastIndex == rop.lastIndex; + // Delete special case of replace (text==null): + // D.i-j.u D.x-y.v | boundaries overlap combine to max(min)..max(right) + if (prevRop.text == null && rop.text == null && !disjoint) + { + //System.out.println("overlapping deletes: "+prevRop+", "+rop); + rewrites[prevRop.instructionIndex] = null; // kill first delete + rop.index = Math.Min(prevRop.index, rop.index); + rop.lastIndex = Math.Max(prevRop.lastIndex, rop.lastIndex); + Console.WriteLine("new rop " + rop); + } + else if ( !disjoint && !same ) + { + throw new ArgumentException( "replace op boundaries of " + rop + + " overlap with previous " + prevRop ); + } + } + } + + // WALK INSERTS + for ( int i = 0; i < rewrites.Count; i++ ) + { + RewriteOperation op = (RewriteOperation)rewrites[i]; + if ( op == null ) + continue; + if ( !( op is InsertBeforeOp ) ) + continue; + InsertBeforeOp iop = (InsertBeforeOp)rewrites[i]; + // combine current insert with prior if any at same index + var prevInserts = GetKindOfOps( rewrites, typeof( InsertBeforeOp ), i ); + for ( int j = 0; j < prevInserts.Count; j++ ) + { + InsertBeforeOp prevIop = (InsertBeforeOp)prevInserts[j]; + if ( prevIop.index == iop.index ) + { // combine objects + // convert to strings...we're in process of toString'ing + // whole token buffer so no lazy eval issue with any templates + iop.text = CatOpText( iop.text, prevIop.text ); + // delete redundant prior insert + rewrites[prevIop.instructionIndex] = null; + } + } + // look for replaces where iop.index is in range; error + var prevReplaces = GetKindOfOps( rewrites, typeof( ReplaceOp ), i ); + for ( int j = 0; j < prevReplaces.Count; j++ ) + { + ReplaceOp rop = (ReplaceOp)prevReplaces[j]; + if ( iop.index == rop.index ) + { + rop.text = CatOpText( iop.text, rop.text ); + rewrites[i] = null; // delete current insert + continue; + } + if ( iop.index >= rop.index && iop.index <= rop.lastIndex ) + { + throw new ArgumentException( "insert op " + iop + + " within boundaries of previous " + rop ); + } + } + } + // System.out.println("rewrites after="+rewrites); + IDictionary<int, RewriteOperation> m = new Dictionary<int, RewriteOperation>(); + for ( int i = 0; i < rewrites.Count; i++ ) + { + RewriteOperation op = (RewriteOperation)rewrites[i]; + if ( op == null ) + continue; // ignore deleted ops + + RewriteOperation existing; + if ( m.TryGetValue( op.index, out existing ) && existing != null ) + { + throw new Exception( "should only be one op per index" ); + } + m[op.index] = op; + } + //System.out.println("index to op: "+m); + return m; + } + + protected virtual string CatOpText( object a, object b ) + { + return string.Concat( a, b ); + } + protected virtual IList<RewriteOperation> GetKindOfOps( IList<RewriteOperation> rewrites, Type kind ) + { + return GetKindOfOps( rewrites, kind, rewrites.Count ); + } + + /** <summary>Get all operations before an index of a particular kind</summary> */ + protected virtual IList<RewriteOperation> GetKindOfOps( IList<RewriteOperation> rewrites, Type kind, int before ) + { + IList<RewriteOperation> ops = new List<RewriteOperation>(); + for ( int i = 0; i < before && i < rewrites.Count; i++ ) + { + RewriteOperation op = rewrites[i]; + if ( op == null ) + continue; // ignore deleted + if ( op.GetType() == kind ) + ops.Add( op ); + } + return ops; + } + + public virtual string ToDebugString() + { + return ToDebugString( MIN_TOKEN_INDEX, Count - 1 ); + } + + public virtual string ToDebugString( int start, int end ) + { + StringBuilder buf = new StringBuilder(); + for ( int i = start; i >= MIN_TOKEN_INDEX && i <= end && i < _tokens.Count; i++ ) + { + buf.Append( Get( i ) ); + } + return buf.ToString(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/TokenTypes.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/TokenTypes.cs new file mode 100644 index 0000000..29692ce --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/TokenTypes.cs @@ -0,0 +1,46 @@ +/* + * [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 +{ + public static class TokenTypes + { + public const int EndOfFile = CharStreamConstants.EndOfFile; + public const int Invalid = 0; + public const int EndOfRule = 1; + /** <summary>imaginary tree navigation type; traverse "get child" link</summary> */ + public const int Down = 2; + /** <summary>imaginary tree navigation type; finish with a child list</summary> */ + public const int Up = 3; + public const int Min = Up + 1; + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tokens.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tokens.cs new file mode 100644 index 0000000..a736f2f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tokens.cs @@ -0,0 +1,44 @@ +/* + * [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 +{ + public static class Tokens + { + /** <summary> + * In an action, a lexer rule can set token to this SKIP_TOKEN and ANTLR + * will avoid creating a token for this symbol and try to fetch another. + * </summary> + */ + public static readonly IToken Skip = new CommonToken( TokenTypes.Invalid ); + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/AntlrRuntime_BaseTreeDebugView.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/AntlrRuntime_BaseTreeDebugView.cs new file mode 100644 index 0000000..3346e36 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/AntlrRuntime_BaseTreeDebugView.cs @@ -0,0 +1,60 @@ +/* + * [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.Tree +{ + using System.Diagnostics; + + internal sealed class AntlrRuntime_BaseTreeDebugView + { + private readonly BaseTree _tree; + + public AntlrRuntime_BaseTreeDebugView(BaseTree tree) + { + _tree = tree; + } + + [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)] + public ITree[] Children + { + get + { + if (_tree == null || _tree.Children == null) + return null; + + ITree[] children = new ITree[_tree.Children.Count]; + _tree.Children.CopyTo(children, 0); + return children; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/AstTreeRuleReturnScope`2.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/AstTreeRuleReturnScope`2.cs new file mode 100644 index 0000000..cc8cb6f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/AstTreeRuleReturnScope`2.cs @@ -0,0 +1,60 @@ +/* + * [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.Tree +{ + public class AstTreeRuleReturnScope<TOutputTree, TInputTree> : TreeRuleReturnScope<TInputTree>, IAstRuleReturnScope<TOutputTree>, IAstRuleReturnScope + { + private TOutputTree _tree; + + public TOutputTree Tree + { + get + { + return _tree; + } + + set + { + _tree = value; + } + } + + object IAstRuleReturnScope.Tree + { + get + { + return Tree; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTree.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTree.cs new file mode 100644 index 0000000..79f3d97 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTree.cs @@ -0,0 +1,532 @@ +/* + * [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.Tree +{ + using System; + using System.Collections.Generic; + + using StringBuilder = System.Text.StringBuilder; + + /** <summary> + * A generic tree implementation with no payload. You must subclass to + * actually have any user data. ANTLR v3 uses a list of children approach + * instead of the child-sibling approach in v2. A flat tree (a list) is + * an empty node whose children represent the list. An empty, but + * non-null node is called "nil". + * </summary> + */ + [System.Serializable] + [System.Diagnostics.DebuggerTypeProxy(typeof(AntlrRuntime_BaseTreeDebugView))] + public abstract class BaseTree : ITree + { + private IList<ITree> _children; + + public BaseTree() + { + } + + /** <summary> + * Create a new node from an existing node does nothing for BaseTree + * as there are no fields other than the children list, which cannot + * be copied as the children are not considered part of this node. + * </summary> + */ + public BaseTree( ITree node ) + { + } + + /** <summary> + * Get the children internal List; note that if you directly mess with + * the list, do so at your own risk. + * </summary> + */ + public virtual IList<ITree> Children + { + get + { + return _children; + } + + private set + { + _children = value; + } + } + + #region ITree Members + + public virtual int ChildCount + { + get + { + if ( Children == null ) + return 0; + + return Children.Count; + } + } + + /** <summary>BaseTree doesn't track parent pointers.</summary> */ + public virtual ITree Parent + { + get + { + return null; + } + set + { + } + } + + /** <summary>BaseTree doesn't track child indexes.</summary> */ + public virtual int ChildIndex + { + get + { + return 0; + } + set + { + } + } + + public virtual bool IsNil + { + get + { + return false; + } + } + + public abstract int TokenStartIndex + { + get; + set; + } + + public abstract int TokenStopIndex + { + get; + set; + } + + public abstract int Type + { + get; + set; + } + + public abstract string Text + { + get; + set; + } + + public virtual int Line + { + get; + set; + } + + public virtual int CharPositionInLine + { + get; + set; + } + + #endregion + + public virtual ITree GetChild( int i ) + { + if (i < 0) + throw new ArgumentOutOfRangeException(); + + if ( Children == null || i >= Children.Count ) + return null; + + return Children[i]; + } + + public virtual ITree GetFirstChildWithType( int type ) + { + foreach ( ITree child in Children ) + { + if ( child.Type == type ) + return child; + } + + return null; + } + + /** <summary>Add t as child of this node.</summary> + * + * <remarks> + * Warning: if t has no children, but child does + * and child isNil then this routine moves children to t via + * t.children = child.children; i.e., without copying the array. + * </remarks> + */ + public virtual void AddChild( ITree t ) + { + //System.out.println("add child "+t.toStringTree()+" "+this.toStringTree()); + //System.out.println("existing children: "+children); + if ( t == null ) + { + return; // do nothing upon addChild(null) + } + if ( t.IsNil ) + { + // t is an empty node possibly with children + BaseTree childTree = t as BaseTree; + if ( childTree != null && this.Children != null && this.Children == childTree.Children ) + { + throw new Exception( "attempt to add child list to itself" ); + } + // just add all of childTree's children to this + if ( t.ChildCount > 0 ) + { + if ( this.Children != null || childTree == null ) + { + if ( this.Children == null ) + this.Children = CreateChildrenList(); + + // must copy, this has children already + int n = t.ChildCount; + for ( int i = 0; i < n; i++ ) + { + ITree c = t.GetChild( i ); + this.Children.Add( c ); + // handle double-link stuff for each child of nil root + c.Parent = this; + c.ChildIndex = Children.Count - 1; + } + } + else + { + // no children for this but t is a BaseTree with children; + // just set pointer call general freshener routine + this.Children = childTree.Children; + this.FreshenParentAndChildIndexes(); + } + } + } + else + { + // child is not nil (don't care about children) + if ( Children == null ) + { + Children = CreateChildrenList(); // create children list on demand + } + Children.Add( t ); + t.Parent = this; + t.ChildIndex = Children.Count - 1; + } + // System.out.println("now children are: "+children); + } + + /** <summary>Add all elements of kids list as children of this node</summary> */ + public virtual void AddChildren( IEnumerable<ITree> kids ) + { + if (kids == null) + throw new ArgumentNullException("kids"); + + foreach ( ITree t in kids ) + AddChild( t ); + } + + public virtual void SetChild( int i, ITree t ) + { + if (i < 0) + throw new ArgumentOutOfRangeException("i"); + + if ( t == null ) + { + return; + } + if ( t.IsNil ) + { + throw new ArgumentException( "Can't set single child to a list" ); + } + if ( Children == null ) + { + Children = CreateChildrenList(); + } + Children[i] = t; + t.Parent = this; + t.ChildIndex = i; + } + + public virtual object DeleteChild( int i ) + { + if (i < 0) + throw new ArgumentOutOfRangeException("i"); + if (i >= ChildCount) + throw new ArgumentException(); + + if ( Children == null ) + return null; + + ITree killed = Children[i]; + Children.RemoveAt( i ); + // walk rest and decrement their child indexes + this.FreshenParentAndChildIndexes( i ); + return killed; + } + + /** <summary> + * Delete children from start to stop and replace with t even if t is + * a list (nil-root tree). num of children can increase or decrease. + * For huge child lists, inserting children can force walking rest of + * children to set their childindex; could be slow. + * </summary> + */ + public virtual void ReplaceChildren( int startChildIndex, int stopChildIndex, object t ) + { + if (startChildIndex < 0) + throw new ArgumentOutOfRangeException(); + if (stopChildIndex < 0) + throw new ArgumentOutOfRangeException(); + if (t == null) + throw new ArgumentNullException("t"); + if (stopChildIndex < startChildIndex) + throw new ArgumentException(); + + /* + System.out.println("replaceChildren "+startChildIndex+", "+stopChildIndex+ + " with "+((BaseTree)t).toStringTree()); + System.out.println("in="+toStringTree()); + */ + if ( Children == null ) + { + throw new ArgumentException( "indexes invalid; no children in list" ); + } + int replacingHowMany = stopChildIndex - startChildIndex + 1; + int replacingWithHowMany; + ITree newTree = (ITree)t; + IList<ITree> newChildren = null; + // normalize to a list of children to add: newChildren + if ( newTree.IsNil ) + { + BaseTree baseTree = newTree as BaseTree; + if ( baseTree != null && baseTree.Children != null ) + { + newChildren = baseTree.Children; + } + else + { + newChildren = CreateChildrenList(); + int n = newTree.ChildCount; + for ( int i = 0; i < n; i++ ) + newChildren.Add( newTree.GetChild( i ) ); + } + } + else + { + newChildren = new List<ITree>( 1 ); + newChildren.Add( newTree ); + } + replacingWithHowMany = newChildren.Count; + int numNewChildren = newChildren.Count; + int delta = replacingHowMany - replacingWithHowMany; + // if same number of nodes, do direct replace + if ( delta == 0 ) + { + int j = 0; // index into new children + for ( int i = startChildIndex; i <= stopChildIndex; i++ ) + { + ITree child = newChildren[j]; + Children[i] = child; + child.Parent = this; + child.ChildIndex = i; + j++; + } + } + else if ( delta > 0 ) + { + // fewer new nodes than there were + // set children and then delete extra + for ( int j = 0; j < numNewChildren; j++ ) + { + Children[startChildIndex + j] = newChildren[j]; + } + int indexToDelete = startChildIndex + numNewChildren; + for ( int c = indexToDelete; c <= stopChildIndex; c++ ) + { + // delete same index, shifting everybody down each time + Children.RemoveAt( indexToDelete ); + } + FreshenParentAndChildIndexes( startChildIndex ); + } + else + { + // more new nodes than were there before + // fill in as many children as we can (replacingHowMany) w/o moving data + for ( int j = 0; j < replacingHowMany; j++ ) + { + Children[startChildIndex + j] = newChildren[j]; + } + int numToInsert = replacingWithHowMany - replacingHowMany; + for ( int j = replacingHowMany; j < replacingWithHowMany; j++ ) + { + Children.Insert( startChildIndex + j, newChildren[j] ); + } + FreshenParentAndChildIndexes( startChildIndex ); + } + //System.out.println("out="+toStringTree()); + } + + /** <summary>Override in a subclass to change the impl of children list</summary> */ + protected virtual IList<ITree> CreateChildrenList() + { + return new List<ITree>(); + } + + /** <summary>Set the parent and child index values for all child of t</summary> */ + public virtual void FreshenParentAndChildIndexes() + { + FreshenParentAndChildIndexes( 0 ); + } + + public virtual void FreshenParentAndChildIndexes( int offset ) + { + int n = ChildCount; + for ( int c = offset; c < n; c++ ) + { + ITree child = GetChild( c ); + child.ChildIndex = c; + child.Parent = this; + } + } + + public virtual void SanityCheckParentAndChildIndexes() + { + SanityCheckParentAndChildIndexes( null, -1 ); + } + + public virtual void SanityCheckParentAndChildIndexes( ITree parent, int i ) + { + if ( parent != this.Parent ) + { + throw new InvalidOperationException( "parents don't match; expected " + parent + " found " + this.Parent ); + } + if ( i != this.ChildIndex ) + { + throw new InvalidOperationException( "child indexes don't match; expected " + i + " found " + this.ChildIndex ); + } + int n = this.ChildCount; + for ( int c = 0; c < n; c++ ) + { + BaseTree child = (BaseTree)this.GetChild( c ); + child.SanityCheckParentAndChildIndexes( this, c ); + } + } + + /** <summary>Walk upwards looking for ancestor with this token type.</summary> */ + public virtual bool HasAncestor( int ttype ) + { + return GetAncestor( ttype ) != null; + } + + /** <summary>Walk upwards and get first ancestor with this token type.</summary> */ + public virtual ITree GetAncestor( int ttype ) + { + ITree t = this; + t = t.Parent; + while ( t != null ) + { + if ( t.Type == ttype ) + return t; + t = t.Parent; + } + return null; + } + + /** <summary> + * Return a list of all ancestors of this node. The first node of + * list is the root and the last is the parent of this node. + * </summary> + */ + public virtual IList<ITree> GetAncestors() + { + if ( Parent == null ) + return null; + + List<ITree> ancestors = new List<ITree>(); + ITree t = this; + t = t.Parent; + while ( t != null ) + { + ancestors.Insert( 0, t ); // insert at start + t = t.Parent; + } + return ancestors; + } + + /** <summary>Print out a whole tree not just a node</summary> */ + public virtual string ToStringTree() + { + if ( Children == null || Children.Count == 0 ) + { + return this.ToString(); + } + StringBuilder buf = new StringBuilder(); + if ( !IsNil ) + { + buf.Append( "(" ); + buf.Append( this.ToString() ); + buf.Append( ' ' ); + } + for ( int i = 0; Children != null && i < Children.Count; i++ ) + { + ITree t = Children[i]; + if ( i > 0 ) + { + buf.Append( ' ' ); + } + buf.Append( t.ToStringTree() ); + } + if ( !IsNil ) + { + buf.Append( ")" ); + } + return buf.ToString(); + } + + /** <summary>Override to say how a node (not a tree) should look as text</summary> */ + public override abstract string ToString(); + + #region Tree Members + public abstract ITree DupNode(); + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTreeAdaptor.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTreeAdaptor.cs new file mode 100644 index 0000000..d77e031 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BaseTreeAdaptor.cs @@ -0,0 +1,517 @@ +/* + * [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.Tree +{ + using System.Collections.Generic; + + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using IDictionary = System.Collections.IDictionary; + using NotSupportedException = System.NotSupportedException; + + /** <summary>A TreeAdaptor that works with any Tree implementation.</summary> */ + public abstract class BaseTreeAdaptor : ITreeAdaptor + { + /** <summary> + * System.identityHashCode() is not always unique; we have to + * track ourselves. That's ok, it's only for debugging, though it's + * expensive: we have to create a hashtable with all tree nodes in it. + * </summary> + */ + protected IDictionary<object, int> treeToUniqueIDMap; + protected int uniqueNodeID = 1; + + public virtual object Nil() + { + return Create( null ); + } + + /** <summary> + * Create tree node that holds the start and stop tokens associated + * with an error. + * </summary> + * + * <remarks> + * If you specify your own kind of tree nodes, you will likely have to + * override this method. CommonTree returns Token.INVALID_TOKEN_TYPE + * if no token payload but you might have to set token type for diff + * node type. + * + * You don't have to subclass CommonErrorNode; you will likely need to + * subclass your own tree node class to avoid class cast exception. + * </remarks> + */ + public virtual object ErrorNode( ITokenStream input, IToken start, IToken stop, + RecognitionException e ) + { + CommonErrorNode t = new CommonErrorNode( input, start, stop, e ); + //System.out.println("returning error node '"+t+"' @index="+input.index()); + return t; + } + + public virtual bool IsNil( object tree ) + { + return ( (ITree)tree ).IsNil; + } + + public virtual object DupNode(int type, object treeNode) + { + object t = DupNode(treeNode); + SetType(t, type); + return t; + } + + public virtual object DupNode(object treeNode, string text) + { + object t = DupNode(treeNode); + SetText(t, text); + return t; + } + + public virtual object DupNode(int type, object treeNode, string text) + { + object t = DupNode(treeNode); + SetType(t, type); + SetText(t, text); + return t; + } + + public virtual object DupTree( object tree ) + { + return DupTree( tree, null ); + } + + /** <summary> + * This is generic in the sense that it will work with any kind of + * tree (not just ITree interface). It invokes the adaptor routines + * not the tree node routines to do the construction. + * </summary> + */ + public virtual object DupTree( object t, object parent ) + { + if ( t == null ) + { + return null; + } + object newTree = DupNode( t ); + // ensure new subtree root has parent/child index set + SetChildIndex( newTree, GetChildIndex( t ) ); // same index in new tree + SetParent( newTree, parent ); + int n = GetChildCount( t ); + for ( int i = 0; i < n; i++ ) + { + object child = GetChild( t, i ); + object newSubTree = DupTree( child, t ); + AddChild( newTree, newSubTree ); + } + return newTree; + } + + /** <summary> + * Add a child to the tree t. If child is a flat tree (a list), make all + * in list children of t. Warning: if t has no children, but child does + * and child isNil then you can decide it is ok to move children to t via + * t.children = child.children; i.e., without copying the array. Just + * make sure that this is consistent with have the user will build + * ASTs. + * </summary> + */ + public virtual void AddChild( object t, object child ) + { + if ( t != null && child != null ) + { + ( (ITree)t ).AddChild( (ITree)child ); + } + } + + /** <summary> + * If oldRoot is a nil root, just copy or move the children to newRoot. + * If not a nil root, make oldRoot a child of newRoot. + * </summary> + * + * <remarks> + * old=^(nil a b c), new=r yields ^(r a b c) + * old=^(a b c), new=r yields ^(r ^(a b c)) + * + * If newRoot is a nil-rooted single child tree, use the single + * child as the new root node. + * + * old=^(nil a b c), new=^(nil r) yields ^(r a b c) + * old=^(a b c), new=^(nil r) yields ^(r ^(a b c)) + * + * If oldRoot was null, it's ok, just return newRoot (even if isNil). + * + * old=null, new=r yields r + * old=null, new=^(nil r) yields ^(nil r) + * + * Return newRoot. Throw an exception if newRoot is not a + * simple node or nil root with a single child node--it must be a root + * node. If newRoot is ^(nil x) return x as newRoot. + * + * Be advised that it's ok for newRoot to point at oldRoot's + * children; i.e., you don't have to copy the list. We are + * constructing these nodes so we should have this control for + * efficiency. + * </remarks> + */ + public virtual object BecomeRoot( object newRoot, object oldRoot ) + { + //System.out.println("becomeroot new "+newRoot.toString()+" old "+oldRoot); + ITree newRootTree = (ITree)newRoot; + ITree oldRootTree = (ITree)oldRoot; + if ( oldRoot == null ) + { + return newRoot; + } + // handle ^(nil real-node) + if ( newRootTree.IsNil ) + { + int nc = newRootTree.ChildCount; + if ( nc == 1 ) + newRootTree = (ITree)newRootTree.GetChild( 0 ); + else if ( nc > 1 ) + { + // TODO: make tree run time exceptions hierarchy + throw new Exception( "more than one node as root (TODO: make exception hierarchy)" ); + } + } + // add oldRoot to newRoot; addChild takes care of case where oldRoot + // is a flat list (i.e., nil-rooted tree). All children of oldRoot + // are added to newRoot. + newRootTree.AddChild( oldRootTree ); + return newRootTree; + } + + /** <summary>Transform ^(nil x) to x and nil to null</summary> */ + public virtual object RulePostProcessing( object root ) + { + //System.out.println("rulePostProcessing: "+((Tree)root).toStringTree()); + ITree r = (ITree)root; + if ( r != null && r.IsNil ) + { + if ( r.ChildCount == 0 ) + { + r = null; + } + else if ( r.ChildCount == 1 ) + { + r = (ITree)r.GetChild( 0 ); + // whoever invokes rule will set parent and child index + r.Parent = null; + r.ChildIndex = -1; + } + } + return r; + } + + public virtual object BecomeRoot( IToken newRoot, object oldRoot ) + { + return BecomeRoot( Create( newRoot ), oldRoot ); + } + + public virtual object Create( int tokenType, IToken fromToken ) + { + fromToken = CreateToken( fromToken ); + fromToken.Type = tokenType; + object t = Create( fromToken ); + return t; + } + + public virtual object Create( int tokenType, IToken fromToken, string text ) + { + if ( fromToken == null ) + return Create( tokenType, text ); + + fromToken = CreateToken( fromToken ); + fromToken.Type = tokenType; + fromToken.Text = text; + object result = Create(fromToken); + return result; + } + + public virtual object Create(IToken fromToken, string text) + { + if (fromToken == null) + throw new ArgumentNullException("fromToken"); + + fromToken = CreateToken(fromToken); + fromToken.Text = text; + object result = Create(fromToken); + return result; + } + + public virtual object Create( int tokenType, string text ) + { + IToken fromToken = CreateToken( tokenType, text ); + object t = Create( fromToken ); + return t; + } + + public virtual int GetType( object t ) + { + ITree tree = GetTree(t); + if (tree == null) + return TokenTypes.Invalid; + + return tree.Type; + } + + public virtual void SetType( object t, int type ) + { + throw new NotSupportedException( "don't know enough about Tree node" ); + } + + public virtual string GetText( object t ) + { + ITree tree = GetTree(t); + if (tree == null) + return null; + + return tree.Text; + } + + public virtual void SetText( object t, string text ) + { + throw new NotSupportedException( "don't know enough about Tree node" ); + } + + public virtual object GetChild( object t, int i ) + { + ITree tree = GetTree(t); + if (tree == null) + return null; + + return tree.GetChild(i); + } + + public virtual void SetChild( object t, int i, object child ) + { + ITree tree = GetTree(t); + if (tree == null) + return; + + ITree childTree = GetTree(child); + tree.SetChild(i, childTree); + } + + public virtual object DeleteChild( object t, int i ) + { + return ( (ITree)t ).DeleteChild( i ); + } + + public virtual int GetChildCount( object t ) + { + ITree tree = GetTree(t); + if (tree == null) + return 0; + + return tree.ChildCount; + } + + public virtual int GetUniqueID( object node ) + { + if ( treeToUniqueIDMap == null ) + { + treeToUniqueIDMap = new Dictionary<object, int>(); + } + int id; + if ( treeToUniqueIDMap.TryGetValue( node, out id ) ) + return id; + + id = uniqueNodeID; + treeToUniqueIDMap[node] = id; + uniqueNodeID++; + return id; + // GC makes these nonunique: + // return System.identityHashCode(node); + } + + /** <summary> + * Tell me how to create a token for use with imaginary token nodes. + * For example, there is probably no input symbol associated with imaginary + * token DECL, but you need to create it as a payload or whatever for + * the DECL node as in ^(DECL type ID). + * </summary> + * + * <remarks> + * If you care what the token payload objects' type is, you should + * override this method and any other createToken variant. + * </remarks> + */ + public abstract IToken CreateToken( int tokenType, string text ); + + /** <summary> + * Tell me how to create a token for use with imaginary token nodes. + * For example, there is probably no input symbol associated with imaginary + * token DECL, but you need to create it as a payload or whatever for + * the DECL node as in ^(DECL type ID). + * </summary> + * + * <remarks> + * This is a variant of createToken where the new token is derived from + * an actual real input token. Typically this is for converting '{' + * tokens to BLOCK etc... You'll see + * + * r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ; + * + * If you care what the token payload objects' type is, you should + * override this method and any other createToken variant. + * </remarks> + */ + public abstract IToken CreateToken( IToken fromToken ); + + public abstract object Create( IToken payload ); + + /** <summary> + * Duplicate a node. This is part of the factory; + * override if you want another kind of node to be built. + * </summary> + * + * <remarks> + * I could use reflection to prevent having to override this + * but reflection is slow. + * </remarks> + */ + public virtual object DupNode(object treeNode) + { + ITree tree = GetTree(treeNode); + if (tree == null) + return null; + + return tree.DupNode(); + } + + public abstract IToken GetToken( object t ); + + /** <summary> + * Track start/stop token for subtree root created for a rule. + * Only works with Tree nodes. For rules that match nothing, + * seems like this will yield start=i and stop=i-1 in a nil node. + * Might be useful info so I'll not force to be i..i. + * </summary> + */ + public virtual void SetTokenBoundaries(object t, IToken startToken, IToken stopToken) + { + ITree tree = GetTree(t); + if (tree == null) + return; + + int start = 0; + int stop = 0; + + if (startToken != null) + start = startToken.TokenIndex; + if (stopToken != null) + stop = stopToken.TokenIndex; + + tree.TokenStartIndex = start; + tree.TokenStopIndex = stop; + } + + public virtual int GetTokenStartIndex(object t) + { + ITree tree = GetTree(t); + if (tree == null) + return -1; + + return tree.TokenStartIndex; + } + + public virtual int GetTokenStopIndex(object t) + { + ITree tree = GetTree(t); + if (tree == null) + return -1; + + return tree.TokenStopIndex; + } + + public virtual object GetParent(object t) + { + ITree tree = GetTree(t); + if (tree == null) + return null; + + return tree.Parent; + } + + public virtual void SetParent(object t, object parent) + { + ITree tree = GetTree(t); + if (tree == null) + return; + + ITree parentTree = GetTree(parent); + tree.Parent = parentTree; + } + + public virtual int GetChildIndex(object t) + { + ITree tree = GetTree(t); + if (tree == null) + return 0; + + return tree.ChildIndex; + } + + public virtual void SetChildIndex(object t, int index) + { + ITree tree = GetTree(t); + if (tree == null) + return; + + tree.ChildIndex = index; + } + + public virtual void ReplaceChildren(object parent, int startChildIndex, int stopChildIndex, object t) + { + ITree tree = GetTree(parent); + if (tree == null) + return; + + tree.ReplaceChildren(startChildIndex, stopChildIndex, t); + } + + protected virtual ITree GetTree(object t) + { + if (t == null) + return null; + + ITree tree = t as ITree; + if (tree == null) + throw new NotSupportedException(); + + return tree; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BufferedTreeNodeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BufferedTreeNodeStream.cs new file mode 100644 index 0000000..3b5a01e --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/BufferedTreeNodeStream.cs @@ -0,0 +1,663 @@ +/* + * [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.Tree +{ + using System.Collections.Generic; + + using Console = System.Console; + using IList = System.Collections.IList; + using InvalidOperationException = System.InvalidOperationException; + using StringBuilder = System.Text.StringBuilder; + + /** <summary>A buffered stream of tree nodes. Nodes can be from a tree of ANY kind.</summary> + * + * This node stream sucks all nodes out of the tree specified in + * the constructor during construction and makes pointers into + * the tree using an array of Object pointers. The stream necessarily + * includes pointers to DOWN and UP and EOF nodes. + * + * This stream knows how to mark/release for backtracking. + * + * This stream is most suitable for tree interpreters that need to + * jump around a lot or for tree parsers requiring speed (at cost of memory). + * There is some duplicated functionality here with UnBufferedTreeNodeStream + * but just in bookkeeping, not tree walking etc... + * + * TARGET DEVELOPERS: + * + * This is the old CommonTreeNodeStream that buffered up entire node stream. + * No need to implement really as new CommonTreeNodeStream is much better + * and covers what we need. + * + * @see CommonTreeNodeStream + */ + public class BufferedTreeNodeStream : ITreeNodeStream, ITokenStreamInformation + { + public const int DEFAULT_INITIAL_BUFFER_SIZE = 100; + public const int INITIAL_CALL_STACK_SIZE = 10; + + protected sealed class StreamIterator : IEnumerator<object> + { + BufferedTreeNodeStream _outer; + int _index; + + public StreamIterator( BufferedTreeNodeStream outer ) + { + _outer = outer; + _index = -1; + } + + #region IEnumerator<object> Members + + public object Current + { + get + { + if ( _index < _outer.nodes.Count ) + return _outer.nodes[_index]; + + return _outer.eof; + } + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + } + + #endregion + + #region IEnumerator Members + + public bool MoveNext() + { + if ( _index < _outer.nodes.Count ) + _index++; + + return _index < _outer.nodes.Count; + } + + public void Reset() + { + _index = -1; + } + + #endregion + } + + // all these navigation nodes are shared and hence they + // cannot contain any line/column info + + protected object down; + protected object up; + protected object eof; + + /** <summary>The complete mapping from stream index to tree node. + * This buffer includes pointers to DOWN, UP, and EOF nodes. + * It is built upon ctor invocation. The elements are type + * Object as we don't what the trees look like.</summary> + * + * Load upon first need of the buffer so we can set token types + * of interest for reverseIndexing. Slows us down a wee bit to + * do all of the if p==-1 testing everywhere though. + */ + protected IList nodes; + + /** <summary>Pull nodes from which tree?</summary> */ + protected object root; + + /** <summary>IF this tree (root) was created from a token stream, track it.</summary> */ + protected ITokenStream tokens; + + /** <summary>What tree adaptor was used to build these trees</summary> */ + ITreeAdaptor adaptor; + + /** <summary>Reuse same DOWN, UP navigation nodes unless this is true</summary> */ + bool uniqueNavigationNodes = false; + + /** <summary>The index into the nodes list of the current node (next node + * to consume). If -1, nodes array not filled yet.</summary> + */ + protected int p = -1; + + /** <summary>Track the last mark() call result value for use in rewind().</summary> */ + protected int lastMarker; + + /** <summary>Stack of indexes used for push/pop calls</summary> */ + protected Stack<int> calls; + + public BufferedTreeNodeStream( object tree ) + : this( new CommonTreeAdaptor(), tree ) + { + } + + public BufferedTreeNodeStream( ITreeAdaptor adaptor, object tree ) + : this( adaptor, tree, DEFAULT_INITIAL_BUFFER_SIZE ) + { + } + + public BufferedTreeNodeStream( ITreeAdaptor adaptor, object tree, int initialBufferSize ) + { + this.root = tree; + this.adaptor = adaptor; + nodes = new List<object>( initialBufferSize ); + down = adaptor.Create( TokenTypes.Down, "DOWN" ); + up = adaptor.Create( TokenTypes.Up, "UP" ); + eof = adaptor.Create( TokenTypes.EndOfFile, "EOF" ); + } + + #region Properties + + public virtual int Count + { + get + { + if ( p == -1 ) + { + throw new InvalidOperationException( "Cannot determine the Count before the buffer is filled." ); + } + return nodes.Count; + } + } + + public virtual object TreeSource + { + get + { + return root; + } + } + + public virtual string SourceName + { + get + { + return TokenStream.SourceName; + } + } + + public virtual ITokenStream TokenStream + { + get + { + return tokens; + } + set + { + tokens = value; + } + } + + public virtual ITreeAdaptor TreeAdaptor + { + get + { + return adaptor; + } + set + { + adaptor = value; + } + } + + public virtual bool UniqueNavigationNodes + { + get + { + return uniqueNavigationNodes; + } + set + { + uniqueNavigationNodes = value; + } + } + + public virtual IToken LastToken + { + get + { + return TreeAdaptor.GetToken(LB(1)); + } + } + + public virtual IToken LastRealToken + { + get + { + int i = 0; + IToken token; + do + { + i++; + token = TreeAdaptor.GetToken(LB(i)); + } while (token != null && token.Line <= 0); + + return token; + } + } + + public virtual int MaxLookBehind + { + get + { + return int.MaxValue; + } + } + + #endregion + + /** Walk tree with depth-first-search and fill nodes buffer. + * Don't do DOWN, UP nodes if its a list (t is isNil). + */ + protected virtual void FillBuffer() + { + FillBuffer( root ); + //Console.Out.WriteLine( "revIndex=" + tokenTypeToStreamIndexesMap ); + p = 0; // buffer of nodes intialized now + } + + public virtual void FillBuffer( object t ) + { + bool nil = adaptor.IsNil( t ); + if ( !nil ) + { + nodes.Add( t ); // add this node + } + // add DOWN node if t has children + int n = adaptor.GetChildCount( t ); + if ( !nil && n > 0 ) + { + AddNavigationNode( TokenTypes.Down ); + } + // and now add all its children + for ( int c = 0; c < n; c++ ) + { + object child = adaptor.GetChild( t, c ); + FillBuffer( child ); + } + // add UP node if t has children + if ( !nil && n > 0 ) + { + AddNavigationNode( TokenTypes.Up ); + } + } + + /** What is the stream index for node? 0..n-1 + * Return -1 if node not found. + */ + protected virtual int GetNodeIndex( object node ) + { + if ( p == -1 ) + { + FillBuffer(); + } + for ( int i = 0; i < nodes.Count; i++ ) + { + object t = nodes[i]; + if ( t == node ) + { + return i; + } + } + return -1; + } + + /** As we flatten the tree, we use UP, DOWN nodes to represent + * the tree structure. When debugging we need unique nodes + * so instantiate new ones when uniqueNavigationNodes is true. + */ + protected virtual void AddNavigationNode( int ttype ) + { + object navNode = null; + if ( ttype == TokenTypes.Down ) + { + if ( UniqueNavigationNodes ) + { + navNode = adaptor.Create( TokenTypes.Down, "DOWN" ); + } + else + { + navNode = down; + } + } + else + { + if ( UniqueNavigationNodes ) + { + navNode = adaptor.Create( TokenTypes.Up, "UP" ); + } + else + { + navNode = up; + } + } + nodes.Add( navNode ); + } + + public virtual object this[int i] + { + get + { + if ( p == -1 ) + { + throw new InvalidOperationException( "Cannot get the node at index i before the buffer is filled." ); + } + return nodes[i]; + } + } + + public virtual object LT( int k ) + { + if ( p == -1 ) + { + FillBuffer(); + } + if ( k == 0 ) + { + return null; + } + if ( k < 0 ) + { + return LB( -k ); + } + //System.out.print("LT(p="+p+","+k+")="); + if ( ( p + k - 1 ) >= nodes.Count ) + { + return eof; + } + return nodes[p + k - 1]; + } + + public virtual object GetCurrentSymbol() + { + return LT( 1 ); + } + +#if false + public virtual object getLastTreeNode() + { + int i = Index; + if ( i >= size() ) + { + i--; // if at EOF, have to start one back + } + Console.Out.WriteLine( "start last node: " + i + " size==" + nodes.Count ); + while ( i >= 0 && + ( adaptor.getType( this[i] ) == TokenTypes.EOF || + adaptor.getType( this[i] ) == TokenTypes.UP || + adaptor.getType( this[i] ) == TokenTypes.DOWN ) ) + { + i--; + } + Console.Out.WriteLine( "stop at node: " + i + " " + nodes[i] ); + return nodes[i]; + } +#endif + + /** <summary>Look backwards k nodes</summary> */ + protected virtual object LB( int k ) + { + if ( k == 0 ) + { + return null; + } + if ( ( p - k ) < 0 ) + { + return null; + } + return nodes[p - k]; + } + + public virtual void Consume() + { + if ( p == -1 ) + { + FillBuffer(); + } + p++; + } + + public virtual int LA( int i ) + { + return adaptor.GetType( LT( i ) ); + } + + public virtual int Mark() + { + if ( p == -1 ) + { + FillBuffer(); + } + lastMarker = Index; + return lastMarker; + } + + public virtual void Release( int marker ) + { + // no resources to release + } + + public virtual int Index + { + get + { + return p; + } + } + + public virtual void Rewind( int marker ) + { + Seek( marker ); + } + + public virtual void Rewind() + { + Seek( lastMarker ); + } + + public virtual void Seek( int index ) + { + if ( p == -1 ) + { + FillBuffer(); + } + p = index; + } + + /** <summary> + * Make stream jump to a new location, saving old location. + * Switch back with pop(). + * </summary> + */ + public virtual void Push( int index ) + { + if ( calls == null ) + { + calls = new Stack<int>(); + } + calls.Push( p ); // save current index + Seek( index ); + } + + /** <summary> + * Seek back to previous index saved during last push() call. + * Return top of stack (return index). + * </summary> + */ + public virtual int Pop() + { + int ret = calls.Pop(); + Seek( ret ); + return ret; + } + + public virtual void Reset() + { + p = 0; + lastMarker = 0; + if ( calls != null ) + { + calls.Clear(); + } + } + + public virtual IEnumerator<object> Iterator() + { + if ( p == -1 ) + { + FillBuffer(); + } + + return new StreamIterator( this ); + } + + // TREE REWRITE INTERFACE + + public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t ) + { + if ( parent != null ) + { + adaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t ); + } + } + + /** <summary>Used for testing, just return the token type stream</summary> */ + public virtual string ToTokenTypeString() + { + if ( p == -1 ) + { + FillBuffer(); + } + StringBuilder buf = new StringBuilder(); + for ( int i = 0; i < nodes.Count; i++ ) + { + object t = nodes[i]; + buf.Append( " " ); + buf.Append( adaptor.GetType( t ) ); + } + return buf.ToString(); + } + + /** <summary>Debugging</summary> */ + public virtual string ToTokenString( int start, int stop ) + { + if ( p == -1 ) + { + FillBuffer(); + } + StringBuilder buf = new StringBuilder(); + for ( int i = start; i < nodes.Count && i <= stop; i++ ) + { + object t = nodes[i]; + buf.Append( " " ); + buf.Append( adaptor.GetToken( t ) ); + } + return buf.ToString(); + } + + public virtual string ToString( object start, object stop ) + { + Console.Out.WriteLine( "toString" ); + if ( start == null || stop == null ) + { + return null; + } + if ( p == -1 ) + { + throw new InvalidOperationException( "Buffer is not yet filled." ); + } + //Console.Out.WriteLine( "stop: " + stop ); + if ( start is CommonTree ) + Console.Out.Write( "toString: " + ( (CommonTree)start ).Token + ", " ); + else + Console.Out.WriteLine( start ); + if ( stop is CommonTree ) + Console.Out.WriteLine( ( (CommonTree)stop ).Token ); + else + Console.Out.WriteLine( stop ); + // if we have the token stream, use that to dump text in order + if ( tokens != null ) + { + int beginTokenIndex = adaptor.GetTokenStartIndex( start ); + int endTokenIndex = adaptor.GetTokenStopIndex( stop ); + // if it's a tree, use start/stop index from start node + // else use token range from start/stop nodes + if ( adaptor.GetType( stop ) == TokenTypes.Up ) + { + endTokenIndex = adaptor.GetTokenStopIndex( start ); + } + else if ( adaptor.GetType( stop ) == TokenTypes.EndOfFile ) + { + endTokenIndex = Count - 2; // don't use EOF + } + return tokens.ToString( beginTokenIndex, endTokenIndex ); + } + // walk nodes looking for start + object t = null; + int i = 0; + for ( ; i < nodes.Count; i++ ) + { + t = nodes[i]; + if ( t == start ) + { + break; + } + } + // now walk until we see stop, filling string buffer with text + StringBuilder buf = new StringBuilder(); + t = nodes[i]; + while ( t != stop ) + { + string text = adaptor.GetText( t ); + if ( text == null ) + { + text = " " + adaptor.GetType( t ).ToString(); + } + buf.Append( text ); + i++; + t = nodes[i]; + } + // include stop node too + string text2 = adaptor.GetText( stop ); + if ( text2 == null ) + { + text2 = " " + adaptor.GetType( stop ).ToString(); + } + buf.Append( text2 ); + return buf.ToString(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonErrorNode.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonErrorNode.cs new file mode 100644 index 0000000..3bd9138 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonErrorNode.cs @@ -0,0 +1,142 @@ +/* + * [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.Tree +{ + + /** <summary>A node representing erroneous token range in token stream</summary> */ + [System.Serializable] + public class CommonErrorNode : CommonTree + { + public IIntStream input; + public IToken start; + public IToken stop; + public RecognitionException trappedException; + + public CommonErrorNode( ITokenStream input, IToken start, IToken stop, + RecognitionException e ) + { + //System.out.println("start: "+start+", stop: "+stop); + if ( stop == null || + ( stop.TokenIndex < start.TokenIndex && + stop.Type != TokenTypes.EndOfFile ) ) + { + // sometimes resync does not consume a token (when LT(1) is + // in follow set. So, stop will be 1 to left to start. adjust. + // Also handle case where start is the first token and no token + // is consumed during recovery; LT(-1) will return null. + stop = start; + } + this.input = input; + this.start = start; + this.stop = stop; + this.trappedException = e; + } + + #region Properties + public override bool IsNil + { + get + { + return false; + } + } + public override string Text + { + get + { + string badText = null; + if ( start is IToken ) + { + int i = ( (IToken)start ).TokenIndex; + int j = ( (IToken)stop ).TokenIndex; + if ( ( (IToken)stop ).Type == TokenTypes.EndOfFile ) + { + j = ( (ITokenStream)input ).Count; + } + badText = ( (ITokenStream)input ).ToString( i, j ); + } + else if ( start is ITree ) + { + badText = ( (ITreeNodeStream)input ).ToString( start, stop ); + } + else + { + // people should subclass if they alter the tree type so this + // next one is for sure correct. + badText = "<unknown>"; + } + return badText; + } + set + { + } + } + public override int Type + { + get + { + return TokenTypes.Invalid; + } + set + { + } + } + #endregion + + public override string ToString() + { + if ( trappedException is MissingTokenException ) + { + return "<missing type: " + + ( (MissingTokenException)trappedException ).MissingType + + ">"; + } + else if ( trappedException is UnwantedTokenException ) + { + return "<extraneous: " + + ( (UnwantedTokenException)trappedException ).UnexpectedToken + + ", resync=" + Text + ">"; + } + else if ( trappedException is MismatchedTokenException ) + { + return "<mismatched token: " + trappedException.Token + ", resync=" + Text + ">"; + } + else if ( trappedException is NoViableAltException ) + { + return "<unexpected: " + trappedException.Token + + ", resync=" + Text + ">"; + } + return "<error: " + Text + ">"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTree.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTree.cs new file mode 100644 index 0000000..33f9bda --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTree.cs @@ -0,0 +1,296 @@ +/* + * [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.Tree +{ + using ArgumentNullException = System.ArgumentNullException; + + /** <summary> + * A tree node that is wrapper for a Token object. After 3.0 release + * while building tree rewrite stuff, it became clear that computing + * parent and child index is very difficult and cumbersome. Better to + * spend the space in every tree node. If you don't want these extra + * fields, it's easy to cut them out in your own BaseTree subclass. + * </summary> + */ + [System.Serializable] + public class CommonTree : BaseTree + { + /** <summary>A single token is the payload</summary> */ + private IToken _token; + + /** <summary> + * What token indexes bracket all tokens associated with this node + * and below? + * </summary> + */ + protected int startIndex = -1; + protected int stopIndex = -1; + + /** <summary>Who is the parent node of this node; if null, implies node is root</summary> */ + CommonTree parent; + + /** <summary>What index is this node in the child list? Range: 0..n-1</summary> */ + int childIndex = -1; + + public CommonTree() + { + } + + public CommonTree( CommonTree node ) + : base( node ) + { + if (node == null) + throw new ArgumentNullException("node"); + + this.Token = node.Token; + this.startIndex = node.startIndex; + this.stopIndex = node.stopIndex; + } + + public CommonTree( IToken t ) + { + this.Token = t; + } + + #region Properties + + public override int CharPositionInLine + { + get + { + if ( Token == null || Token.CharPositionInLine == -1 ) + { + if ( ChildCount > 0 ) + return Children[0].CharPositionInLine; + + return 0; + } + return Token.CharPositionInLine; + } + + set + { + base.CharPositionInLine = value; + } + } + + public override int ChildIndex + { + get + { + return childIndex; + } + + set + { + childIndex = value; + } + } + + public override bool IsNil + { + get + { + return Token == null; + } + } + + public override int Line + { + get + { + if ( Token == null || Token.Line == 0 ) + { + if ( ChildCount > 0 ) + return Children[0].Line; + + return 0; + } + + return Token.Line; + } + + set + { + base.Line = value; + } + } + + public override ITree Parent + { + get + { + return parent; + } + + set + { + parent = (CommonTree)value; + } + } + + public override string Text + { + get + { + if ( Token == null ) + return null; + + return Token.Text; + } + + set + { + } + } + + public IToken Token + { + get + { + return _token; + } + + set + { + _token = value; + } + } + + public override int TokenStartIndex + { + get + { + if ( startIndex == -1 && Token != null ) + return Token.TokenIndex; + + return startIndex; + } + + set + { + startIndex = value; + } + } + + public override int TokenStopIndex + { + get + { + if ( stopIndex == -1 && Token != null ) + { + return Token.TokenIndex; + } + return stopIndex; + } + + set + { + stopIndex = value; + } + } + + public override int Type + { + get + { + if ( Token == null ) + return TokenTypes.Invalid; + + return Token.Type; + } + + set + { + } + } + + #endregion + + public override ITree DupNode() + { + return new CommonTree( this ); + } + + /** <summary> + * For every node in this subtree, make sure it's start/stop token's + * are set. Walk depth first, visit bottom up. Only updates nodes + * with at least one token index < 0. + * </summary> + */ + public virtual void SetUnknownTokenBoundaries() + { + if ( Children == null ) + { + if ( startIndex < 0 || stopIndex < 0 ) + startIndex = stopIndex = Token.TokenIndex; + + return; + } + + foreach (ITree childTree in Children) + { + CommonTree commonTree = childTree as CommonTree; + if (commonTree == null) + continue; + + commonTree.SetUnknownTokenBoundaries(); + } + + if ( startIndex >= 0 && stopIndex >= 0 ) + return; // already set + + if ( Children.Count > 0 ) + { + ITree firstChild = Children[0]; + ITree lastChild = Children[Children.Count - 1]; + startIndex = firstChild.TokenStartIndex; + stopIndex = lastChild.TokenStopIndex; + } + } + + public override string ToString() + { + if (IsNil) + return "nil"; + + if (Type == TokenTypes.Invalid) + return "<errornode>"; + + if (Token == null) + return string.Empty; + + return Token.Text; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeAdaptor.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeAdaptor.cs new file mode 100644 index 0000000..18c7505 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeAdaptor.cs @@ -0,0 +1,112 @@ +/* + * [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.Tree +{ + + /** <summary> + * A TreeAdaptor that works with any Tree implementation. It provides + * really just factory methods; all the work is done by BaseTreeAdaptor. + * If you would like to have different tokens created than ClassicToken + * objects, you need to override this and then set the parser tree adaptor to + * use your subclass. + * </summary> + * + * <remarks> + * To get your parser to build nodes of a different type, override + * create(Token), errorNode(), and to be safe, YourTreeClass.dupNode(). + * dupNode is called to duplicate nodes during rewrite operations. + * </remarks> + */ + public class CommonTreeAdaptor : BaseTreeAdaptor + { + public override object Create( IToken payload ) + { + return new CommonTree( payload ); + } + + /** <summary> + * Tell me how to create a token for use with imaginary token nodes. + * For example, there is probably no input symbol associated with imaginary + * token DECL, but you need to create it as a payload or whatever for + * the DECL node as in ^(DECL type ID). + * </summary> + * + * <remarks> + * If you care what the token payload objects' type is, you should + * override this method and any other createToken variant. + * </remarks> + */ + public override IToken CreateToken( int tokenType, string text ) + { + return new CommonToken( tokenType, text ); + } + + /** <summary> + * Tell me how to create a token for use with imaginary token nodes. + * For example, there is probably no input symbol associated with imaginary + * token DECL, but you need to create it as a payload or whatever for + * the DECL node as in ^(DECL type ID). + * </summary> + * + * <remarks> + * This is a variant of createToken where the new token is derived from + * an actual real input token. Typically this is for converting '{' + * tokens to BLOCK etc... You'll see + * + * r : lc='{' ID+ '}' -> ^(BLOCK[$lc] ID+) ; + * + * If you care what the token payload objects' type is, you should + * override this method and any other createToken variant. + * </remarks> + */ + public override IToken CreateToken( IToken fromToken ) + { + return new CommonToken( fromToken ); + } + + /** <summary> + * What is the Token associated with this node? If + * you are not using CommonTree, then you must + * override this in your own adaptor. + * </summary> + */ + public override IToken GetToken( object t ) + { + if ( t is CommonTree ) + { + return ( (CommonTree)t ).Token; + } + return null; // no idea what to do + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeNodeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeNodeStream.cs new file mode 100644 index 0000000..45c46be --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/CommonTreeNodeStream.cs @@ -0,0 +1,254 @@ +/* + * [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.Tree +{ + using System.Collections.Generic; + using Antlr.Runtime.Misc; + + using StringBuilder = System.Text.StringBuilder; + using NotSupportedException = System.NotSupportedException; + + [System.Serializable] + public class CommonTreeNodeStream : LookaheadStream<object>, ITreeNodeStream + { + public const int DEFAULT_INITIAL_BUFFER_SIZE = 100; + public const int INITIAL_CALL_STACK_SIZE = 10; + + /** <summary>Pull nodes from which tree?</summary> */ + object _root; + + /** <summary>If this tree (root) was created from a token stream, track it.</summary> */ + protected ITokenStream tokens; + + /** <summary>What tree adaptor was used to build these trees</summary> */ + [System.NonSerialized] + ITreeAdaptor _adaptor; + + /** The tree iterator we are using */ + TreeIterator _it; + + /** <summary>Stack of indexes used for push/pop calls</summary> */ + Stack<int> _calls; + + /** <summary>Tree (nil A B C) trees like flat A B C streams</summary> */ + bool _hasNilRoot = false; + + /** <summary>Tracks tree depth. Level=0 means we're at root node level.</summary> */ + int _level = 0; + + public CommonTreeNodeStream( object tree ) + : this( new CommonTreeAdaptor(), tree ) + { + } + + public CommonTreeNodeStream( ITreeAdaptor adaptor, object tree ) + { + this._root = tree; + this._adaptor = adaptor; + _it = new TreeIterator( adaptor, _root ); + } + + #region Properties + + public virtual string SourceName + { + get + { + if ( TokenStream == null ) + return null; + + return TokenStream.SourceName; + } + } + + public virtual ITokenStream TokenStream + { + get + { + return tokens; + } + set + { + tokens = value; + } + } + + public virtual ITreeAdaptor TreeAdaptor + { + get + { + return _adaptor; + } + + set + { + _adaptor = value; + } + } + + public virtual object TreeSource + { + get + { + return _root; + } + } + + public virtual bool UniqueNavigationNodes + { + get + { + return false; + } + + set + { + } + } + + #endregion + + public virtual void Reset() + { + base.Clear(); + _it.Reset(); + _hasNilRoot = false; + _level = 0; + if ( _calls != null ) + _calls.Clear(); + } + + public override object NextElement() + { + _it.MoveNext(); + object t = _it.Current; + //System.out.println("pulled "+adaptor.getType(t)); + if ( t == _it.up ) + { + _level--; + if ( _level == 0 && _hasNilRoot ) + { + _it.MoveNext(); + return _it.Current; // don't give last UP; get EOF + } + } + else if ( t == _it.down ) + { + _level++; + } + + if ( _level == 0 && TreeAdaptor.IsNil( t ) ) + { + // if nil root, scarf nil, DOWN + _hasNilRoot = true; + _it.MoveNext(); + t = _it.Current; // t is now DOWN, so get first real node next + _level++; + _it.MoveNext(); + t = _it.Current; + } + + return t; + } + + public override bool IsEndOfFile(object o) + { + return TreeAdaptor.GetType(o) == CharStreamConstants.EndOfFile; + } + + public virtual int LA( int i ) + { + return TreeAdaptor.GetType( LT( i ) ); + } + + /** Make stream jump to a new location, saving old location. + * Switch back with pop(). + */ + public virtual void Push( int index ) + { + if ( _calls == null ) + { + _calls = new Stack<int>(); + } + _calls.Push( _p ); // save current index + Seek( index ); + } + + /** Seek back to previous index saved during last push() call. + * Return top of stack (return index). + */ + public virtual int Pop() + { + int ret = _calls.Pop(); + Seek( ret ); + return ret; + } + + #region Tree rewrite interface + + public virtual void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t ) + { + if ( parent != null ) + { + TreeAdaptor.ReplaceChildren( parent, startChildIndex, stopChildIndex, t ); + } + } + + #endregion + + public virtual string ToString( object start, object stop ) + { + // we'll have to walk from start to stop in tree; we're not keeping + // a complete node stream buffer + return "n/a"; + } + + /** <summary>For debugging; destructive: moves tree iterator to end.</summary> */ + public virtual string ToTokenTypeString() + { + Reset(); + StringBuilder buf = new StringBuilder(); + object o = LT( 1 ); + int type = TreeAdaptor.GetType( o ); + while ( type != TokenTypes.EndOfFile ) + { + buf.Append( " " ); + buf.Append( type ); + Consume(); + o = LT( 1 ); + type = TreeAdaptor.GetType( o ); + } + return buf.ToString(); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/DotTreeGenerator.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/DotTreeGenerator.cs new file mode 100644 index 0000000..8a35b45 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/DotTreeGenerator.cs @@ -0,0 +1,216 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Tree +{ + using System.Collections.Generic; + using StringBuilder = System.Text.StringBuilder; + + /** A utility class to generate DOT diagrams (graphviz) from + * arbitrary trees. You can pass in your own templates and + * can pass in any kind of tree or use Tree interface method. + * I wanted this separator so that you don't have to include + * ST just to use the org.antlr.runtime.tree.* package. + * This is a set of non-static methods so you can subclass + * to override. For example, here is an invocation: + * + * CharStream input = new ANTLRInputStream(System.in); + * TLexer lex = new TLexer(input); + * CommonTokenStream tokens = new CommonTokenStream(lex); + * TParser parser = new TParser(tokens); + * TParser.e_return r = parser.e(); + * Tree t = (Tree)r.tree; + * System.out.println(t.toStringTree()); + * DOTTreeGenerator gen = new DOTTreeGenerator(); + * StringTemplate st = gen.toDOT(t); + * System.out.println(st); + */ + public class DotTreeGenerator + { + readonly string[] HeaderLines = + { + "digraph {", + "", + "\tordering=out;", + "\tranksep=.4;", + "\tbgcolor=\"lightgrey\"; node [shape=box, fixedsize=false, fontsize=12, fontname=\"Helvetica-bold\", fontcolor=\"blue\"", + "\t\twidth=.25, height=.25, color=\"black\", fillcolor=\"white\", style=\"filled, solid, bold\"];", + "\tedge [arrowsize=.5, color=\"black\", style=\"bold\"]", + "" + }; + const string Footer = "}"; + const string NodeFormat = " {0} [label=\"{1}\"];"; + const string EdgeFormat = " {0} -> {1} // \"{2}\" -> \"{3}\""; + + /** Track node to number mapping so we can get proper node name back */ + Dictionary<object, int> nodeToNumberMap = new Dictionary<object, int>(); + + /** Track node number so we can get unique node names */ + int nodeNumber = 0; + + /** Generate DOT (graphviz) for a whole tree not just a node. + * For example, 3+4*5 should generate: + * + * digraph { + * node [shape=plaintext, fixedsize=true, fontsize=11, fontname="Courier", + * width=.4, height=.2]; + * edge [arrowsize=.7] + * "+"->3 + * "+"->"*" + * "*"->4 + * "*"->5 + * } + * + * Takes a Tree interface object. + */ + public virtual string ToDot( object tree, ITreeAdaptor adaptor ) + { + StringBuilder builder = new StringBuilder(); + foreach ( string line in HeaderLines ) + builder.AppendLine( line ); + + nodeNumber = 0; + var nodes = DefineNodes( tree, adaptor ); + nodeNumber = 0; + var edges = DefineEdges( tree, adaptor ); + + foreach ( var s in nodes ) + builder.AppendLine( s ); + + builder.AppendLine(); + + foreach ( var s in edges ) + builder.AppendLine( s ); + + builder.AppendLine(); + + builder.AppendLine( Footer ); + return builder.ToString(); + } + + public virtual string ToDot( ITree tree ) + { + return ToDot( tree, new CommonTreeAdaptor() ); + } + protected virtual IEnumerable<string> DefineNodes( object tree, ITreeAdaptor adaptor ) + { + if ( tree == null ) + yield break; + + int n = adaptor.GetChildCount( tree ); + if ( n == 0 ) + { + // must have already dumped as child from previous + // invocation; do nothing + yield break; + } + + // define parent node + yield return GetNodeText( adaptor, tree ); + + // for each child, do a "<unique-name> [label=text]" node def + for ( int i = 0; i < n; i++ ) + { + object child = adaptor.GetChild( tree, i ); + yield return GetNodeText( adaptor, child ); + foreach ( var t in DefineNodes( child, adaptor ) ) + yield return t; + } + } + + protected virtual IEnumerable<string> DefineEdges( object tree, ITreeAdaptor adaptor ) + { + if ( tree == null ) + yield break; + + int n = adaptor.GetChildCount( tree ); + if ( n == 0 ) + { + // must have already dumped as child from previous + // invocation; do nothing + yield break; + } + + string parentName = "n" + GetNodeNumber( tree ); + + // for each child, do a parent -> child edge using unique node names + string parentText = adaptor.GetText( tree ); + for ( int i = 0; i < n; i++ ) + { + object child = adaptor.GetChild( tree, i ); + string childText = adaptor.GetText( child ); + string childName = "n" + GetNodeNumber( child ); + yield return string.Format( EdgeFormat, parentName, childName, FixString( parentText ), FixString( childText ) ); + foreach ( var t in DefineEdges( child, adaptor ) ) + yield return t; + } + } + + protected virtual string GetNodeText( ITreeAdaptor adaptor, object t ) + { + string text = adaptor.GetText( t ); + string uniqueName = "n" + GetNodeNumber( t ); + return string.Format( NodeFormat, uniqueName, FixString( text ) ); + } + + protected virtual int GetNodeNumber( object t ) + { + int i; + if ( nodeToNumberMap.TryGetValue( t, out i ) ) + { + return i; + } + else + { + nodeToNumberMap[t] = nodeNumber; + nodeNumber++; + return nodeNumber - 1; + } + } + + protected virtual string FixString( string text ) + { + if ( text != null ) + { + text = System.Text.RegularExpressions.Regex.Replace( text, "\"", "\\\\\"" ); + text = System.Text.RegularExpressions.Regex.Replace( text, "\\t", " " ); + text = System.Text.RegularExpressions.Regex.Replace( text, "\\n", "\\\\n" ); + text = System.Text.RegularExpressions.Regex.Replace( text, "\\r", "\\\\r" ); + + if ( text.Length > 20 ) + text = text.Substring( 0, 8 ) + "..." + text.Substring( text.Length - 8 ); + } + + return text; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITree.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITree.cs new file mode 100644 index 0000000..a3eb034 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITree.cs @@ -0,0 +1,173 @@ +/* + * [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.Tree +{ + using System.Collections.Generic; + + /** <summary> + * What does a tree look like? ANTLR has a number of support classes + * such as CommonTreeNodeStream that work on these kinds of trees. You + * don't have to make your trees implement this interface, but if you do, + * you'll be able to use more support code. + * </summary> + * + * <remarks> + * NOTE: When constructing trees, ANTLR can build any kind of tree; it can + * even use Token objects as trees if you add a child list to your tokens. + * + * This is a tree node without any payload; just navigation and factory stuff. + * </remarks> + */ + public interface ITree + { + + ITree GetChild( int i ); + + int ChildCount + { + get; + } + + // Tree tracks parent and child index now > 3.0 + + ITree Parent + { + get; + set; + } + + /** <summary>Is there is a node above with token type ttype?</summary> */ + bool HasAncestor( int ttype ); + + /** <summary>Walk upwards and get first ancestor with this token type.</summary> */ + ITree GetAncestor( int ttype ); + + /** <summary> + * Return a list of all ancestors of this node. The first node of + * list is the root and the last is the parent of this node. + * </summary> + */ + IList<ITree> GetAncestors(); + + /** <summary>This node is what child index? 0..n-1</summary> */ + int ChildIndex + { + get; + set; + } + + /** <summary>Set the parent and child index values for all children</summary> */ + void FreshenParentAndChildIndexes(); + + /** <summary> + * Add t as a child to this node. If t is null, do nothing. If t + * is nil, add all children of t to this' children. + * </summary> + */ + void AddChild( ITree t ); + + /** <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary> */ + void SetChild( int i, ITree t ); + + object DeleteChild( int i ); + + /** <summary> + * Delete children from start to stop and replace with t even if t is + * a list (nil-root tree). num of children can increase or decrease. + * For huge child lists, inserting children can force walking rest of + * children to set their childindex; could be slow. + * </summary> + */ + void ReplaceChildren( int startChildIndex, int stopChildIndex, object t ); + + /** <summary> + * Indicates the node is a nil node but may still have children, meaning + * the tree is a flat list. + * </summary> + */ + bool IsNil + { + get; + } + + /** <summary> + * What is the smallest token index (indexing from 0) for this node + * and its children? + * </summary> + */ + int TokenStartIndex + { + get; + set; + } + + /** <summary> + * What is the largest token index (indexing from 0) for this node + * and its children? + * </summary> + */ + int TokenStopIndex + { + get; + set; + } + + ITree DupNode(); + + /** <summary>Return a token type; needed for tree parsing</summary> */ + int Type + { + get; + } + + string Text + { + get; + } + + /** <summary>In case we don't have a token payload, what is the line for errors?</summary> */ + int Line + { + get; + } + + int CharPositionInLine + { + get; + } + + string ToStringTree(); + + string ToString(); + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeAdaptor.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeAdaptor.cs new file mode 100644 index 0000000..30230cc --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeAdaptor.cs @@ -0,0 +1,346 @@ +/* + * [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.Tree +{ + + /** <summary> + * How to create and navigate trees. Rather than have a separate factory + * and adaptor, I've merged them. Makes sense to encapsulate. + * </summary> + * + * <remarks> + * This takes the place of the tree construction code generated in the + * generated code in 2.x and the ASTFactory. + * + * I do not need to know the type of a tree at all so they are all + * generic Objects. This may increase the amount of typecasting needed. :( + * </remarks> + */ + public interface ITreeAdaptor + { + #region Construction + + /** <summary> + * Create a tree node from Token object; for CommonTree type trees, + * then the token just becomes the payload. This is the most + * common create call. + * </summary> + * + * <remarks> + * Override if you want another kind of node to be built. + * </remarks> + */ + object Create(IToken payload); + + /** <summary> + * Create a new node derived from a token, with a new token type. + * This is invoked from an imaginary node ref on right side of a + * rewrite rule as IMAG[$tokenLabel]. + * </summary> + * + * <remarks> + * This should invoke createToken(Token). + * </remarks> + */ + object Create(int tokenType, IToken fromToken); + + /** <summary> + * Same as create(tokenType,fromToken) except set the text too. + * This is invoked from an imaginary node ref on right side of a + * rewrite rule as IMAG[$tokenLabel, "IMAG"]. + * </summary> + * + * <remarks> + * This should invoke createToken(Token). + * </remarks> + */ + object Create(int tokenType, IToken fromToken, string text); + + /** <summary> + * Same as create(fromToken) except set the text too. + * This is invoked when the <c>text</c> terminal option is set, as in + * IMAG<text='IMAG'>. + * </summary> + * + * <remarks> + * This should invoke createToken(Token). + * </remarks> + */ + object Create(IToken fromToken, string text); + + /** <summary> + * Create a new node derived from a token, with a new token type. + * This is invoked from an imaginary node ref on right side of a + * rewrite rule as IMAG["IMAG"]. + * </summary> + * + * <remarks> + * This should invoke createToken(int,String). + * </remarks> + */ + object Create(int tokenType, string text); + + /** <summary>Duplicate a single tree node.</summary> + * <remarks>Override if you want another kind of node to be built.</remarks> + */ + object DupNode(object treeNode); + + object DupNode(int type, object treeNode); + + object DupNode(object treeNode, string text); + + object DupNode(int type, object treeNode, string text); + + /** <summary>Duplicate tree recursively, using dupNode() for each node</summary> */ + object DupTree( object tree ); + + /** <summary> + * Return a nil node (an empty but non-null node) that can hold + * a list of element as the children. If you want a flat tree (a list) + * use "t=adaptor.nil(); t.addChild(x); t.addChild(y);" + * </summary> + */ + object Nil(); + + /** <summary> + * Return a tree node representing an error. This node records the + * tokens consumed during error recovery. The start token indicates the + * input symbol at which the error was detected. The stop token indicates + * the last symbol consumed during recovery. + * </summary> + * + * </remarks> + * You must specify the input stream so that the erroneous text can + * be packaged up in the error node. The exception could be useful + * to some applications; default implementation stores ptr to it in + * the CommonErrorNode. + * + * This only makes sense during token parsing, not tree parsing. + * Tree parsing should happen only when parsing and tree construction + * succeed. + * </remarks> + */ + object ErrorNode( ITokenStream input, IToken start, IToken stop, RecognitionException e ); + + /** <summary>Is tree considered a nil node used to make lists of child nodes?</summary> */ + bool IsNil( object tree ); + + /** <summary> + * Add a child to the tree t. If child is a flat tree (a list), make all + * in list children of t. Warning: if t has no children, but child does + * and child isNil then you can decide it is ok to move children to t via + * t.children = child.children; i.e., without copying the array. Just + * make sure that this is consistent with have the user will build + * ASTs. Do nothing if t or child is null. + * </summary> + */ + void AddChild( object t, object child ); + + /** <summary> + * If oldRoot is a nil root, just copy or move the children to newRoot. + * If not a nil root, make oldRoot a child of newRoot. + * </summary> + * + * <remarks> + * old=^(nil a b c), new=r yields ^(r a b c) + * old=^(a b c), new=r yields ^(r ^(a b c)) + * + * If newRoot is a nil-rooted single child tree, use the single + * child as the new root node. + * + * old=^(nil a b c), new=^(nil r) yields ^(r a b c) + * old=^(a b c), new=^(nil r) yields ^(r ^(a b c)) + * + * If oldRoot was null, it's ok, just return newRoot (even if isNil). + * + * old=null, new=r yields r + * old=null, new=^(nil r) yields ^(nil r) + * + * Return newRoot. Throw an exception if newRoot is not a + * simple node or nil root with a single child node--it must be a root + * node. If newRoot is ^(nil x) return x as newRoot. + * + * Be advised that it's ok for newRoot to point at oldRoot's + * children; i.e., you don't have to copy the list. We are + * constructing these nodes so we should have this control for + * efficiency. + * </remarks> + */ + object BecomeRoot( object newRoot, object oldRoot ); + + /** <summary> + * Given the root of the subtree created for this rule, post process + * it to do any simplifications or whatever you want. A required + * behavior is to convert ^(nil singleSubtree) to singleSubtree + * as the setting of start/stop indexes relies on a single non-nil root + * for non-flat trees. + * </summary> + * + * <remarks> + * Flat trees such as for lists like "idlist : ID+ ;" are left alone + * unless there is only one ID. For a list, the start/stop indexes + * are set in the nil node. + * + * This method is executed after all rule tree construction and right + * before setTokenBoundaries(). + * </remarks> + */ + object RulePostProcessing( object root ); + + /** <summary>For identifying trees.</summary> + * + * <remarks> + * How to identify nodes so we can say "add node to a prior node"? + * Even becomeRoot is an issue. Use System.identityHashCode(node) + * usually. + * </remarks> + */ + int GetUniqueID( object node ); + + + // R e w r i t e R u l e s + + /** <summary> + * Create a node for newRoot make it the root of oldRoot. + * If oldRoot is a nil root, just copy or move the children to newRoot. + * If not a nil root, make oldRoot a child of newRoot. + * </summary> + * + * <returns> + * Return node created for newRoot. + * </returns> + * + * <remarks> + * Be advised: when debugging ASTs, the DebugTreeAdaptor manually + * calls create(Token child) and then plain becomeRoot(node, node) + * because it needs to trap calls to create, but it can't since it delegates + * to not inherits from the TreeAdaptor. + * </remarks> + */ + object BecomeRoot( IToken newRoot, object oldRoot ); + + #endregion + + + #region Content + + /** <summary>For tree parsing, I need to know the token type of a node</summary> */ + int GetType( object t ); + + /** <summary>Node constructors can set the type of a node</summary> */ + void SetType( object t, int type ); + + string GetText( object t ); + + /** <summary>Node constructors can set the text of a node</summary> */ + void SetText( object t, string text ); + + /** <summary> + * Return the token object from which this node was created. + * Currently used only for printing an error message. + * The error display routine in BaseRecognizer needs to + * display where the input the error occurred. If your + * tree of limitation does not store information that can + * lead you to the token, you can create a token filled with + * the appropriate information and pass that back. See + * BaseRecognizer.getErrorMessage(). + * </summary> + */ + IToken GetToken( object t ); + + /** <summary> + * Where are the bounds in the input token stream for this node and + * all children? Each rule that creates AST nodes will call this + * method right before returning. Flat trees (i.e., lists) will + * still usually have a nil root node just to hold the children list. + * That node would contain the start/stop indexes then. + * </summary> + */ + void SetTokenBoundaries( object t, IToken startToken, IToken stopToken ); + + /** <summary>Get the token start index for this subtree; return -1 if no such index</summary> */ + int GetTokenStartIndex( object t ); + + /** <summary>Get the token stop index for this subtree; return -1 if no such index</summary> */ + int GetTokenStopIndex( object t ); + + #endregion + + + #region Navigation / Tree Parsing + + /** <summary>Get a child 0..n-1 node</summary> */ + object GetChild( object t, int i ); + + /** <summary>Set ith child (0..n-1) to t; t must be non-null and non-nil node</summary> */ + void SetChild( object t, int i, object child ); + + /** <summary>Remove ith child and shift children down from right.</summary> */ + object DeleteChild( object t, int i ); + + /** <summary>How many children? If 0, then this is a leaf node</summary> */ + int GetChildCount( object t ); + + /** <summary> + * Who is the parent node of this node; if null, implies node is root. + * If your node type doesn't handle this, it's ok but the tree rewrites + * in tree parsers need this functionality. + * </summary> + */ + object GetParent( object t ); + void SetParent( object t, object parent ); + + /** <summary> + * What index is this node in the child list? Range: 0..n-1 + * If your node type doesn't handle this, it's ok but the tree rewrites + * in tree parsers need this functionality. + * </summary> + */ + int GetChildIndex( object t ); + void SetChildIndex( object t, int index ); + + /** <summary> + * Replace from start to stop child index of parent with t, which might + * be a list. Number of children may be different after this call. + * </summary> + * + * <remarks> + * If parent is null, don't do anything; must be at root of overall tree. + * Can't replace whatever points to the parent externally. Do nothing. + * </remarks> + */ + void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t ); + + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeNodeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeNodeStream.cs new file mode 100644 index 0000000..b133f39 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeNodeStream.cs @@ -0,0 +1,144 @@ +/* + * [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.Tree +{ + /** <summary>A stream of tree nodes, accessing nodes from a tree of some kind</summary> */ + public interface ITreeNodeStream : IIntStream + { + /** <summary> + * Get a tree node at an absolute index i; 0..n-1. + * If you don't want to buffer up nodes, then this method makes no + * sense for you. + * </summary> + */ + object this[int i] + { + get; + } + + /** <summary> + * Get tree node at current input pointer + i ahead where i=1 is next node. + * i<0 indicates nodes in the past. So LT(-1) is previous node, but + * implementations are not required to provide results for k < -1. + * LT(0) is undefined. For i>=n, return null. + * Return null for LT(0) and any index that results in an absolute address + * that is negative. + * </summary> + * + * <remarks> + * This is analogus to the LT() method of the TokenStream, but this + * returns a tree node instead of a token. Makes code gen identical + * for both parser and tree grammars. :) + * </remarks> + */ + object LT( int k ); + + /** <summary> + * Where is this stream pulling nodes from? This is not the name, but + * the object that provides node objects. + * </summary> + */ + object TreeSource + { + get; + } + + /** <summary> + * If the tree associated with this stream was created from a TokenStream, + * you can specify it here. Used to do rule $text attribute in tree + * parser. Optional unless you use tree parser rule text attribute + * or output=template and rewrite=true options. + * </summary> + */ + ITokenStream TokenStream + { + get; + } + + /** <summary> + * What adaptor can tell me how to interpret/navigate nodes and + * trees. E.g., get text of a node. + * </summary> + */ + ITreeAdaptor TreeAdaptor + { + get; + } + + /** <summary> + * As we flatten the tree, we use UP, DOWN nodes to represent + * the tree structure. When debugging we need unique nodes + * so we have to instantiate new ones. When doing normal tree + * parsing, it's slow and a waste of memory to create unique + * navigation nodes. Default should be false; + * </summary> + */ + bool UniqueNavigationNodes + { + get; + set; + } + + /** <summary> + * Return the text of all nodes from start to stop, inclusive. + * If the stream does not buffer all the nodes then it can still + * walk recursively from start until stop. You can always return + * null or "" too, but users should not access $ruleLabel.text in + * an action of course in that case. + * </summary> + */ + string ToString( object start, object stop ); + + + #region REWRITING TREES (used by tree parser) + + /** <summary> + * Replace from start to stop child index of parent with t, which might + * be a list. Number of children may be different + * after this call. The stream is notified because it is walking the + * tree and might need to know you are monkeying with the underlying + * tree. Also, it might be able to modify the node stream to avoid + * restreaming for future phases. + * </summary> + * + * <remarks> + * If parent is null, don't do anything; must be at root of overall tree. + * Can't replace whatever points to the parent externally. Do nothing. + * </remarks> + */ + void ReplaceChildren( object parent, int startChildIndex, int stopChildIndex, object t ); + + #endregion + + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeVisitorAction.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeVisitorAction.cs new file mode 100644 index 0000000..bcf0156 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ITreeVisitorAction.cs @@ -0,0 +1,90 @@ +/* + * [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.Tree +{ + using Antlr.Runtime.Misc; + + /** <summary> + * How to execute code for node t when a visitor visits node t. Execute + * pre() before visiting children and execute post() after visiting children. + * </summary> + */ + public interface ITreeVisitorAction + { + /** <summary> + * Execute an action before visiting children of t. Return t or + * a rewritten t. It is up to the visitor to decide what to do + * with the return value. Children of returned value will be + * visited if using TreeVisitor.visit(). + * </summary> + */ + object Pre( object t ); + + /** <summary> + * Execute an action after visiting children of t. Return t or + * a rewritten t. It is up to the visitor to decide what to do + * with the return value. + * </summary> + */ + object Post( object t ); + } + + public class TreeVisitorAction + : ITreeVisitorAction + { + private readonly Func<object, object> _preAction; + private readonly Func<object, object> _postAction; + + public TreeVisitorAction( Func<object, object> preAction, Func<object, object> postAction ) + { + _preAction = preAction; + _postAction = postAction; + } + + public object Pre( object t ) + { + if ( _preAction != null ) + return _preAction( t ); + + return t; + } + + public object Post( object t ) + { + if ( _postAction != null ) + return _postAction( t ); + + return t; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ParseTree.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ParseTree.cs new file mode 100644 index 0000000..149269a --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/ParseTree.cs @@ -0,0 +1,167 @@ +/* + * [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.Tree +{ + using System.Collections.Generic; + + using StringBuilder = System.Text.StringBuilder; + + /** <summary> + * A record of the rules used to match a token sequence. The tokens + * end up as the leaves of this tree and rule nodes are the interior nodes. + * This really adds no functionality, it is just an alias for CommonTree + * that is more meaningful (specific) and holds a String to display for a node. + * </summary> + */ + [System.Serializable] + public class ParseTree : BaseTree + { + public object payload; + public List<IToken> hiddenTokens; + + public ParseTree( object label ) + { + this.payload = label; + } + + #region Properties + public override string Text + { + get + { + return ToString(); + } + set + { + } + } + public override int TokenStartIndex + { + get + { + return 0; + } + set + { + } + } + public override int TokenStopIndex + { + get + { + return 0; + } + set + { + } + } + public override int Type + { + get + { + return 0; + } + set + { + } + } + #endregion + + public override ITree DupNode() + { + return null; + } + + public override string ToString() + { + if ( payload is IToken ) + { + IToken t = (IToken)payload; + if ( t.Type == TokenTypes.EndOfFile ) + { + return "<EOF>"; + } + return t.Text; + } + return payload.ToString(); + } + + /** <summary> + * Emit a token and all hidden nodes before. EOF node holds all + * hidden tokens after last real token. + * </summary> + */ + public virtual string ToStringWithHiddenTokens() + { + StringBuilder buf = new StringBuilder(); + if ( hiddenTokens != null ) + { + for ( int i = 0; i < hiddenTokens.Count; i++ ) + { + IToken hidden = (IToken)hiddenTokens[i]; + buf.Append( hidden.Text ); + } + } + string nodeText = this.ToString(); + if ( !nodeText.Equals( "<EOF>" ) ) + buf.Append( nodeText ); + return buf.ToString(); + } + + /** <summary> + * Print out the leaves of this tree, which means printing original + * input back out. + * </summary> + */ + public virtual string ToInputString() + { + StringBuilder buf = new StringBuilder(); + ToStringLeaves( buf ); + return buf.ToString(); + } + + protected virtual void ToStringLeaves( StringBuilder buf ) + { + if ( payload is IToken ) + { // leaf node token? + buf.Append( this.ToStringWithHiddenTokens() ); + return; + } + for ( int i = 0; Children != null && i < Children.Count; i++ ) + { + ParseTree t = (ParseTree)Children[i]; + t.ToStringLeaves( buf ); + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteCardinalityException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteCardinalityException.cs new file mode 100644 index 0000000..4590287 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteCardinalityException.cs @@ -0,0 +1,96 @@ +/* + * [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.Tree +{ + using ArgumentNullException = System.ArgumentNullException; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary> + * Base class for all exceptions thrown during AST rewrite construction. + * This signifies a case where the cardinality of two or more elements + * in a subrule are different: (ID INT)+ where |ID|!=|INT| + * </summary> + */ + [System.Serializable] + public class RewriteCardinalityException : Exception + { + private readonly string _elementDescription; + + public RewriteCardinalityException() + { + } + + public RewriteCardinalityException(string elementDescription) + : this(elementDescription, elementDescription) + { + this._elementDescription = elementDescription; + } + + public RewriteCardinalityException(string elementDescription, Exception innerException) + : this(elementDescription, elementDescription, innerException) + { + } + + public RewriteCardinalityException(string message, string elementDescription) + : base(message) + { + _elementDescription = elementDescription; + } + + public RewriteCardinalityException(string message, string elementDescription, Exception innerException) + : base(message, innerException) + { + _elementDescription = elementDescription; + } + + protected RewriteCardinalityException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + if (info == null) + throw new ArgumentNullException("info"); + + _elementDescription = info.GetString("ElementDescription"); + } + + public override void GetObjectData(SerializationInfo info, StreamingContext context) + { + if (info == null) + throw new ArgumentNullException("info"); + + base.GetObjectData(info, context); + info.AddValue("ElementDescription", _elementDescription); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteEarlyExitException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteEarlyExitException.cs new file mode 100644 index 0000000..43c51fe --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteEarlyExitException.cs @@ -0,0 +1,72 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Tree +{ + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary>No elements within a (...)+ in a rewrite rule</summary> */ + [System.Serializable] + public class RewriteEarlyExitException : RewriteCardinalityException + { + public RewriteEarlyExitException() + { + } + + public RewriteEarlyExitException(string elementDescription) + : base(elementDescription) + { + } + + public RewriteEarlyExitException(string elementDescription, Exception innerException) + : base(elementDescription, innerException) + { + } + + public RewriteEarlyExitException(string message, string elementDescription) + : base(message, elementDescription) + { + } + + public RewriteEarlyExitException(string message, string elementDescription, Exception innerException) + : base(message, elementDescription, innerException) + { + } + + protected RewriteEarlyExitException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteEmptyStreamException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteEmptyStreamException.cs new file mode 100644 index 0000000..8390cd6 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteEmptyStreamException.cs @@ -0,0 +1,72 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2008 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.Tree +{ + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary>Ref to ID or expr but no tokens in ID stream or subtrees in expr stream</summary> */ + [System.Serializable] + public class RewriteEmptyStreamException : RewriteCardinalityException + { + public RewriteEmptyStreamException() + { + } + + public RewriteEmptyStreamException(string elementDescription) + : base(elementDescription) + { + } + + public RewriteEmptyStreamException(string elementDescription, Exception innerException) + : base(elementDescription, innerException) + { + } + + public RewriteEmptyStreamException(string message, string elementDescription) + : base(message, elementDescription) + { + } + + public RewriteEmptyStreamException(string message, string elementDescription, Exception innerException) + : base(message, elementDescription, innerException) + { + } + + protected RewriteEmptyStreamException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleElementStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleElementStream.cs new file mode 100644 index 0000000..8e3d5b0 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleElementStream.cs @@ -0,0 +1,256 @@ +/* + * [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.Tree +{ + using System.Collections.Generic; + using IList = System.Collections.IList; + + /** <summary> + * A generic list of elements tracked in an alternative to be used in + * a -> rewrite rule. We need to subclass to fill in the next() method, + * which returns either an AST node wrapped around a token payload or + * an existing subtree. + * </summary> + * + * <remarks> + * Once you start next()ing, do not try to add more elements. It will + * break the cursor tracking I believe. + * + * TODO: add mechanism to detect/puke on modification after reading from stream + * </remarks> + * + * <see cref="RewriteRuleSubtreeStream"/> + * <see cref="RewriteRuleTokenStream"/> + */ + [System.Serializable] + public abstract class RewriteRuleElementStream + { + /** <summary> + * Cursor 0..n-1. If singleElement!=null, cursor is 0 until you next(), + * which bumps it to 1 meaning no more elements. + * </summary> + */ + protected int cursor = 0; + + /** <summary>Track single elements w/o creating a list. Upon 2nd add, alloc list */ + protected object singleElement; + + /** <summary>The list of tokens or subtrees we are tracking */ + protected IList elements; + + /** <summary>Once a node / subtree has been used in a stream, it must be dup'd + * from then on. Streams are reset after subrules so that the streams + * can be reused in future subrules. So, reset must set a dirty bit. + * If dirty, then next() always returns a dup. + * + * I wanted to use "naughty bit" here, but couldn't think of a way + * to use "naughty". + */ + protected bool dirty = false; + + /** <summary>The element or stream description; usually has name of the token or + * rule reference that this list tracks. Can include rulename too, but + * the exception would track that info. + */ + protected string elementDescription; + protected ITreeAdaptor adaptor; + + public RewriteRuleElementStream( ITreeAdaptor adaptor, string elementDescription ) + { + this.elementDescription = elementDescription; + this.adaptor = adaptor; + } + + /** <summary>Create a stream with one element</summary> */ + public RewriteRuleElementStream( ITreeAdaptor adaptor, string elementDescription, object oneElement ) + : this( adaptor, elementDescription ) + { + Add( oneElement ); + } + + /** <summary>Create a stream, but feed off an existing list</summary> */ + public RewriteRuleElementStream( ITreeAdaptor adaptor, string elementDescription, IList elements ) + : this( adaptor, elementDescription ) + { + this.singleElement = null; + this.elements = elements; + } + + /** <summary> + * Reset the condition of this stream so that it appears we have + * not consumed any of its elements. Elements themselves are untouched. + * Once we reset the stream, any future use will need duplicates. Set + * the dirty bit. + * </summary> + */ + public virtual void Reset() + { + cursor = 0; + dirty = true; + } + + public virtual void Add( object el ) + { + //System.out.println("add '"+elementDescription+"' is "+el); + if ( el == null ) + { + return; + } + if ( elements != null ) + { // if in list, just add + elements.Add( el ); + return; + } + if ( singleElement == null ) + { // no elements yet, track w/o list + singleElement = el; + return; + } + // adding 2nd element, move to list + elements = new List<object>( 5 ); + elements.Add( singleElement ); + singleElement = null; + elements.Add( el ); + } + + /** <summary> + * Return the next element in the stream. If out of elements, throw + * an exception unless size()==1. If size is 1, then return elements[0]. + * Return a duplicate node/subtree if stream is out of elements and + * size==1. If we've already used the element, dup (dirty bit set). + * </summary> + */ + public virtual object NextTree() + { + int n = Count; + if ( dirty || ( cursor >= n && n == 1 ) ) + { + // if out of elements and size is 1, dup + object el = NextCore(); + return Dup( el ); + } + // test size above then fetch + object el2 = NextCore(); + return el2; + } + + /** <summary> + * Do the work of getting the next element, making sure that it's + * a tree node or subtree. Deal with the optimization of single- + * element list versus list of size > 1. Throw an exception + * if the stream is empty or we're out of elements and size>1. + * protected so you can override in a subclass if necessary. + * </summary> + */ + protected virtual object NextCore() + { + int n = Count; + if ( n == 0 ) + { + throw new RewriteEmptyStreamException( elementDescription ); + } + if ( cursor >= n ) + { // out of elements? + if ( n == 1 ) + { // if size is 1, it's ok; return and we'll dup + return ToTree( singleElement ); + } + // out of elements and size was not 1, so we can't dup + throw new RewriteCardinalityException( elementDescription ); + } + // we have elements + if ( singleElement != null ) + { + cursor++; // move cursor even for single element list + return ToTree( singleElement ); + } + // must have more than one in list, pull from elements + object o = ToTree( elements[cursor] ); + cursor++; + return o; + } + + /** <summary> + * When constructing trees, sometimes we need to dup a token or AST + * subtree. Dup'ing a token means just creating another AST node + * around it. For trees, you must call the adaptor.dupTree() unless + * the element is for a tree root; then it must be a node dup. + * </summary> + */ + protected abstract object Dup( object el ); + + /** <summary> + * Ensure stream emits trees; tokens must be converted to AST nodes. + * AST nodes can be passed through unmolested. + * </summary> + */ + protected virtual object ToTree( object el ) + { + return el; + } + + public virtual bool HasNext + { + get + { + return ( singleElement != null && cursor < 1 ) || + ( elements != null && cursor < elements.Count ); + } + } + + public virtual int Count + { + get + { + int n = 0; + if ( singleElement != null ) + { + n = 1; + } + if ( elements != null ) + { + return elements.Count; + } + return n; + } + } + + public virtual string Description + { + get + { + return elementDescription; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleNodeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleNodeStream.cs new file mode 100644 index 0000000..eb434cc --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleNodeStream.cs @@ -0,0 +1,81 @@ +/* + * [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.Tree +{ + using IList = System.Collections.IList; + using NotSupportedException = System.NotSupportedException; + + /** <summary> + * Queues up nodes matched on left side of -> in a tree parser. This is + * the analog of RewriteRuleTokenStream for normal parsers. + * </summary> + */ + [System.Serializable] + public class RewriteRuleNodeStream : RewriteRuleElementStream + { + + public RewriteRuleNodeStream( ITreeAdaptor adaptor, string elementDescription ) + : base( adaptor, elementDescription ) + { + } + + /** <summary>Create a stream with one element</summary> */ + public RewriteRuleNodeStream( ITreeAdaptor adaptor, string elementDescription, object oneElement ) + : base( adaptor, elementDescription, oneElement ) + { + } + + /** <summary>Create a stream, but feed off an existing list</summary> */ + public RewriteRuleNodeStream( ITreeAdaptor adaptor, string elementDescription, IList elements ) + : base( adaptor, elementDescription, elements ) + { + } + + public virtual object NextNode() + { + return NextCore(); + } + + protected override object ToTree( object el ) + { + return adaptor.DupNode( el ); + } + + protected override object Dup( object el ) + { + // we dup every node, so don't have to worry about calling dup; short- + // circuited next() so it doesn't call. + throw new NotSupportedException( "dup can't be called for a node stream." ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleSubtreeStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleSubtreeStream.cs new file mode 100644 index 0000000..504b891 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleSubtreeStream.cs @@ -0,0 +1,99 @@ +/* + * [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.Tree +{ + using IList = System.Collections.IList; + + [System.Serializable] + public class RewriteRuleSubtreeStream : RewriteRuleElementStream + { + public RewriteRuleSubtreeStream( ITreeAdaptor adaptor, string elementDescription ) + : base( adaptor, elementDescription ) + { + } + + /** <summary>Create a stream with one element</summary> */ + public RewriteRuleSubtreeStream( ITreeAdaptor adaptor, string elementDescription, object oneElement ) + : base( adaptor, elementDescription, oneElement ) + { + } + + /** <summary>Create a stream, but feed off an existing list</summary> */ + public RewriteRuleSubtreeStream( ITreeAdaptor adaptor, string elementDescription, IList elements ) + : base( adaptor, elementDescription, elements ) + { + } + + /** <summary> + * Treat next element as a single node even if it's a subtree. + * This is used instead of next() when the result has to be a + * tree root node. Also prevents us from duplicating recently-added + * children; e.g., ^(type ID)+ adds ID to type and then 2nd iteration + * must dup the type node, but ID has been added. + * </summary> + * + * <remarks> + * Referencing a rule result twice is ok; dup entire tree as + * we can't be adding trees as root; e.g., expr expr. + * + * Hideous code duplication here with super.next(). Can't think of + * a proper way to refactor. This needs to always call dup node + * and super.next() doesn't know which to call: dup node or dup tree. + * </remarks> + */ + public virtual object NextNode() + { + //System.Console.WriteLine("nextNode: elements={0}, singleElement={1}", elements, ((ITree)singleElement).ToStringTree()); + int n = Count; + if ( dirty || ( cursor >= n && n == 1 ) ) + { + // if out of elements and size is 1, dup (at most a single node + // since this is for making root nodes). + object el = NextCore(); + return adaptor.DupNode( el ); + } + // test size above then fetch + object tree = NextCore(); + while (adaptor.IsNil(tree) && adaptor.GetChildCount(tree) == 1) + tree = adaptor.GetChild(tree, 0); + //System.Console.WriteLine("_next={0}", ((ITree)tree).ToStringTree()); + object el2 = adaptor.DupNode(tree); // dup just the root (want node here) + return el2; + } + + protected override object Dup( object el ) + { + return adaptor.DupTree( el ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleTokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleTokenStream.cs new file mode 100644 index 0000000..4441e47 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/RewriteRuleTokenStream.cs @@ -0,0 +1,86 @@ +/* + * [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.Tree +{ + using IList = System.Collections.IList; + using NotSupportedException = System.NotSupportedException; + + [System.Serializable] + public class RewriteRuleTokenStream : RewriteRuleElementStream + { + + public RewriteRuleTokenStream( ITreeAdaptor adaptor, string elementDescription ) + : base( adaptor, elementDescription ) + { + } + + /** <summary>Create a stream with one element</summary> */ + public RewriteRuleTokenStream( ITreeAdaptor adaptor, string elementDescription, object oneElement ) + : base( adaptor, elementDescription, oneElement ) + { + } + + /** <summary>Create a stream, but feed off an existing list</summary> */ + public RewriteRuleTokenStream( ITreeAdaptor adaptor, string elementDescription, IList elements ) + : base( adaptor, elementDescription, elements ) + { + } + + /** <summary>Get next token from stream and make a node for it</summary> */ + public virtual object NextNode() + { + IToken t = (IToken)NextCore(); + return adaptor.Create( t ); + } + + public virtual IToken NextToken() + { + return (IToken)NextCore(); + } + + /** <summary> + * Don't convert to a tree unless they explicitly call nextTree. + * This way we can do hetero tree nodes in rewrite. + * </summary> + */ + protected override object ToTree( object el ) + { + return el; + } + + protected override object Dup( object el ) + { + throw new NotSupportedException( "dup can't be called for a token stream." ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TemplateTreeRuleReturnScope`2.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TemplateTreeRuleReturnScope`2.cs new file mode 100644 index 0000000..96ac54f --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TemplateTreeRuleReturnScope`2.cs @@ -0,0 +1,60 @@ +/* + * [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.Tree +{ + public class TemplateTreeRuleReturnScope<TTemplate, TTree> : TreeRuleReturnScope<TTree>, ITemplateRuleReturnScope<TTemplate>, ITemplateRuleReturnScope + { + private TTemplate _template; + + public TTemplate Template + { + get + { + return _template; + } + + set + { + _template = value; + } + } + + object ITemplateRuleReturnScope.Template + { + get + { + return Template; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeFilter.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeFilter.cs new file mode 100644 index 0000000..ef7b412 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeFilter.cs @@ -0,0 +1,99 @@ +/* + * [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.Tree +{ + using Antlr.Runtime.Misc; + + public class TreeFilter : TreeParser + { + protected ITokenStream originalTokenStream; + protected ITreeAdaptor originalAdaptor; + + public TreeFilter( ITreeNodeStream input ) + : this( input, new RecognizerSharedState() ) + { + } + public TreeFilter( ITreeNodeStream input, RecognizerSharedState state ) + : base( input, state ) + { + originalAdaptor = input.TreeAdaptor; + originalTokenStream = input.TokenStream; + } + + public virtual void ApplyOnce( object t, Action whichRule ) + { + if ( t == null ) + return; + + try + { + // share TreeParser object but not parsing-related state + state = new RecognizerSharedState(); + input = new CommonTreeNodeStream( originalAdaptor, t ); + ( (CommonTreeNodeStream)input ).TokenStream = originalTokenStream; + BacktrackingLevel = 1; + whichRule(); + BacktrackingLevel = 0; + } + catch ( RecognitionException ) + { + } + } + + public virtual void Downup( object t ) + { + TreeVisitor v = new TreeVisitor( new CommonTreeAdaptor() ); + Func<object, object> pre = ( o ) => + { + ApplyOnce( o, Topdown ); + return o; + }; + Func<object, object> post = ( o ) => + { + ApplyOnce( o, Bottomup ); + return o; + }; + v.Visit( t, pre, post ); + } + + // methods the downup strategy uses to do the up and down rules. + // to override, just define tree grammar rule topdown and turn on + // filter=true. + protected virtual void Topdown() + { + } + protected virtual void Bottomup() + { + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeIterator.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeIterator.cs new file mode 100644 index 0000000..02549d5 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeIterator.cs @@ -0,0 +1,180 @@ +/* + * [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.Tree +{ + using System.Collections.Generic; + + /** Return a node stream from a doubly-linked tree whose nodes + * know what child index they are. No remove() is supported. + * + * Emit navigation nodes (DOWN, UP, and EOF) to let show tree structure. + */ + public class TreeIterator : IEnumerator<object> + { + protected ITreeAdaptor adaptor; + protected object root; + protected object tree; + protected bool firstTime = true; + private bool reachedEof; + + // navigation nodes to return during walk and at end + public object up; + public object down; + public object eof; + + /** If we emit UP/DOWN nodes, we need to spit out multiple nodes per + * next() call. + */ + protected Queue<object> nodes; + + public TreeIterator( CommonTree tree ) + : this( new CommonTreeAdaptor(), tree ) + { + } + + public TreeIterator( ITreeAdaptor adaptor, object tree ) + { + this.adaptor = adaptor; + this.tree = tree; + this.root = tree; + nodes = new Queue<object>(); + down = adaptor.Create( TokenTypes.Down, "DOWN" ); + up = adaptor.Create( TokenTypes.Up, "UP" ); + eof = adaptor.Create( TokenTypes.EndOfFile, "EOF" ); + } + + #region IEnumerator<object> Members + + public object Current + { + get; + private set; + } + + #endregion + + #region IDisposable Members + + public void Dispose() + { + } + + #endregion + + #region IEnumerator Members + + public bool MoveNext() + { + if ( firstTime ) + { + // initial condition + firstTime = false; + if ( adaptor.GetChildCount( tree ) == 0 ) + { + // single node tree (special) + nodes.Enqueue( eof ); + } + Current = tree; + } + else + { + // if any queued up, use those first + if ( nodes != null && nodes.Count > 0 ) + { + Current = nodes.Dequeue(); + } + else + { + // no nodes left? + if ( tree == null ) + { + Current = eof; + } + else + { + // next node will be child 0 if any children + if ( adaptor.GetChildCount( tree ) > 0 ) + { + tree = adaptor.GetChild( tree, 0 ); + nodes.Enqueue( tree ); // real node is next after DOWN + Current = down; + } + else + { + // if no children, look for next sibling of tree or ancestor + object parent = adaptor.GetParent( tree ); + // while we're out of siblings, keep popping back up towards root + while ( parent != null && + adaptor.GetChildIndex( tree ) + 1 >= adaptor.GetChildCount( parent ) ) + { + nodes.Enqueue( up ); // we're moving back up + tree = parent; + parent = adaptor.GetParent( tree ); + } + + // no nodes left? + if ( parent == null ) + { + tree = null; // back at root? nothing left then + nodes.Enqueue( eof ); // add to queue, might have UP nodes in there + Current = nodes.Dequeue(); + } + else + { + // must have found a node with an unvisited sibling + // move to it and return it + int nextSiblingIndex = adaptor.GetChildIndex( tree ) + 1; + tree = adaptor.GetChild( parent, nextSiblingIndex ); + nodes.Enqueue( tree ); // add to queue, might have UP nodes in there + Current = nodes.Dequeue(); + } + } + } + } + } + + bool result = Current != eof || !reachedEof; + reachedEof = Current == eof; + return result; + } + + public void Reset() + { + firstTime = true; + tree = root; + nodes.Clear(); + } + + #endregion + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeParser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeParser.cs new file mode 100644 index 0000000..927ee23 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeParser.cs @@ -0,0 +1,209 @@ +/* + * [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.Tree +{ + using ConditionalAttribute = System.Diagnostics.ConditionalAttribute; + using Regex = System.Text.RegularExpressions.Regex; + using RegexOptions = System.Text.RegularExpressions.RegexOptions; + + /** <summary> + * A parser for a stream of tree nodes. "tree grammars" result in a subclass + * of this. All the error reporting and recovery is shared with Parser via + * the BaseRecognizer superclass. + * </summary> + */ + public class TreeParser : BaseRecognizer + { + public const int DOWN = TokenTypes.Down; + public const int UP = TokenTypes.Up; + + // precompiled regex used by inContext + static string dotdot = ".*[^.]\\.\\.[^.].*"; + static string doubleEtc = ".*\\.\\.\\.\\s+\\.\\.\\..*"; + static Regex dotdotPattern = new Regex( dotdot, RegexOptions.Compiled ); + static Regex doubleEtcPattern = new Regex( doubleEtc, RegexOptions.Compiled ); + + protected ITreeNodeStream input; + + public TreeParser( ITreeNodeStream input ) + : base() // highlight that we go to super to set state object + { + SetTreeNodeStream( input ); + } + + public TreeParser( ITreeNodeStream input, RecognizerSharedState state ) + : base( state ) // share the state object with another parser + { + SetTreeNodeStream( input ); + } + + public override void Reset() + { + base.Reset(); // reset all recognizer state variables + if ( input != null ) + { + input.Seek( 0 ); // rewind the input + } + } + + /** <summary>Set the input stream</summary> */ + public virtual void SetTreeNodeStream( ITreeNodeStream input ) + { + this.input = input; + } + + public virtual ITreeNodeStream GetTreeNodeStream() + { + return input; + } + + public override string SourceName + { + get + { + return input.SourceName; + } + } + + protected override object GetCurrentInputSymbol( IIntStream input ) + { + return ( (ITreeNodeStream)input ).LT( 1 ); + } + + protected override object GetMissingSymbol( IIntStream input, + RecognitionException e, + int expectedTokenType, + BitSet follow ) + { + string tokenText = + "<missing " + TokenNames[expectedTokenType] + ">"; + ITreeAdaptor adaptor = ((ITreeNodeStream)e.Input).TreeAdaptor; + return adaptor.Create(new CommonToken(expectedTokenType, tokenText)); + } + + /** <summary> + * Match '.' in tree parser has special meaning. Skip node or + * entire tree if node has children. If children, scan until + * corresponding UP node. + * </summary> + */ + public override void MatchAny( IIntStream ignore ) + { + state.errorRecovery = false; + state.failed = false; + // always consume the current node + input.Consume(); + // if the next node is DOWN, then the current node is a subtree: + // skip to corresponding UP. must count nesting level to get right UP + int look = input.LA( 1 ); + if ( look == DOWN ) + { + input.Consume(); + int level = 1; + while ( level > 0 ) + { + switch ( input.LA( 1 ) ) + { + case DOWN: + level++; + break; + case UP: + level--; + break; + case TokenTypes.EndOfFile: + return; + default: + break; + } + input.Consume(); + } + } + } + + /** <summary> + * We have DOWN/UP nodes in the stream that have no line info; override. + * plus we want to alter the exception type. Don't try to recover + * from tree parser errors inline... + * </summary> + */ + protected override object RecoverFromMismatchedToken( IIntStream input, int ttype, BitSet follow ) + { + throw new MismatchedTreeNodeException( ttype, (ITreeNodeStream)input ); + } + + /** <summary> + * Prefix error message with the grammar name because message is + * always intended for the programmer because the parser built + * the input tree not the user. + * </summary> + */ + public override string GetErrorHeader( RecognitionException e ) + { + return GrammarFileName + ": node from " + + ( e.ApproximateLineInfo ? "after " : "" ) + "line " + e.Line + ":" + e.CharPositionInLine; + } + + /** <summary> + * Tree parsers parse nodes they usually have a token object as + * payload. Set the exception token and do the default behavior. + * </summary> + */ + public override string GetErrorMessage( RecognitionException e, string[] tokenNames ) + { + if ( this is TreeParser ) + { + ITreeAdaptor adaptor = ( (ITreeNodeStream)e.Input ).TreeAdaptor; + e.Token = adaptor.GetToken( e.Node ); + if ( e.Token == null ) + { // could be an UP/DOWN node + e.Token = new CommonToken( adaptor.GetType( e.Node ), + adaptor.GetText( e.Node ) ); + } + } + return base.GetErrorMessage( e, tokenNames ); + } + + [Conditional("ANTLR_TRACE")] + public virtual void TraceIn( string ruleName, int ruleIndex ) + { + base.TraceIn( ruleName, ruleIndex, input.LT( 1 ) ); + } + + [Conditional("ANTLR_TRACE")] + public virtual void TraceOut( string ruleName, int ruleIndex ) + { + base.TraceOut( ruleName, ruleIndex, input.LT( 1 ) ); + } + + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreePatternLexer.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreePatternLexer.cs new file mode 100644 index 0000000..e742205 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreePatternLexer.cs @@ -0,0 +1,162 @@ +/* + * [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.Tree +{ + using StringBuilder = System.Text.StringBuilder; + + public class TreePatternLexer + { + public const int Begin = 1; + public const int End = 2; + public const int Id = 3; + public const int Arg = 4; + public const int Percent = 5; + public const int Colon = 6; + public const int Dot = 7; + + /** <summary>The tree pattern to lex like "(A B C)"</summary> */ + protected string pattern; + + /** <summary>Index into input string</summary> */ + protected int p = -1; + + /** <summary>Current char</summary> */ + protected int c; + + /** <summary>How long is the pattern in char?</summary> */ + protected int n; + + /** <summary>Set when token type is ID or ARG (name mimics Java's StreamTokenizer)</summary> */ + public StringBuilder sval = new StringBuilder(); + + public bool error = false; + + public TreePatternLexer( string pattern ) + { + this.pattern = pattern; + this.n = pattern.Length; + Consume(); + } + + public virtual int NextToken() + { + sval.Length = 0; // reset, but reuse buffer + while ( c != CharStreamConstants.EndOfFile ) + { + if ( c == ' ' || c == '\n' || c == '\r' || c == '\t' ) + { + Consume(); + continue; + } + if ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || c == '_' ) + { + sval.Append( (char)c ); + Consume(); + while ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) || + ( c >= '0' && c <= '9' ) || c == '_' ) + { + sval.Append( (char)c ); + Consume(); + } + return Id; + } + if ( c == '(' ) + { + Consume(); + return Begin; + } + if ( c == ')' ) + { + Consume(); + return End; + } + if ( c == '%' ) + { + Consume(); + return Percent; + } + if ( c == ':' ) + { + Consume(); + return Colon; + } + if ( c == '.' ) + { + Consume(); + return Dot; + } + if ( c == '[' ) + { + // grab [x] as a string, returning x + Consume(); + while ( c != ']' ) + { + if ( c == '\\' ) + { + Consume(); + if ( c != ']' ) + { + sval.Append( '\\' ); + } + sval.Append( (char)c ); + } + else + { + sval.Append( (char)c ); + } + Consume(); + } + Consume(); + return Arg; + } + Consume(); + error = true; + return CharStreamConstants.EndOfFile; + } + return CharStreamConstants.EndOfFile; + } + + protected virtual void Consume() + { + p++; + if ( p >= n ) + { + c = CharStreamConstants.EndOfFile; + } + else + { + c = pattern[p]; + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreePatternParser.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreePatternParser.cs new file mode 100644 index 0000000..5112335 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreePatternParser.cs @@ -0,0 +1,183 @@ +/* + * [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.Tree +{ + using InvalidOperationException = System.InvalidOperationException; + + public class TreePatternParser + { + protected TreePatternLexer tokenizer; + protected int ttype; + protected TreeWizard wizard; + protected ITreeAdaptor adaptor; + + public TreePatternParser( TreePatternLexer tokenizer, TreeWizard wizard, ITreeAdaptor adaptor ) + { + this.tokenizer = tokenizer; + this.wizard = wizard; + this.adaptor = adaptor; + ttype = tokenizer.NextToken(); // kickstart + } + + public virtual object Pattern() + { + if ( ttype == TreePatternLexer.Begin ) + { + return ParseTree(); + } + else if ( ttype == TreePatternLexer.Id ) + { + object node = ParseNode(); + if ( ttype == CharStreamConstants.EndOfFile ) + { + return node; + } + return null; // extra junk on end + } + return null; + } + + public virtual object ParseTree() + { + if ( ttype != TreePatternLexer.Begin ) + throw new InvalidOperationException("No beginning."); + + ttype = tokenizer.NextToken(); + object root = ParseNode(); + if ( root == null ) + { + return null; + } + while ( ttype == TreePatternLexer.Begin || + ttype == TreePatternLexer.Id || + ttype == TreePatternLexer.Percent || + ttype == TreePatternLexer.Dot ) + { + if ( ttype == TreePatternLexer.Begin ) + { + object subtree = ParseTree(); + adaptor.AddChild( root, subtree ); + } + else + { + object child = ParseNode(); + if ( child == null ) + { + return null; + } + adaptor.AddChild( root, child ); + } + } + + if ( ttype != TreePatternLexer.End ) + throw new InvalidOperationException("No end."); + + ttype = tokenizer.NextToken(); + return root; + } + + public virtual object ParseNode() + { + // "%label:" prefix + string label = null; + if ( ttype == TreePatternLexer.Percent ) + { + ttype = tokenizer.NextToken(); + if ( ttype != TreePatternLexer.Id ) + { + return null; + } + label = tokenizer.sval.ToString(); + ttype = tokenizer.NextToken(); + if ( ttype != TreePatternLexer.Colon ) + { + return null; + } + ttype = tokenizer.NextToken(); // move to ID following colon + } + + // Wildcard? + if ( ttype == TreePatternLexer.Dot ) + { + ttype = tokenizer.NextToken(); + IToken wildcardPayload = new CommonToken( 0, "." ); + TreeWizard.TreePattern node = + new TreeWizard.WildcardTreePattern( wildcardPayload ); + if ( label != null ) + { + node.label = label; + } + return node; + } + + // "ID" or "ID[arg]" + if ( ttype != TreePatternLexer.Id ) + { + return null; + } + string tokenName = tokenizer.sval.ToString(); + ttype = tokenizer.NextToken(); + if ( tokenName.Equals( "nil" ) ) + { + return adaptor.Nil(); + } + string text = tokenName; + // check for arg + string arg = null; + if ( ttype == TreePatternLexer.Arg ) + { + arg = tokenizer.sval.ToString(); + text = arg; + ttype = tokenizer.NextToken(); + } + + // create node + int treeNodeType = wizard.GetTokenType( tokenName ); + if ( treeNodeType == TokenTypes.Invalid ) + { + return null; + } + object node2; + node2 = adaptor.Create( treeNodeType, text ); + if ( label != null && node2.GetType() == typeof( TreeWizard.TreePattern ) ) + { + ( (TreeWizard.TreePattern)node2 ).label = label; + } + if ( arg != null && node2.GetType() == typeof( TreeWizard.TreePattern ) ) + { + ( (TreeWizard.TreePattern)node2 ).hasTextArg = true; + } + return node2; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRewriter.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRewriter.cs new file mode 100644 index 0000000..b610c2c --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRewriter.cs @@ -0,0 +1,144 @@ +/* + * [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.Tree +{ + using Antlr.Runtime.Misc; + + using Console = System.Console; + + public class TreeRewriter : TreeParser + { + protected bool showTransformations; + + protected ITokenStream originalTokenStream; + protected ITreeAdaptor originalAdaptor; + + Func<IAstRuleReturnScope> topdown_func; + Func<IAstRuleReturnScope> bottomup_func; + + public TreeRewriter( ITreeNodeStream input ) + : this( input, new RecognizerSharedState() ) + { + } + public TreeRewriter( ITreeNodeStream input, RecognizerSharedState state ) + : base( input, state ) + { + originalAdaptor = input.TreeAdaptor; + originalTokenStream = input.TokenStream; + topdown_func = () => Topdown(); + bottomup_func = () => Bottomup(); + } + + public virtual object ApplyOnce( object t, Func<IAstRuleReturnScope> whichRule ) + { + if ( t == null ) + return null; + + try + { + // share TreeParser object but not parsing-related state + state = new RecognizerSharedState(); + input = new CommonTreeNodeStream( originalAdaptor, t ); + ( (CommonTreeNodeStream)input ).TokenStream = originalTokenStream; + BacktrackingLevel = 1; + IAstRuleReturnScope r = whichRule(); + BacktrackingLevel = 0; + if ( Failed ) + return t; + + if (showTransformations && r != null && !t.Equals(r.Tree) && r.Tree != null) + ReportTransformation(t, r.Tree); + + if ( r != null && r.Tree != null ) + return r.Tree; + else + return t; + } + catch ( RecognitionException ) + { + } + + return t; + } + + public virtual object ApplyRepeatedly( object t, Func<IAstRuleReturnScope> whichRule ) + { + bool treeChanged = true; + while ( treeChanged ) + { + object u = ApplyOnce( t, whichRule ); + treeChanged = !t.Equals( u ); + t = u; + } + return t; + } + + public virtual object Downup( object t ) + { + return Downup( t, false ); + } + + public virtual object Downup( object t, bool showTransformations ) + { + this.showTransformations = showTransformations; + TreeVisitor v = new TreeVisitor( new CommonTreeAdaptor() ); + t = v.Visit( t, ( o ) => ApplyOnce( o, topdown_func ), ( o ) => ApplyRepeatedly( o, bottomup_func ) ); + return t; + } + + // methods the downup strategy uses to do the up and down rules. + // to override, just define tree grammar rule topdown and turn on + // filter=true. + public virtual IAstRuleReturnScope Topdown() + { + return null; + } + + public virtual IAstRuleReturnScope Bottomup() + { + return null; + } + + /** Override this if you need transformation tracing to go somewhere + * other than stdout or if you're not using ITree-derived trees. + */ + protected virtual void ReportTransformation(object oldTree, object newTree) + { + ITree old = oldTree as ITree; + ITree @new = newTree as ITree; + string oldMessage = old != null ? old.ToStringTree() : "??"; + string newMessage = @new != null ? @new.ToStringTree() : "??"; + Console.WriteLine("{0} -> {1}", oldMessage, newMessage); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRuleReturnScope`1.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRuleReturnScope`1.cs new file mode 100644 index 0000000..2a928e2 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeRuleReturnScope`1.cs @@ -0,0 +1,84 @@ +/* + * [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.Tree +{ + /** <summary> + * This is identical to the ParserRuleReturnScope except that + * the start property is a tree nodes not Token object + * when you are parsing trees. + * </summary> + */ + [System.Serializable] + public class TreeRuleReturnScope<TTree> : IRuleReturnScope<TTree> + { + private TTree _start; + + /** <summary>Gets the first node or root node of tree matched for this rule.</summary> */ + public TTree Start + { + get + { + return _start; + } + + set + { + _start = value; + } + } + + object IRuleReturnScope.Start + { + get + { + return Start; + } + } + + TTree IRuleReturnScope<TTree>.Stop + { + get + { + return default(TTree); + } + } + + object IRuleReturnScope.Stop + { + get + { + return default(TTree); + } + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeVisitor.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeVisitor.cs new file mode 100644 index 0000000..f6e49ea --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeVisitor.cs @@ -0,0 +1,83 @@ +/* + * [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.Tree +{ + using Antlr.Runtime.Misc; + + /** <summary>Do a depth first walk of a tree, applying pre() and post() actions as we go.</summary> */ + public class TreeVisitor + { + protected ITreeAdaptor adaptor; + + public TreeVisitor( ITreeAdaptor adaptor ) + { + this.adaptor = adaptor; + } + public TreeVisitor() + : this( new CommonTreeAdaptor() ) + { + } + + /** <summary> + * Visit every node in tree t and trigger an action for each node + * before/after having visited all of its children. Bottom up walk. + * Execute both actions even if t has no children. Ignore return + * results from transforming children since they will have altered + * the child list of this node (their parent). Return result of + * applying post action to this node. + * </summary> + */ + public object Visit( object t, ITreeVisitorAction action ) + { + // System.out.println("visit "+((Tree)t).toStringTree()); + bool isNil = adaptor.IsNil( t ); + if ( action != null && !isNil ) + { + t = action.Pre( t ); // if rewritten, walk children of new t + } + for ( int i = 0; i < adaptor.GetChildCount(t); i++ ) + { + object child = adaptor.GetChild( t, i ); + Visit( child, action ); + } + if ( action != null && !isNil ) + t = action.Post( t ); + return t; + } + + public object Visit( object t, Func<object, object> preAction, Func<object, object> postAction ) + { + return Visit( t, new TreeVisitorAction( preAction, postAction ) ); + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeWizard.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeWizard.cs new file mode 100644 index 0000000..98c759b --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/Tree/TreeWizard.cs @@ -0,0 +1,736 @@ +/* + * [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. + */ + +// TODO: build indexes for wizard +//#define BUILD_INDEXES + +namespace Antlr.Runtime.Tree +{ + using System.Collections.Generic; + + using IList = System.Collections.IList; +#if BUILD_INDEXES + using IDictionary = System.Collections.IDictionary; +#endif + + /** <summary> + * Build and navigate trees with this object. Must know about the names + * of tokens so you have to pass in a map or array of token names (from which + * this class can build the map). I.e., Token DECL means nothing unless the + * class can translate it to a token type. + * </summary> + * + * <remarks> + * In order to create nodes and navigate, this class needs a TreeAdaptor. + * + * This class can build a token type -> node index for repeated use or for + * iterating over the various nodes with a particular type. + * + * This class works in conjunction with the TreeAdaptor rather than moving + * all this functionality into the adaptor. An adaptor helps build and + * navigate trees using methods. This class helps you do it with string + * patterns like "(A B C)". You can create a tree from that pattern or + * match subtrees against it. + * </remarks> + */ + public class TreeWizard + { + protected ITreeAdaptor adaptor; + protected IDictionary<string, int> tokenNameToTypeMap; + + public interface IContextVisitor + { + // TODO: should this be called visit or something else? + void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels ); + } + + public abstract class Visitor : IContextVisitor + { + public virtual void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels ) + { + Visit( t ); + } + public abstract void Visit( object t ); + } + + class ActionVisitor : Visitor + { + System.Action<object> _action; + + public ActionVisitor( System.Action<object> action ) + { + _action = action; + } + + public override void Visit( object t ) + { + _action( t ); + } + } + + /** <summary> + * When using %label:TOKENNAME in a tree for parse(), we must + * track the label. + * </summary> + */ + public class TreePattern : CommonTree + { + public string label; + public bool hasTextArg; + public TreePattern( IToken payload ) : + base( payload ) + { + } + public override string ToString() + { + if ( label != null ) + { + return "%" + label + ":"; //+ base.ToString(); + } + else + { + return base.ToString(); + } + } + } + + public class WildcardTreePattern : TreePattern + { + public WildcardTreePattern( IToken payload ) : + base( payload ) + { + } + } + + /** <summary>This adaptor creates TreePattern objects for use during scan()</summary> */ + public class TreePatternTreeAdaptor : CommonTreeAdaptor + { + public override object Create( IToken payload ) + { + return new TreePattern( payload ); + } + } + +#if BUILD_INDEXES + // TODO: build indexes for the wizard + + /** <summary> + * During fillBuffer(), we can make a reverse index from a set + * of token types of interest to the list of indexes into the + * node stream. This lets us convert a node pointer to a + * stream index semi-efficiently for a list of interesting + * nodes such as function definition nodes (you'll want to seek + * to their bodies for an interpreter). Also useful for doing + * dynamic searches; i.e., go find me all PLUS nodes. + * </summary> + */ + protected IDictionary<int, IList<int>> tokenTypeToStreamIndexesMap; + + /** <summary> + * If tokenTypesToReverseIndex set to INDEX_ALL then indexing + * occurs for all token types. + * </summary> + */ + public static readonly HashSet<int> INDEX_ALL = new HashSet<int>(); + + /** <summary> + * A set of token types user would like to index for faster lookup. + * If this is INDEX_ALL, then all token types are tracked. If null, + * then none are indexed. + * </summary> + */ + protected HashSet<int> tokenTypesToReverseIndex = null; +#endif + + public TreeWizard( ITreeAdaptor adaptor ) + { + this.adaptor = adaptor; + } + + public TreeWizard( ITreeAdaptor adaptor, IDictionary<string, int> tokenNameToTypeMap ) + { + this.adaptor = adaptor; + this.tokenNameToTypeMap = tokenNameToTypeMap; + } + + public TreeWizard( ITreeAdaptor adaptor, string[] tokenNames ) + { + this.adaptor = adaptor; + this.tokenNameToTypeMap = ComputeTokenTypes( tokenNames ); + } + + public TreeWizard( string[] tokenNames ) + : this( new CommonTreeAdaptor(), tokenNames ) + { + } + + /** <summary> + * Compute a Map<String, Integer> that is an inverted index of + * tokenNames (which maps int token types to names). + * </summary> + */ + public virtual IDictionary<string, int> ComputeTokenTypes( string[] tokenNames ) + { + IDictionary<string, int> m = new Dictionary<string, int>(); + if ( tokenNames == null ) + { + return m; + } + for ( int ttype = TokenTypes.Min; ttype < tokenNames.Length; ttype++ ) + { + string name = tokenNames[ttype]; + m[name] = ttype; + } + return m; + } + + /** <summary>Using the map of token names to token types, return the type.</summary> */ + public virtual int GetTokenType( string tokenName ) + { + if ( tokenNameToTypeMap == null ) + { + return TokenTypes.Invalid; + } + + int value; + if ( tokenNameToTypeMap.TryGetValue( tokenName, out value ) ) + return value; + + return TokenTypes.Invalid; + } + + /** <summary> + * Walk the entire tree and make a node name to nodes mapping. + * For now, use recursion but later nonrecursive version may be + * more efficient. Returns Map<Integer, List> where the List is + * of your AST node type. The Integer is the token type of the node. + * </summary> + * + * <remarks> + * TODO: save this index so that find and visit are faster + * </remarks> + */ + public IDictionary<int, IList> Index( object t ) + { + IDictionary<int, IList> m = new Dictionary<int, IList>(); + IndexCore( t, m ); + return m; + } + + /** <summary>Do the work for index</summary> */ + protected virtual void IndexCore( object t, IDictionary<int, IList> m ) + { + if ( t == null ) + { + return; + } + int ttype = adaptor.GetType( t ); + IList elements; + if ( !m.TryGetValue( ttype, out elements ) || elements == null ) + { + elements = new List<object>(); + m[ttype] = elements; + } + elements.Add( t ); + int n = adaptor.GetChildCount( t ); + for ( int i = 0; i < n; i++ ) + { + object child = adaptor.GetChild( t, i ); + IndexCore( child, m ); + } + } + + class FindTreeWizardVisitor : TreeWizard.Visitor + { + IList _nodes; + public FindTreeWizardVisitor( IList nodes ) + { + _nodes = nodes; + } + public override void Visit( object t ) + { + _nodes.Add( t ); + } + } + class FindTreeWizardContextVisitor : TreeWizard.IContextVisitor + { + TreeWizard _outer; + TreePattern _tpattern; + IList _subtrees; + public FindTreeWizardContextVisitor( TreeWizard outer, TreePattern tpattern, IList subtrees ) + { + _outer = outer; + _tpattern = tpattern; + _subtrees = subtrees; + } + + public void Visit( object t, object parent, int childIndex, IDictionary<string, object> labels ) + { + if ( _outer.ParseCore( t, _tpattern, null ) ) + { + _subtrees.Add( t ); + } + } + } + + /** <summary>Return a List of tree nodes with token type ttype</summary> */ + public virtual IList Find( object t, int ttype ) + { + IList nodes = new List<object>(); + Visit( t, ttype, new FindTreeWizardVisitor( nodes ) ); + return nodes; + } + + /** <summary>Return a List of subtrees matching pattern.</summary> */ + public virtual IList Find( object t, string pattern ) + { + IList subtrees = new List<object>(); + // Create a TreePattern from the pattern + TreePatternLexer tokenizer = new TreePatternLexer( pattern ); + TreePatternParser parser = + new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() ); + TreePattern tpattern = (TreePattern)parser.Pattern(); + // don't allow invalid patterns + if ( tpattern == null || + tpattern.IsNil || + tpattern.GetType() == typeof( WildcardTreePattern ) ) + { + return null; + } + int rootTokenType = tpattern.Type; + Visit( t, rootTokenType, new FindTreeWizardContextVisitor( this, tpattern, subtrees ) ); + return subtrees; + } + + public virtual object FindFirst( object t, int ttype ) + { + return null; + } + + public virtual object FindFirst( object t, string pattern ) + { + return null; + } + + /** <summary> + * Visit every ttype node in t, invoking the visitor. This is a quicker + * version of the general visit(t, pattern) method. The labels arg + * of the visitor action method is never set (it's null) since using + * a token type rather than a pattern doesn't let us set a label. + * </summary> + */ + public void Visit( object t, int ttype, IContextVisitor visitor ) + { + VisitCore( t, null, 0, ttype, visitor ); + } + + public void Visit( object t, int ttype, System.Action<object> action ) + { + Visit( t, ttype, new ActionVisitor( action ) ); + } + + /** <summary>Do the recursive work for visit</summary> */ + protected virtual void VisitCore( object t, object parent, int childIndex, int ttype, IContextVisitor visitor ) + { + if ( t == null ) + { + return; + } + if ( adaptor.GetType( t ) == ttype ) + { + visitor.Visit( t, parent, childIndex, null ); + } + int n = adaptor.GetChildCount( t ); + for ( int i = 0; i < n; i++ ) + { + object child = adaptor.GetChild( t, i ); + VisitCore( child, t, i, ttype, visitor ); + } + } + + class VisitTreeWizardContextVisitor : TreeWizard.IContextVisitor + { + TreeWizard _outer; + IContextVisitor _visitor; + IDictionary<string, object> _labels; + TreePattern _tpattern; + + public VisitTreeWizardContextVisitor( TreeWizard outer, IContextVisitor visitor, IDictionary<string, object> labels, TreePattern tpattern ) + { + _outer = outer; + _visitor = visitor; + _labels = labels; + _tpattern = tpattern; + } + + public void Visit( object t, object parent, int childIndex, IDictionary<string, object> unusedlabels ) + { + // the unusedlabels arg is null as visit on token type doesn't set. + _labels.Clear(); + if ( _outer.ParseCore( t, _tpattern, _labels ) ) + { + _visitor.Visit( t, parent, childIndex, _labels ); + } + } + } + + /** <summary> + * For all subtrees that match the pattern, execute the visit action. + * The implementation uses the root node of the pattern in combination + * with visit(t, ttype, visitor) so nil-rooted patterns are not allowed. + * Patterns with wildcard roots are also not allowed. + * </summary> + */ + public void Visit( object t, string pattern, IContextVisitor visitor ) + { + // Create a TreePattern from the pattern + TreePatternLexer tokenizer = new TreePatternLexer( pattern ); + TreePatternParser parser = + new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() ); + TreePattern tpattern = (TreePattern)parser.Pattern(); + // don't allow invalid patterns + if ( tpattern == null || + tpattern.IsNil || + tpattern.GetType() == typeof( WildcardTreePattern ) ) + { + return; + } + IDictionary<string, object> labels = new Dictionary<string, object>(); // reused for each _parse + int rootTokenType = tpattern.Type; + Visit( t, rootTokenType, new VisitTreeWizardContextVisitor( this, visitor, labels, tpattern ) ); + } + + /** <summary> + * Given a pattern like (ASSIGN %lhs:ID %rhs:.) with optional labels + * on the various nodes and '.' (dot) as the node/subtree wildcard, + * return true if the pattern matches and fill the labels Map with + * the labels pointing at the appropriate nodes. Return false if + * the pattern is malformed or the tree does not match. + * </summary> + * + * <remarks> + * If a node specifies a text arg in pattern, then that must match + * for that node in t. + * + * TODO: what's a better way to indicate bad pattern? Exceptions are a hassle + * </remarks> + */ + public bool Parse( object t, string pattern, IDictionary<string, object> labels ) + { + TreePatternLexer tokenizer = new TreePatternLexer( pattern ); + TreePatternParser parser = + new TreePatternParser( tokenizer, this, new TreePatternTreeAdaptor() ); + TreePattern tpattern = (TreePattern)parser.Pattern(); + /* + System.out.println("t="+((Tree)t).toStringTree()); + System.out.println("scant="+tpattern.toStringTree()); + */ + bool matched = ParseCore( t, tpattern, labels ); + return matched; + } + + public bool Parse( object t, string pattern ) + { + return Parse( t, pattern, null ); + } + + /** <summary> + * Do the work for parse. Check to see if the t2 pattern fits the + * structure and token types in t1. Check text if the pattern has + * text arguments on nodes. Fill labels map with pointers to nodes + * in tree matched against nodes in pattern with labels. + * </summary> + */ + protected virtual bool ParseCore( object t1, TreePattern tpattern, IDictionary<string, object> labels ) + { + // make sure both are non-null + if ( t1 == null || tpattern == null ) + { + return false; + } + // check roots (wildcard matches anything) + if ( tpattern.GetType() != typeof( WildcardTreePattern ) ) + { + if ( adaptor.GetType( t1 ) != tpattern.Type ) + { + return false; + } + // if pattern has text, check node text + if ( tpattern.hasTextArg && !adaptor.GetText( t1 ).Equals( tpattern.Text ) ) + { + return false; + } + } + if ( tpattern.label != null && labels != null ) + { + // map label in pattern to node in t1 + labels[tpattern.label] = t1; + } + // check children + int n1 = adaptor.GetChildCount( t1 ); + int n2 = tpattern.ChildCount; + if ( n1 != n2 ) + { + return false; + } + for ( int i = 0; i < n1; i++ ) + { + object child1 = adaptor.GetChild( t1, i ); + TreePattern child2 = (TreePattern)tpattern.GetChild( i ); + if ( !ParseCore( child1, child2, labels ) ) + { + return false; + } + } + return true; + } + + /** <summary> + * Create a tree or node from the indicated tree pattern that closely + * follows ANTLR tree grammar tree element syntax: + * + * (root child1 ... child2). + * </summary> + * + * <remarks> + * You can also just pass in a node: ID + * + * Any node can have a text argument: ID[foo] + * (notice there are no quotes around foo--it's clear it's a string). + * + * nil is a special name meaning "give me a nil node". Useful for + * making lists: (nil A B C) is a list of A B C. + * </remarks> + */ + public virtual object Create( string pattern ) + { + TreePatternLexer tokenizer = new TreePatternLexer( pattern ); + TreePatternParser parser = new TreePatternParser( tokenizer, this, adaptor ); + object t = parser.Pattern(); + return t; + } + + /** <summary> + * Compare t1 and t2; return true if token types/text, structure match exactly. + * The trees are examined in their entirety so that (A B) does not match + * (A B C) nor (A (B C)). + * </summary> + * + * <remarks> + * TODO: allow them to pass in a comparator + * TODO: have a version that is nonstatic so it can use instance adaptor + * + * I cannot rely on the tree node's equals() implementation as I make + * no constraints at all on the node types nor interface etc... + * </remarks> + */ + public static bool Equals( object t1, object t2, ITreeAdaptor adaptor ) + { + return EqualsCore( t1, t2, adaptor ); + } + + /** <summary> + * Compare type, structure, and text of two trees, assuming adaptor in + * this instance of a TreeWizard. + * </summary> + */ + public new bool Equals( object t1, object t2 ) + { + return EqualsCore( t1, t2, adaptor ); + } + + protected static bool EqualsCore( object t1, object t2, ITreeAdaptor adaptor ) + { + // make sure both are non-null + if ( t1 == null || t2 == null ) + { + return false; + } + // check roots + if ( adaptor.GetType( t1 ) != adaptor.GetType( t2 ) ) + { + return false; + } + if ( !adaptor.GetText( t1 ).Equals( adaptor.GetText( t2 ) ) ) + { + return false; + } + // check children + int n1 = adaptor.GetChildCount( t1 ); + int n2 = adaptor.GetChildCount( t2 ); + if ( n1 != n2 ) + { + return false; + } + for ( int i = 0; i < n1; i++ ) + { + object child1 = adaptor.GetChild( t1, i ); + object child2 = adaptor.GetChild( t2, i ); + if ( !EqualsCore( child1, child2, adaptor ) ) + { + return false; + } + } + return true; + } + +#if BUILD_INDEXES + // TODO: next stuff taken from CommonTreeNodeStream + + /** <summary> + * Given a node, add this to the reverse index tokenTypeToStreamIndexesMap. + * You can override this method to alter how indexing occurs. The + * default is to create a + * + * Map<Integer token type,ArrayList<Integer stream index>> + * </summary> + * + * <remarks> + * This data structure allows you to find all nodes with type INT in order. + * + * If you really need to find a node of type, say, FUNC quickly then perhaps + * + * Map<Integertoken type,Map<Object tree node,Integer stream index>> + * + * would be better for you. The interior maps map a tree node to + * the index so you don't have to search linearly for a specific node. + * + * If you change this method, you will likely need to change + * getNodeIndex(), which extracts information. + * </remarks> + */ + protected void fillReverseIndex( object node, int streamIndex ) + { + //System.out.println("revIndex "+node+"@"+streamIndex); + if ( tokenTypesToReverseIndex == null ) + { + return; // no indexing if this is empty (nothing of interest) + } + if ( tokenTypeToStreamIndexesMap == null ) + { + tokenTypeToStreamIndexesMap = new Dictionary<int, IList<int>>(); // first indexing op + } + int tokenType = adaptor.getType( node ); + if ( !( tokenTypesToReverseIndex == INDEX_ALL || + tokenTypesToReverseIndex.Contains( tokenType ) ) ) + { + return; // tokenType not of interest + } + IList<int> indexes; + + if ( !tokenTypeToStreamIndexesMap.TryGetValue( tokenType, out indexes ) || indexes == null ) + { + indexes = new List<int>(); // no list yet for this token type + indexes.Add( streamIndex ); // not there yet, add + tokenTypeToStreamIndexesMap[tokenType] = indexes; + } + else + { + if ( !indexes.Contains( streamIndex ) ) + { + indexes.Add( streamIndex ); // not there yet, add + } + } + } + + /** <summary> + * Track the indicated token type in the reverse index. Call this + * repeatedly for each type or use variant with Set argument to + * set all at once. + * </summary> + * + * <param name="tokenType" /> + */ + public void reverseIndex( int tokenType ) + { + if ( tokenTypesToReverseIndex == null ) + { + tokenTypesToReverseIndex = new HashSet<int>(); + } + else if ( tokenTypesToReverseIndex == INDEX_ALL ) + { + return; + } + tokenTypesToReverseIndex.add( tokenType ); + } + + /** <summary> + * Track the indicated token types in the reverse index. Set + * to INDEX_ALL to track all token types. + * </summary> + */ + public void reverseIndex( HashSet<int> tokenTypes ) + { + tokenTypesToReverseIndex = tokenTypes; + } + + /** <summary> + * Given a node pointer, return its index into the node stream. + * This is not its Token stream index. If there is no reverse map + * from node to stream index or the map does not contain entries + * for node's token type, a linear search of entire stream is used. + * </summary> + * + * <remarks> + * Return -1 if exact node pointer not in stream. + * </remarks> + */ + public int getNodeIndex( object node ) + { + //System.out.println("get "+node); + if ( tokenTypeToStreamIndexesMap == null ) + { + return getNodeIndexLinearly( node ); + } + int tokenType = adaptor.getType( node ); + IList<int> indexes; + if ( !tokenTypeToStreamIndexesMap.TryGetValue( tokenType, out indexes ) || indexes == null ) + { + //System.out.println("found linearly; stream index = "+getNodeIndexLinearly(node)); + return getNodeIndexLinearly( node ); + } + for ( int i = 0; i < indexes.size(); i++ ) + { + int streamIndex = indexes[i]; + object n = get( streamIndex ); + if ( n == node ) + { + //System.out.println("found in index; stream index = "+streamIndexI); + return streamIndex; // found it! + } + } + return -1; + } +#endif + + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/UnbufferedTokenStream.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/UnbufferedTokenStream.cs new file mode 100644 index 0000000..c1bfcb2 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/UnbufferedTokenStream.cs @@ -0,0 +1,172 @@ +/* + * [The "BSD licence"] + * Copyright (c) 2005-2008 Terence Parr + * All rights reserved. + * + * Conversion to C#: + * Copyright (c) 2009 Sam Harwell + * 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 +{ + using Antlr.Runtime.Misc; + using CLSCompliant = System.CLSCompliantAttribute; + using NotSupportedException = System.NotSupportedException; + using IndexOutOfRangeException = System.IndexOutOfRangeException; + + /** A token stream that pulls tokens from the code source on-demand and + * without tracking a complete buffer of the tokens. This stream buffers + * the minimum number of tokens possible. It's the same as + * OnDemandTokenStream except that OnDemandTokenStream buffers all tokens. + * + * You can't use this stream if you pass whitespace or other off-channel + * tokens to the parser. The stream can't ignore off-channel tokens. + * + * You can only look backwards 1 token: LT(-1). + * + * Use this when you need to read from a socket or other infinite stream. + * + * @see BufferedTokenStream + * @see CommonTokenStream + */ + public class UnbufferedTokenStream : LookaheadStream<IToken>, ITokenStream, ITokenStreamInformation + { + [CLSCompliant(false)] + protected ITokenSource tokenSource; + protected int tokenIndex; // simple counter to set token index in tokens + + /** Skip tokens on any channel but this one; this is how we skip whitespace... */ + protected int channel = TokenChannels.Default; + + private readonly ListStack<IToken> _realTokens = new ListStack<IToken>() { null }; + + public UnbufferedTokenStream(ITokenSource tokenSource) + { + this.tokenSource = tokenSource; + } + + public ITokenSource TokenSource + { + get + { + return this.tokenSource; + } + } + + public string SourceName + { + get + { + return TokenSource.SourceName; + } + } + + #region ITokenStreamInformation Members + + public IToken LastToken + { + get + { + return LB(1); + } + } + + public IToken LastRealToken + { + get + { + return _realTokens.Peek(); + } + } + + public int MaxLookBehind + { + get + { + return 1; + } + } + + public override int Mark() + { + _realTokens.Push(_realTokens.Peek()); + return base.Mark(); + } + + public override void Release(int marker) + { + base.Release(marker); + _realTokens.Pop(); + } + + public override void Clear() + { + _realTokens.Clear(); + _realTokens.Push(null); + } + + public override void Consume() + { + base.Consume(); + if (PreviousElement != null && PreviousElement.Line > 0) + _realTokens[_realTokens.Count - 1] = PreviousElement; + } + + #endregion + + public override IToken NextElement() + { + IToken t = this.tokenSource.NextToken(); + t.TokenIndex = this.tokenIndex++; + return t; + } + + public override bool IsEndOfFile(IToken o) + { + return o.Type == CharStreamConstants.EndOfFile; + } + + public IToken Get(int i) + { + throw new NotSupportedException("Absolute token indexes are meaningless in an unbuffered stream"); + } + + public int LA(int i) + { + return LT(i).Type; + } + + public string ToString(int start, int stop) + { + return "n/a"; + } + + public string ToString(IToken start, IToken stop) + { + return "n/a"; + } + } +} diff --git a/runtime/CSharp3/Sources/Antlr3.Runtime/UnwantedTokenException.cs b/runtime/CSharp3/Sources/Antlr3.Runtime/UnwantedTokenException.cs new file mode 100644 index 0000000..89b3481 --- /dev/null +++ b/runtime/CSharp3/Sources/Antlr3.Runtime/UnwantedTokenException.cs @@ -0,0 +1,109 @@ +/* + * [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 +{ + using System.Collections.Generic; + using Exception = System.Exception; + using SerializationInfo = System.Runtime.Serialization.SerializationInfo; + using StreamingContext = System.Runtime.Serialization.StreamingContext; + + /** <summary>An extra token while parsing a TokenStream</summary> */ + [System.Serializable] + public class UnwantedTokenException : MismatchedTokenException + { + public UnwantedTokenException() + { + } + + public UnwantedTokenException(string message) + : base(message) + { + } + + public UnwantedTokenException(string message, Exception innerException) + : base(message, innerException) + { + } + + public UnwantedTokenException(int expecting, IIntStream input) + : base(expecting, input) + { + } + + public UnwantedTokenException(int expecting, IIntStream input, IList<string> tokenNames) + : base(expecting, input, tokenNames) + { + } + + public UnwantedTokenException(string message, int expecting, IIntStream input, IList<string> tokenNames) + : base(message, expecting, input, tokenNames) + { + } + + public UnwantedTokenException(string message, int expecting, IIntStream input, IList<string> tokenNames, Exception innerException) + : base(message, expecting, input, tokenNames, innerException) + { + } + + protected UnwantedTokenException(SerializationInfo info, StreamingContext context) + : base(info, context) + { + } + + public virtual IToken UnexpectedToken + { + get + { + return Token; + } + } + + public override string ToString() + { + //int unexpectedType = getUnexpectedType(); + //string unexpected = ( tokenNames != null && unexpectedType >= 0 && unexpectedType < tokenNames.Length ) ? tokenNames[unexpectedType] : unexpectedType.ToString(); + string expected = (TokenNames != null && Expecting >= 0 && Expecting < TokenNames.Count) ? TokenNames[Expecting] : Expecting.ToString(); + + string exp = ", expected " + expected; + if (Expecting == TokenTypes.Invalid) + { + exp = ""; + } + if (Token == null) + { + return "UnwantedTokenException(found=" + null + exp + ")"; + } + return "UnwantedTokenException(found=" + Token.Text + exp + ")"; + } + } +} |