mirror of
https://github.com/twiglet/cs2j.git
synced 2025-01-18 13:15:17 +01:00
Add parseString and IsJavaish so that we can parse arbitrary snippets of Java(ish) code and weave them into the output
This commit is contained in:
parent
71beb7eef6
commit
18fb3d4063
@ -129,6 +129,7 @@ namespace Twiglet.CS2J.Translator
|
||||
.Add ("translator-timestamp-files=", v => cfg.TranslatorAddTimeStamp = Boolean.Parse(v))
|
||||
.Add ("translator-exception-is-throwable=", v => cfg.TranslatorExceptionIsThrowable = Boolean.Parse(v))
|
||||
.Add ("experimental-transforms=", v => cfg.ExperimentalTransforms = Boolean.Parse(v))
|
||||
.Add ("internal-isjavaish", v => cfg.InternalIsJavaish = true)
|
||||
;
|
||||
|
||||
//TODO: fix enum dump
|
||||
@ -191,6 +192,7 @@ namespace Twiglet.CS2J.Translator
|
||||
w.Close();
|
||||
}
|
||||
}
|
||||
|
||||
// load in T.stg template group, put in templates variable
|
||||
string templateLocation = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("templates", "java.stg"));
|
||||
if (File.Exists(templateLocation)) {
|
||||
@ -279,6 +281,7 @@ namespace Twiglet.CS2J.Translator
|
||||
// }
|
||||
csParser p = new csParser(tokens);
|
||||
p.TraceDestination = Console.Error;
|
||||
p.IsJavaish = cfg.InternalIsJavaish;
|
||||
|
||||
csParser.compilation_unit_return parser_rt = p.compilation_unit();
|
||||
|
||||
@ -439,6 +442,7 @@ namespace Twiglet.CS2J.Translator
|
||||
javaMaker.Cfg = cfg;
|
||||
javaMaker.CUMap = new Dictionary<string, CUnit>();
|
||||
javaMaker.CUKeys = new List<string>();
|
||||
javaMaker.IsJavaish = cfg.InternalIsJavaish;
|
||||
|
||||
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Translating {0} to Java", fullName);
|
||||
|
||||
@ -514,6 +518,8 @@ namespace Twiglet.CS2J.Translator
|
||||
netMaker.AliasKeys = javaMaker.CUMap[typeName].NameSpaceAliasKeys;
|
||||
netMaker.AliasNamespaces = javaMaker.CUMap[typeName].NameSpaceAliasValues;
|
||||
|
||||
netMaker.IsJavaish = cfg.InternalIsJavaish;
|
||||
|
||||
if (cfg.DebugLevel > 5) Console.Out.WriteLine("Translating {0} Net Calls to Java", javaFName);
|
||||
NetMaker.compilation_unit_return javaCompilationUnit = netMaker.compilation_unit();
|
||||
|
||||
|
@ -61,6 +61,11 @@ namespace Twiglet.CS2J.Translator
|
||||
get; set;
|
||||
}
|
||||
|
||||
public bool InternalIsJavaish
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
|
||||
public CS2JSettings ()
|
||||
{
|
||||
|
||||
@ -95,6 +100,8 @@ namespace Twiglet.CS2J.Translator
|
||||
TranslatorExceptionIsThrowable = false;
|
||||
|
||||
ExperimentalTransforms = false;
|
||||
|
||||
InternalIsJavaish = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,13 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Reflection;
|
||||
|
||||
using Antlr.Runtime.Tree;
|
||||
using Antlr.Runtime;
|
||||
|
||||
using AntlrCSharp;
|
||||
|
||||
using Twiglet.CS2J.Translator.Utils;
|
||||
using Twiglet.CS2J.Translator.TypeRep;
|
||||
using Twiglet.CS2J.Translator;
|
||||
@ -119,6 +123,84 @@ namespace Twiglet.CS2J.Translator.Transform
|
||||
return (String.IsNullOrEmpty(ns) ? "" : ns + ".");
|
||||
}
|
||||
|
||||
// Routines to parse strings to ANTLR Trees on the fly, used to generate fragments needed by the transformation
|
||||
public CommonTree parseString(string startRule, string inStr)
|
||||
{
|
||||
|
||||
if (Cfg.Verbosity > 5) Console.WriteLine("Parsing fragment ");
|
||||
|
||||
ICharStream input = new ANTLRStringStream(inStr);
|
||||
|
||||
PreProcessor lex = new PreProcessor();
|
||||
lex.AddDefine(Cfg.MacroDefines);
|
||||
lex.CharStream = input;
|
||||
lex.TraceDestination = Console.Error;
|
||||
|
||||
CommonTokenStream tokens = new CommonTokenStream(lex);
|
||||
|
||||
csParser p = new csParser(tokens);
|
||||
p.TraceDestination = Console.Error;
|
||||
p.IsJavaish = true;
|
||||
|
||||
// Try and call a rule like CSParser.namespace_body()
|
||||
// Use reflection to find the rule to use.
|
||||
MethodInfo mi = p.GetType().GetMethod(startRule);
|
||||
|
||||
if (mi == null)
|
||||
{
|
||||
throw new Exception("Could not find start rule " + startRule + " in csParser");
|
||||
}
|
||||
|
||||
ParserRuleReturnScope csRet = (ParserRuleReturnScope) mi.Invoke(p, new object[0]);
|
||||
|
||||
CommonTreeNodeStream csTreeStream = new CommonTreeNodeStream(csRet.Tree);
|
||||
csTreeStream.TokenStream = tokens;
|
||||
|
||||
JavaMaker javaMaker = new JavaMaker(csTreeStream);
|
||||
javaMaker.TraceDestination = Console.Error;
|
||||
javaMaker.Cfg = Cfg;
|
||||
javaMaker.IsJavaish = true;
|
||||
|
||||
// Try and call a rule like CSParser.namespace_body()
|
||||
// Use reflection to find the rule to use.
|
||||
mi = javaMaker.GetType().GetMethod(startRule);
|
||||
|
||||
if (mi == null)
|
||||
{
|
||||
throw new Exception("Could not find start rule " + startRule + " in javaMaker");
|
||||
}
|
||||
|
||||
TreeRuleReturnScope javaSyntaxRet = (TreeRuleReturnScope) mi.Invoke(javaMaker, new object[0]);
|
||||
|
||||
CommonTree javaSyntaxAST = (CommonTree)javaSyntaxRet.Tree;
|
||||
|
||||
// CommonTreeNodeStream javaSyntaxNodes = new CommonTreeNodeStream(javaSyntaxAST);
|
||||
//
|
||||
// javaSyntaxNodes.TokenStream = csTree.TokenStream;
|
||||
//
|
||||
// NetMaker netMaker = new NetMaker(javaSyntaxNodes);
|
||||
// netMaker.TraceDestination = Console.Error;
|
||||
//
|
||||
// netMaker.Cfg = Cfg;
|
||||
// netMaker.AppEnv = AppEnv;
|
||||
//
|
||||
// CommonTree javaAST = (CommonTree)netMaker.class_member_declarations().Tree;
|
||||
//
|
||||
return javaSyntaxAST;
|
||||
}
|
||||
|
||||
// If true, then we are parsing some JavaIsh fragment
|
||||
private bool isJavaish = false;
|
||||
public bool IsJavaish
|
||||
{
|
||||
get {
|
||||
return isJavaish;
|
||||
}
|
||||
set {
|
||||
isJavaish = value;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Wraps a compilation unit with its imports search path
|
||||
|
@ -40,6 +40,7 @@ scope TypeContext {
|
||||
@header
|
||||
{
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
}
|
||||
|
||||
@ -707,7 +708,17 @@ type_arguments returns [List<string> tyargs]
|
||||
$tyargs = new List<string>();
|
||||
}
|
||||
:
|
||||
t1=type { $tyargs.Add($t1.thetext); } (',' tn=type { $tyargs.Add($tn.thetext); })* ;
|
||||
t1=type_argument { $tyargs.Add($t1.thetext); } (',' tn=type_argument { $tyargs.Add($tn.thetext); })* ;
|
||||
|
||||
public type_argument returns [string thetext]:
|
||||
{this.IsJavaish}?=> javaish_type_argument {$thetext = $javaish_type_argument.thetext; }
|
||||
| type {$thetext = $type.thetext; }
|
||||
;
|
||||
public javaish_type_argument returns [string thetext]:
|
||||
('?' 'extends')=> '?' 'extends' type {$thetext = "? extends " + $type.thetext; }
|
||||
| '?' {$thetext = "?"; }
|
||||
| type {$thetext = $type.thetext; }
|
||||
;
|
||||
|
||||
type returns [string thetext]:
|
||||
((predefined_type | type_name) rank_specifiers) => (p1=predefined_type { $thetext = $p1.thetext; } | tn1=type_name { $thetext = $tn1.thetext; }) rs=rank_specifiers { $thetext += $rs.text; } ('*' { $thetext += "*"; })* -> ^(TYPE $p1? $tn1? $rs '*'*)
|
||||
@ -1029,11 +1040,14 @@ method_declaration [CommonTree atts, CommonTree mods, List<string> modList, Comm
|
||||
)?
|
||||
')'
|
||||
( type_parameter_constraints_clauses { isToString = false; isMain = false; })?
|
||||
// Only have throw Exceptions if IsJavaish
|
||||
throw_exceptions?
|
||||
|
||||
b=method_body[isToString]
|
||||
|
||||
// build main method if required
|
||||
argParam=magicMainArgs[isMain && isMainHasArg, $member_name.tree.Token]
|
||||
mainApply=magicMainApply[isMain, $member_name.tree.Token, $TypeContext::typeName, $argParam.tree]
|
||||
mainApply=magicMainApply[isMain, $member_name.tree.Token, (isMain ? $TypeContext::typeName : null), $argParam.tree]
|
||||
mainCall=magicMainExit[isMain, isInt, $member_name.tree.Token, $mainApply.tree]
|
||||
mainMethod=magicMainWrapper[isMain, $member_name.tree.Token, $mainCall.tree]
|
||||
|
||||
@ -1041,7 +1055,7 @@ method_declaration [CommonTree atts, CommonTree mods, List<string> modList, Comm
|
||||
{ if (isToString) {
|
||||
$member_name.tree.Token.Text = "toString";
|
||||
}
|
||||
exceptions = $b.exceptionList;
|
||||
exceptions = IsJavaish ? $throw_exceptions.tree : $b.exceptionList;
|
||||
}
|
||||
-> $mainMethod?
|
||||
^(METHOD { dupTree($atts) } { dupTree($mods) } { dupTree($type) }
|
||||
@ -1053,8 +1067,16 @@ method_body [bool smotherExceptions] returns [CommonTree exceptionList]:
|
||||
| b=block el=magicThrowsException[true,$b.tree.Token] { $exceptionList=$el.tree; }
|
||||
-> $b
|
||||
;
|
||||
member_name returns [string rawId]:
|
||||
(type_or_generic '.')* i=identifier { $rawId = $i.text; }
|
||||
|
||||
throw_exceptions:
|
||||
{IsJavaish}?=> 'throws'! t1=identifier { $t1.tree.Type = EXCEPTION; } (','! tn=identifier { $tn.tree.Type = EXCEPTION; } )*
|
||||
;
|
||||
member_name returns [string rawId, string full_name]
|
||||
@init {
|
||||
$full_name = "";
|
||||
}:
|
||||
(type_or_generic '.' {$full_name += mkTypeOrGenericString($type_or_generic.type, $type_or_generic.generic_arguments) + ".";})*
|
||||
i=identifier { $rawId = $i.text; $full_name += $i.text; }
|
||||
// keving [interface_type.identifier] | type_name '.' identifier
|
||||
;
|
||||
|
||||
|
@ -670,8 +670,13 @@ qid_part:
|
||||
generic_argument_list:
|
||||
'<' type_arguments '>' -> generic_args(args={ $type_arguments.st });
|
||||
type_arguments:
|
||||
ts+=type (',' ts+=type)* -> commalist(items = { $ts });
|
||||
ts+=type_argument (',' ts+=type_argument)* -> commalist(items = { $ts });
|
||||
|
||||
public type_argument:
|
||||
('?' 'extends')=> '?' 'extends' type -> op(pre={"?"},op={" extends "},post={$type.st})
|
||||
| '?' -> string(payload={"?"})
|
||||
| type -> { $type.st }
|
||||
;
|
||||
type
|
||||
@init {
|
||||
StringTemplate nm = null;
|
||||
@ -1349,16 +1354,19 @@ predefined_type:
|
||||
| t='short' | t='string' | t='uint' | t='ulong' | t='ushort') { collectComments($t.TokenStartIndex); } -> string(payload={$t.text});
|
||||
|
||||
identifier:
|
||||
i=IDENTIFIER { collectComments($i.TokenStartIndex); } -> string(payload= { $IDENTIFIER.text }) | also_keyword -> string(payload= { $also_keyword.text });
|
||||
i=IDENTIFIER { collectComments($i.TokenStartIndex); } -> string(payload= { $IDENTIFIER.text }) | also_keyword -> { $also_keyword.st };
|
||||
|
||||
keyword:
|
||||
'abstract' | 'as' | 'base' | 'bool' | 'break' | 'byte' | 'case' | 'catch' | 'char' | 'checked' | 'class' | 'const' | 'continue' | 'decimal' | 'default' | 'delegate' | 'do' | 'double' | 'else' | 'enum' | 'event' | 'explicit' | 'extern' | 'false' | 'finally' | 'fixed' | 'float' | 'for' | 'foreach' | 'goto' | 'if' | 'implicit' | 'in' | 'int' | 'interface' | 'internal' | 'is' | 'lock' | 'long' | 'namespace' | 'new' | 'null' | 'object' | 'operator' | 'out' | 'override' | 'params' | 'private' | 'protected' | 'public' | 'readonly' | 'ref' | 'return' | 'sbyte' | 'sealed' | 'short' | 'sizeof' | 'stackalloc' | 'static' | 'string' | 'struct' | 'switch' | 'this' | 'throw' | 'true' | 'try' | 'typeof' | 'uint' | 'ulong' | 'unchecked' | 'unsafe' | 'ushort' | 'using' | 'virtual' | 'void' | 'volatile' ;
|
||||
|
||||
also_keyword:
|
||||
'add' | 'alias' | 'assembly' | 'module' | 'field' | 'method' | 'param' | 'property' | 'type' | 'yield'
|
||||
| 'from' | 'into' | 'join' | 'on' | 'where' | 'orderby' | 'group' | 'by' | 'ascending' | 'descending'
|
||||
| 'equals' | 'select' | 'pragma' | 'let' | 'remove' | 'get' | 'set' | 'var' | '__arglist' | 'dynamic' | 'elif'
|
||||
| 'endif' | 'define' | 'undef';
|
||||
(
|
||||
t='add' | t='alias' | t='assembly' | t='module' | t='field' | t='method' | t='param' | t='property' | t='type' | t='yield'
|
||||
| t='from' | t='into' | t='join' | t='on' | t='where' | t='orderby' | t='group' | t='by' | t='ascending' | t='descending'
|
||||
| t='equals' | t='select' | t='pragma' | t='let' | t='remove' | t='get' | t='set' | t='var' | t='__arglist' | t='dynamic' | t='elif'
|
||||
| t='endif' | t='define' | t='undef'
|
||||
) -> string(payload={$t.text})
|
||||
;
|
||||
|
||||
literal:
|
||||
Real_literal -> string(payload={$Real_literal.text})
|
||||
|
@ -15,7 +15,6 @@ tokens {
|
||||
INTERFACE;
|
||||
FINAL; /* final modifier */
|
||||
ANNOTATION;
|
||||
IN;
|
||||
OUT;
|
||||
CONST;
|
||||
EVENT;
|
||||
@ -66,6 +65,9 @@ tokens {
|
||||
ELSE = 'else';
|
||||
BREAK = 'break';
|
||||
OBJECT = 'object';
|
||||
THIS = 'this';
|
||||
FOREACH = 'foreach';
|
||||
IN = 'in';
|
||||
|
||||
OPEN_BRACKET='[';
|
||||
CLOSE_BRACKET=']';
|
||||
@ -176,6 +178,19 @@ tokens {
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// We have a fragments library for strings that we want to splice in to the generated code.
|
||||
// This is Java, so to parse it we need to set IsJavaish so that we are a bit more lenient ...
|
||||
private bool isJavaish = false;
|
||||
public bool IsJavaish
|
||||
{
|
||||
get {
|
||||
return isJavaish;
|
||||
}
|
||||
set {
|
||||
isJavaish = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public compilation_unit:
|
||||
@ -485,8 +500,16 @@ public qid_part:
|
||||
public generic_argument_list:
|
||||
'<' type_arguments '>' ;
|
||||
public type_arguments:
|
||||
type (',' type)* ;
|
||||
|
||||
type_argument (',' type_argument)* ;
|
||||
public type_argument:
|
||||
{this.IsJavaish}?=> javaish_type_argument
|
||||
| type
|
||||
;
|
||||
public javaish_type_argument:
|
||||
('?' 'extends')=> '?' 'extends' type
|
||||
| '?'
|
||||
| type
|
||||
;
|
||||
public type:
|
||||
((predefined_type | type_name) rank_specifiers) => (predefined_type | type_name) rank_specifiers '*'*
|
||||
| ((predefined_type | type_name) ('*'+ | '?')) => (predefined_type | type_name) ('*'+ | '?')
|
||||
@ -1127,7 +1150,10 @@ public for_iterator:
|
||||
public statement_expression_list:
|
||||
statement_expression (',' statement_expression)* ;
|
||||
public foreach_statement:
|
||||
'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement ;
|
||||
'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement
|
||||
| {this.IsJavaish}? f='for' '(' local_variable_type identifier i=':' expression ')' embedded_statement
|
||||
-> FOREACH[$f,"foreach"] '(' local_variable_type identifier IN[$i,"in"] expression ')' embedded_statement
|
||||
;
|
||||
public jump_statement:
|
||||
break_statement
|
||||
| continue_statement
|
||||
|
Loading…
x
Reference in New Issue
Block a user