Commit 2ad75270 authored by Arpad Lovassy's avatar Arpad Lovassy
Browse files

Parse tree logger: removed ...LexerLogUtil related dependencies and class generation script


Signed-off-by: Arpad Lovassy's avatarzlovarp <arpad.lovassy@semcon.com>
parent 385eaf14
...@@ -87,9 +87,5 @@ ...@@ -87,9 +87,5 @@
@java %ANTLR% VariantAttributeLexer.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser @java %ANTLR% VariantAttributeLexer.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser
@java %ANTLR% VariantAttributeParser.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser @java %ANTLR% VariantAttributeParser.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser
@echo Generating ...LexerLogUtil.java files from ...Lexer.java files for resolving token names (OPTIONAL)
@cd %DIR%
@perl antlr4_generate_lexerlogutil.pl
@cd %CURDIR% @cd %CURDIR%
...@@ -84,7 +84,3 @@ cd $WORKSPACE_PATH/org.eclipse.titan.designer/src/org/eclipse/titan/designer/par ...@@ -84,7 +84,3 @@ cd $WORKSPACE_PATH/org.eclipse.titan.designer/src/org/eclipse/titan/designer/par
$ANTLR4 VariantAttributeLexer.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser $ANTLR4 VariantAttributeLexer.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser
$ANTLR4 VariantAttributeParser.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser $ANTLR4 VariantAttributeParser.g4 -no-listener -no-visitor -encoding UTF-8 -package org.eclipse.titan.designer.parsers.variantattributeparser
# Generating ...LexerLogUtil.java files from ...Lexer.java files for resolving token names (OPTIONAL)
cd $WORKSPACE_PATH
$DIR/antlr4_generate_lexerlogutil.pl
#!/usr/bin/perl
###############################################################################
# Copyright (c) 2000-2021 Ericsson Telecom AB
# All rights reserved. This program and the accompanying materials
# are made available under the terms of the Eclipse Public License v2.0
# which accompanies this distribution, and is available at
# https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
#
# Contributors:
# Lovassy, Arpad
#
###############################################################################
###############################################################################
# Generates ...LexerLogUtil.java implements ILexerLogUtil
# for all ...Lexer.java under the current directory
# to determine token name from token index.
# This is used for logging purpose,
# see ParserLogger.java and TokenNameResolver.java
#
# Prerequisites: ANTLR lexer .g4 files must be compiled,
# because generated java files must exist.
#
# Example usage (to create ...LexerLogUtil.java for all the ...Lexer.java
# in titan.EclipsePlug-ins project):
# cd <titan.EclipsePlug-ins project root>
# Tools/antlr4_generate_lexerlogutil.pl
###############################################################################
# to read the whole file at once, not just line-by-line
# http://www.kichwa.com/quik_ref/spec_variables.html
undef $/;
$fileindex = 0;
#total number of changed files
$total = 0;
sub load
{
local $filename = shift; # 1st parameter
local $f = "F".$fileindex++;
if(opendir($f, $filename))
{
# $filename is a directory
while(local $newfilename = readdir($f))
{
if(!($newfilename =~ /^\.(\.|git)?$/)) # filter . .. .git
{
local $longfilename = $filename."/".$newfilename; # for Unix
#local $longfilename = $filename."\\".$newfilename; # for DOS/Windows
load($longfilename);
}
}
closedir($f);
}
else
{
# $filename is a file
if($filename =~ /^(.*\/)(Asn1|Cfg|Ttcn3|ExtensionAttribute|VariantAttribute|PreprocessorDirective)(Lexer)(\.java)$/)
{
$file_part1 = $1;
$file_part2 = $2;
$file_part3 = $3;
$file_part4 = "LogUtil";
$file_part5 = $4;
print("Source file: $filename\n");
open(IN, $filename);
$whole_file = <IN>;
close(IN);
$outfilename = $file_part1.$file_part2.$file_part3.$file_part4.$file_part5;
print("Output file: $outfilename\n");
open(OUT, ">$outfilename");
if ( $whole_file =~ /package\s+([a-zA-Z_][a-zA-Z_0-9]*(\.[a-zA-Z_][a-zA-Z_0-9]*)*);/gs ) {
$package = $1;
print "Package: $package\n";
} else {
print "ERROR: package missing";
}
$out =
"package $package;\n".
"\n".
"import org.eclipse.titan.common.parsers.ILexerLogUtil;\n".
"\n".
"public class $file_part2$file_part3$file_part4 implements ILexerLogUtil {\n".
"\n".
" public String getTokenName( int aIndex ) {\n".
" switch ( aIndex ) {\n";
if ( $whole_file =~ /public static final int\r?\n\s*(.*?);/gs ) {
$const_defs = $1; #comma separated constant definition: WS=1, LINE_COMMENT=2, ..., MACRO12=451
# print "\$const_defs == $const_defs\n";
my @list = split(/,\s*/, $const_defs);
foreach my $const_def (@list) {
# print "\$const_def == \"$const_def\"\n";
if ( $const_def =~ /(^[A-Za-z][A-Za-z0-9_]*)=([0-9]+)$/ ) {
$const_name = $1;
$const_value = $2;
# print "\$const_name == \"$const_name\"\n";
# print "\$const_value == \"$const_value\"\n";
$out .=
" case $const_value:\n".
" return \"$const_name\";\n";
}
else {
print "ERROR: $const_def does NOT match!\n";
}
}
}
$out .=
" case -1:\n".
" return \"EOF\";\n".
" default:\n".
" return \"\" + aIndex;\n".
" }\n".
" }\n".
"}\n".
"";
print OUT $out;
close(OUT);
print("DONE\n");
}
}
}
load("..");
/******************************************************************************
* Copyright (c) 2000-2021 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
package org.eclipse.titan.common.parsers;
/**
* USED FOR LOGGING PURPOSES
* Interface for token name resolving
* @see TokenNameResolver
* @author Arpad Lovassy
*/
public interface ILexerLogUtil {
/**
* @param aIndex token type index
* @return resolved token name
*/
public String getTokenName( int aIndex );
}
...@@ -15,13 +15,13 @@ import java.util.Date; ...@@ -15,13 +15,13 @@ import java.util.Date;
import java.util.List; import java.util.List;
import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.NoViableAltException; import org.antlr.v4.runtime.NoViableAltException;
import org.antlr.v4.runtime.Parser; import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException; import org.antlr.v4.runtime.RecognitionException;
import org.antlr.v4.runtime.Token; import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.TokenStream; import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.Vocabulary;
import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.TerminalNodeImpl; import org.antlr.v4.runtime.tree.TerminalNodeImpl;
import org.eclipse.titan.common.parsers.cfg.CfgInterval; import org.eclipse.titan.common.parsers.cfg.CfgInterval;
...@@ -32,6 +32,7 @@ import org.eclipse.titan.common.parsers.cfg.CfgInterval; ...@@ -32,6 +32,7 @@ import org.eclipse.titan.common.parsers.cfg.CfgInterval;
* @author Arpad Lovassy * @author Arpad Lovassy
*/ */
public final class ParserLogger { public final class ParserLogger {
/** date format in ISO 8601 */ /** date format in ISO 8601 */
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
...@@ -47,17 +48,13 @@ public final class ParserLogger { ...@@ -47,17 +48,13 @@ public final class ParserLogger {
/** /**
* Logs a parse tree. (General version) * Logs a parse tree. (General version)
* Token name is resolved if ...LexerLogUtil.java is generated,
* otherwise only token type index is displayed
* @param aRoot parse tree * @param aRoot parse tree
* @param aParser parser to get rule names * @param aParser parser to get rule names
* @param aTokenNameResolver resolver to get token name
* @param aPrinter printer * @param aPrinter printer
* @param aDescription description of the parsing type, for the logging (for example: TTCN-3, Cfg, ASN.1) * @param aDescription description of the parsing type, for the logging (for example: TTCN-3, Cfg, ASN.1)
*/ */
public static synchronized void log( final ParseTree aRoot, public static synchronized void log( final ParseTree aRoot,
final Parser aParser, final Parser aParser,
final TokenNameResolver aTokenNameResolver,
final IPrinter aPrinter, final IPrinter aPrinter,
final String aDescription ) { final String aDescription ) {
if ( !aParser.getBuildParseTree() ) { if ( !aParser.getBuildParseTree() ) {
...@@ -76,21 +73,7 @@ public final class ParserLogger { ...@@ -76,21 +73,7 @@ public final class ParserLogger {
} }
final CommonTokenStream commonTokenStream = (CommonTokenStream)tokenStream; final CommonTokenStream commonTokenStream = (CommonTokenStream)tokenStream;
final List<Token> tokens = commonTokenStream.getTokens(); final List<Token> tokens = commonTokenStream.getTokens();
log( aRoot, aParser, tokens, aTokenNameResolver ); log( aRoot, aParser, tokens );
}
/**
* Logs a parse tree
* @param aRoot parse tree
* @param aParser parser to get rule names
* @param aTokens token list to get tokens by index (for getting tokens of a rule)
* @param aLexerLogUtil resolver to get token name by method 1, see TokenNameResolver
*/
public static void log( final ParseTree aRoot,
final Parser aParser,
final List<Token> aTokens,
final ILexerLogUtil aLexerLogUtil ) {
log( aRoot, aParser, aTokens, new TokenNameResolver( aLexerLogUtil ) );
} }
/** /**
...@@ -98,40 +81,12 @@ public final class ParserLogger { ...@@ -98,40 +81,12 @@ public final class ParserLogger {
* @param aRoot parse tree * @param aRoot parse tree
* @param aParser parser to get rule names * @param aParser parser to get rule names
* @param aTokens token list to get tokens by index (for getting tokens of a rule) * @param aTokens token list to get tokens by index (for getting tokens of a rule)
* @param aLexer resolver to get token name by method 2, see TokenNameResolver
*/
public static void log( final ParseTree aRoot,
final Parser aParser,
final List<Token> aTokens,
final Lexer aLexer ) {
log( aRoot, aParser, aTokens, new TokenNameResolver( aLexer ) );
}
/**
* Logs a parse tree, token name is not resolved, only token type index is displayed
* @param aRoot parse tree
* @param aParser parser to get rule names
* @param aTokens token list to get tokens by index (for getting tokens of a rule)
*/ */
public static void log( final ParseTree aRoot, public static void log( final ParseTree aRoot,
final Parser aParser, final Parser aParser,
final List<Token> aTokens ) { final List<Token> aTokens ) {
log( aRoot, aParser, aTokens, new TokenNameResolver() );
}
/**
* Logs a parse tree
* @param aRoot parse tree
* @param aParser parser to get rule names
* @param aTokens token list to get tokens by index (for getting tokens of a rule)
* @param aTokenNameResolver resolver to get token name
*/
private static void log( final ParseTree aRoot,
final Parser aParser,
final List<Token> aTokens,
final TokenNameResolver aTokenNameResolver ) {
try { try {
log( aRoot, aParser, aTokens, aTokenNameResolver, new ArrayList<Boolean>(), false, false ); log( aRoot, aParser, aTokens, new ArrayList<Boolean>(), false, false );
} catch( Exception e ) { } catch( Exception e ) {
final StringWriter sw = new StringWriter(); final StringWriter sw = new StringWriter();
final PrintWriter pw = new PrintWriter( sw ); final PrintWriter pw = new PrintWriter( sw );
...@@ -147,7 +102,6 @@ public final class ParserLogger { ...@@ -147,7 +102,6 @@ public final class ParserLogger {
* @param aRoot parse tree * @param aRoot parse tree
* @param aParser parser to get rule name * @param aParser parser to get rule name
* @param aTokens token list to get tokens by index (for getting tokens of a rule) * @param aTokens token list to get tokens by index (for getting tokens of a rule)
* @param aTokenNameResolver resolver to get token name
* @param aLevel a list, that tells, if tree section is drawn for that level (parent). * @param aLevel a list, that tells, if tree section is drawn for that level (parent).
* If the parent of the given level is already the last child, tree sections are not drawn below. * If the parent of the given level is already the last child, tree sections are not drawn below.
* NOTE: indentation level is aLevel.size() * NOTE: indentation level is aLevel.size()
...@@ -157,7 +111,6 @@ public final class ParserLogger { ...@@ -157,7 +111,6 @@ public final class ParserLogger {
private static void log( final ParseTree aRoot, private static void log( final ParseTree aRoot,
final Parser aParser, final Parser aParser,
final List<Token> aTokens, final List<Token> aTokens,
final TokenNameResolver aTokenNameResolver,
final List<Boolean> aLevel, final List<Boolean> aLevel,
final boolean aParentOneChild, final boolean aParentOneChild,
final boolean aLastChild ) { final boolean aLastChild ) {
...@@ -172,7 +125,7 @@ public final class ParserLogger { ...@@ -172,7 +125,7 @@ public final class ParserLogger {
if ( aRoot instanceof ParserRuleContext ) { if ( aRoot instanceof ParserRuleContext ) {
final ParserRuleContext rule = (ParserRuleContext)aRoot; final ParserRuleContext rule = (ParserRuleContext)aRoot;
final String ruleInfo = getRuleInfo( rule, aParser, aTokenNameResolver ); final String ruleInfo = getRuleInfo( rule, aParser );
if ( aParentOneChild ) { if ( aParentOneChild ) {
printArrow( ruleInfo ); printArrow( ruleInfo );
} else { } else {
...@@ -182,7 +135,7 @@ public final class ParserLogger { ...@@ -182,7 +135,7 @@ public final class ParserLogger {
final int count = rule.getChildCount(); final int count = rule.getChildCount();
final boolean oneChild = count == 1 && rule.exception == null; final boolean oneChild = count == 1 && rule.exception == null;
if ( !oneChild ) { if ( !oneChild ) {
println( ": '" + getEscapedRuleText( rule, aTokens ) + "'" + getExceptionInfo( rule, aTokenNameResolver ) ); println( ": '" + getEscapedRuleText( rule, aTokens ) + "'" + getExceptionInfo( rule, aParser ) );
} }
for( int i = 0; i < count; i++ ) { for( int i = 0; i < count; i++ ) {
...@@ -195,7 +148,7 @@ public final class ParserLogger { ...@@ -195,7 +148,7 @@ public final class ParserLogger {
} }
level.add( true ); level.add( true );
} }
log( child, aParser, aTokens, aTokenNameResolver, level, oneChild, i == count - 1 ); log( child, aParser, aTokens, level, oneChild, i == count - 1 );
} }
} else if ( aRoot instanceof TerminalNodeImpl ) { } else if ( aRoot instanceof TerminalNodeImpl ) {
final TerminalNodeImpl tn = (TerminalNodeImpl)aRoot; final TerminalNodeImpl tn = (TerminalNodeImpl)aRoot;
...@@ -203,7 +156,7 @@ public final class ParserLogger { ...@@ -203,7 +156,7 @@ public final class ParserLogger {
println( ": '" + getEscapedTokenText( tn.getSymbol() ) + "'" ); println( ": '" + getEscapedTokenText( tn.getSymbol() ) + "'" );
} }
printIndent( getTokenInfo( tn.getSymbol(), aTokenNameResolver ), aLevel ); printIndent( getTokenInfo( tn.getSymbol(), aParser ), aLevel );
if ( tn.parent == null ) { if ( tn.parent == null ) {
print(", parent == null <-------------------------------------------------------------- ERROR"); print(", parent == null <-------------------------------------------------------------- ERROR");
} }
...@@ -226,10 +179,10 @@ public final class ParserLogger { ...@@ -226,10 +179,10 @@ public final class ParserLogger {
/** /**
* Rule exception info in string format for logging purpose * Rule exception info in string format for logging purpose
* @param aRule rule * @param aRule rule
* @param aTokenNameResolver resolver to get token name * @param aParser parser to get token name
* @return exception stack trace + some other info from the exception object * @return exception stack trace + some other info from the exception object
*/ */
private static String getExceptionInfo( final ParserRuleContext aRule, final TokenNameResolver aTokenNameResolver ) { private static String getExceptionInfo( final ParserRuleContext aRule, final Parser aParser ) {
final RecognitionException e = aRule.exception; final RecognitionException e = aRule.exception;
if ( e == null ) { if ( e == null ) {
return ""; return "";
...@@ -242,12 +195,12 @@ public final class ParserLogger { ...@@ -242,12 +195,12 @@ public final class ParserLogger {
sb.append(", "); sb.append(", ");
} }
final int tokenType = expectedTokens.get( i ); final int tokenType = expectedTokens.get( i );
sb.append( getTokenName( tokenType, aTokenNameResolver ) ); sb.append( getTokenName( tokenType, aParser ) );
} }
sb.append(']'); sb.append(']');
if ( e instanceof NoViableAltException ) { if ( e instanceof NoViableAltException ) {
final NoViableAltException nvae = (NoViableAltException)e; final NoViableAltException nvae = (NoViableAltException)e;
sb.append( ", start token: " + getTokenInfo( nvae.getStartToken(), aTokenNameResolver ) ); sb.append( ", start token: " + getTokenInfo( nvae.getStartToken(), aParser ) );
} }
return sb.toString(); return sb.toString();
...@@ -257,10 +210,9 @@ public final class ParserLogger { ...@@ -257,10 +210,9 @@ public final class ParserLogger {
* Rule info in string format for logging purpose * Rule info in string format for logging purpose
* @param aRule rule * @param aRule rule
* @param aParser parser to get rule name * @param aParser parser to get rule name
* @param aTokenNameResolver resolver to get token name (used only if rule is erroneous)
* @return rule name and exception and some other info if rule is erroneous * @return rule name and exception and some other info if rule is erroneous
*/ */
private static String getRuleInfo( final ParserRuleContext aRule, final Parser aParser, final TokenNameResolver aTokenNameResolver ) { private static String getRuleInfo( final ParserRuleContext aRule, final Parser aParser ) {
// only rule name // only rule name
final String info = aParser.getRuleInvocationStack( aRule ).get( 0 ); final String info = aParser.getRuleInvocationStack( aRule ).get( 0 );
return info; return info;
...@@ -333,7 +285,7 @@ public final class ParserLogger { ...@@ -333,7 +285,7 @@ public final class ParserLogger {
/** /**
* Token info in string format for logging purpose * Token info in string format for logging purpose
* @param aToken token * @param aToken token
* @param aTokenNameResolver resolver to get token name * @param aParser parser to get token name
* @return &lt;token name&gt;: '&lt;token text&gt;', @&lt;token index&gt;, &lt;line&gt;:&lt;column&gt;[, channel=&lt;channel&gt;] * @return &lt;token name&gt;: '&lt;token text&gt;', @&lt;token index&gt;, &lt;line&gt;:&lt;column&gt;[, channel=&lt;channel&gt;]
* <br>where * <br>where
* <br>&lt;token index&gt; starts from 0, * <br>&lt;token index&gt; starts from 0,
...@@ -341,10 +293,10 @@ public final class ParserLogger { ...@@ -341,10 +293,10 @@ public final class ParserLogger {
* <br>&lt;column&gt; starts from 0, * <br>&lt;column&gt; starts from 0,
* <br>channel info is provided if &lt;channel&gt; > 0 (hidden channel) * <br>channel info is provided if &lt;channel&gt; > 0 (hidden channel)
*/ */
private static String getTokenInfo( final Token aToken, final TokenNameResolver aTokenNameResolver ) { private static String getTokenInfo( final Token aToken, final Parser aParser ) {
final StringBuilder sb = new StringBuilder(); final StringBuilder sb = new StringBuilder();
final int tokenType = aToken.getType(); final int tokenType = aToken.getType();
final String tokenName = getTokenName( tokenType, aTokenNameResolver ); final String tokenName = getTokenName( tokenType, aParser );
sb.append( tokenName ); sb.append( tokenName );
sb.append( ": " ); sb.append( ": " );
...@@ -390,22 +342,13 @@ public final class ParserLogger { ...@@ -390,22 +342,13 @@ public final class ParserLogger {
/** /**
* @param aTokenType token type index * @param aTokenType token type index
* @param aTokenNameResolver token name resolver * @param aParser parser to resolve token name
* @return resolved token name * @return resolved token name
*/ */
private static String getTokenName( final int aTokenType, TokenNameResolver aTokenNameResolver ) { private static String getTokenName( final int aTokenType, final Parser aParser ) {
/* final Vocabulary vocabulary = aParser.getVocabulary();
TODO: use Vocabulary interface when ANTLR 4.5 is used
See https://github.com/antlr/antlr4/pull/712
Vocabulary vocabulary = recognizer.getVocabulary();
final String symbolicName = vocabulary.getSymbolicName( aTokenType ); final String symbolicName = vocabulary.getSymbolicName( aTokenType );
return symbolicName; return symbolicName;
*/
if ( aTokenNameResolver == null ) {
aTokenNameResolver = new TokenNameResolver();
}
return aTokenNameResolver.getTokenName( aTokenType );
} }
/** /**
......
/******************************************************************************
* Copyright (c) 2000-2021 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
package org.eclipse.titan.common.parsers;
import org.antlr.v4.runtime.Lexer;
/**
* USED FOR LOGGING PURPOSES.<br>
* Utility class to get the token name from token index for logging purpose.<br>
* Token name can be calculated in 2 ways:
* <ol>
* <li> Generate ILexerLogUtil for each lexer from ...Lexer.java,
* see <titan.EclipsePlug-ins root>/Tools/antlr4_generate_logutil.pl<br>
* This is preferred, it is accurate
* <li> Get token name like this: aTokenType == -1 ? "EOF" : aLexer.getRuleNames()[ aTokenType - 1 ]<br>
* There are 2 problems with it:
* <ol>
* <li> fragments are not tokens, but they are listed in ruleNames[], for example: CfgLexer FR_NUMBER1
* <li> tokens, which are defined, but has no rule are not listed in ruleNames[], for example: Ttcn3Lexer MACRO
* </ol>
* so after these cases the lexer rule names are in wrong position, it is a bug in ANTLR 4.4<br>
* But it can be still used in general cases if no ILexerLogUtil is generated
* </ol>
* @author Arpad Lovassy
*/
public class TokenNameResolver {
/**
* token name resolver for case 1
*/
private ILexerLogUtil mLexerLogUtil = null;
/**
* token name resolver for case 2
*/
private Lexer mLexer = null;
/**
* Default constructor, in this case no resolving is made, token index is displayed
*/
public TokenNameResolver() {
}
/**
* Constructor for case 1
* @param aLexerLogUtil token name resolver for case 1
*/
public TokenNameResolver( final ILexerLogUtil aLexerLogUtil ) {
mLexerLogUtil = aLexerLogUtil;
}
/**
* Constructor for case 2
* @param aLexerLogUtil token name resolver for case 2