1
0
mirror of https://github.com/twiglet/cs2j.git synced 2025-01-18 13:15:17 +01:00

generate java main method to wrap a C# Main method

This commit is contained in:
Kevin Glynn 2010-12-19 10:22:15 +01:00
parent 71512e308f
commit 65508713f0
2 changed files with 118 additions and 25 deletions

View File

@ -21,6 +21,11 @@ scope NSContext {
string currentNS;
}
// A scope to keep track of the current type context
scope TypeContext {
string typeName;
}
@namespace { RusticiSoftware.Translator.CSharp }
@header
@ -69,11 +74,11 @@ scope NSContext {
protected CommonTree addConstModifiers(IToken tok, List<string> filter) {
CommonTree root = (CommonTree)adaptor.Nil;
if (!filter.Contains("static") )
if (filter == null || !filter.Contains("static") )
{
adaptor.AddChild(root, (CommonTree)adaptor.Create(STATIC, tok, "static"));
}
if (!filter.Contains("final"))
if (filter == null || !filter.Contains("final"))
{
adaptor.AddChild(root, (CommonTree)adaptor.Create(FINAL, tok, "final"));
}
@ -207,15 +212,15 @@ modifier:
class_member_declaration:
a=attributes?
m=modifiers?
( c='const' ct=type constant_declarators ';' -> ^(FIELD[$c.token, "FIELD"] $a? $m { addConstModifiers($c.token, $modifiers.modList) } $ct constant_declarators)
( c='const' ct=type constant_declarators ';' -> ^(FIELD[$c.token, "FIELD"] $a? $m? { addConstModifiers($c.token, $m.modList) } $ct constant_declarators)
| ed=event_declaration -> ^(EVENT[$ed.start.Token, "EVENT"] $a? $m? $ed)
| p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (v1=void_type m3=method_declaration[$a.tree, $m.tree, $v1.tree] -> $m3 //-> ^(METHOD[$v1.token, "METHOD"] $a? $m? ^(TYPE $v1) $m3)
| p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (v1=void_type m3=method_declaration[$a.tree, $m.tree, $m.modList, $v1.tree, $v1.text] -> $m3 //-> ^(METHOD[$v1.token, "METHOD"] $a? $m? ^(TYPE $v1) $m3)
| i1=interface_declaration -> ^(INTERFACE[$i1.start.Token, "INTERFACE"] $a? $m? $i1)
| c1=class_declaration -> ^(CLASS[$c1.start.Token, "CLASS"] $a? $m? $c1)
| s1=struct_declaration) -> ^(CLASS[$s1.start.Token, "CLASS"] $a? $m? $s1)
| i2=interface_declaration -> ^(INTERFACE[$i2.start.Token, "INTERFACE"] $a? $m? $i2) // 'interface'
| v2=void_type m1=method_declaration[$a.tree, $m.tree, $v2.tree] -> $m1 //-> ^(METHOD[$v.token, "METHOD"] $a? $m? ^(TYPE[$v.token, "TYPE"] $v) $m1)
| t=type ( (member_name type_parameter_list? '(') => m2=method_declaration[$a.tree, $m.tree, $t.tree] -> $m2
| v2=void_type m1=method_declaration[$a.tree, $m.tree, $m.modList, $v2.tree, $v2.text] -> $m1 //-> ^(METHOD[$v.token, "METHOD"] $a? $m? ^(TYPE[$v.token, "TYPE"] $v) $m1)
| t=type ( (member_name type_parameter_list? '(') => m2=method_declaration[$a.tree, $m.tree, $m.modList, $t.tree, $t.text] -> $m2
| (member_name '{') => pd=property_declaration[$a.tree, $m.tree, $t.tree] -> $pd
| (member_name '.' 'this') => type_name '.' ix1=indexer_declaration[$a.tree, $m.tree, $t.tree] -> $ix1
| ix2=indexer_declaration[$a.tree, $m.tree, $t.tree] -> $ix2 //this
@ -712,8 +717,10 @@ attribute_argument_expression:
// Class Section
///////////////////////////////////////////////////////
class_declaration returns [string name]:
c='class' identifier type_parameter_list? { $name = mkTypeName($identifier.text, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body ';'?
class_declaration returns [string name]
scope TypeContext;
:
c='class' identifier { $TypeContext::typeName = $identifier.text; } type_parameter_list? { $name = mkTypeName($identifier.text, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body ';'?
-> ^(CLASS[$c.Token] identifier type_parameter_constraints_clauses? type_parameter_list? class_base? class_body );
type_parameter_list returns [List<string> names]
@ -756,20 +763,62 @@ variable_declarator:
type_name ('=' variable_initializer)? ; // eg. event EventHandler IInterface.VariableName = Foo;
///////////////////////////////////////////////////////
method_declaration [CommonTree atts, CommonTree mods, CommonTree type]
method_declaration [CommonTree atts, CommonTree mods, List<string> modList, CommonTree type, String typeText]
@init {
bool isToString = false;
CommonTree exceptions = null;
CommonTree optMain = null;
bool isVoid = $typeText == "void";
bool isInt = $typeText == "int" || $typeText == "System.Int32" || $typeText == "Int32";
bool isMain = isVoid || isInt;
bool isMainHasArg = false;
}:
member_name { isToString = $member_name.text == "ToString"; } (type_parameter_list { isToString = false; })? '(' (formal_parameter_list { isToString = false; })? ')' ( type_parameter_constraints_clauses { isToString = false; })? b=method_body[isToString]
{ if (isToString) {
$member_name.tree.Token.Text = "toString";
}
else {
// TODO: According to the spec the C# Main() method should be static and not public. We aren't checking for lack of public
// we can check the modifiers in modList if we want to enforce that.
member_name { isToString = $member_name.text == "ToString"; isMain &= $member_name.text == "Main"; }
(type_parameter_list { isToString = false; isMain = false; })?
'('
// We are looking for ToString(), and Main(String[] args), where arg is optional.
(formal_parameter_list
{ isToString = false;
if (isMain) {
isMain = false;
// since we have an argument, must check its an array of String
if ($formal_parameter_list.tree != null && $formal_parameter_list.tree.Children != null && $formal_parameter_list.tree.Children.Count == 2) {
// parameter list children size is 2 (type arg)
CommonTree argTy = (CommonTree)$formal_parameter_list.tree.Children[0];
if (argTy != null && argTy.Children != null && argTy.Children.Count == 3) {
// Looking for Children of "String" "[" "]"
if (argTy.Children[0].Text.ToLower() == "string" &&
argTy.Children[1].Text == "[" &&
argTy.Children[2].Text == "]") {
// Bingo!
isMain = true;
isMainHasArg = true;
}
}
}
}
}
)?
')'
( type_parameter_constraints_clauses { isToString = false; isMain = false; })?
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]
mainCall=magicMainExit[isMain, isInt, $member_name.tree.Token, $mainApply.tree]
mainMethod=magicMainWrapper[isMain, $member_name.tree.Token, $mainCall.tree]
{ if (isToString) {
$member_name.tree.Token.Text = "toString";
}
exceptions = $b.exceptionList;
}
}
-> ^(METHOD { dupTree($atts) } { dupTree($mods) } { dupTree($type) }
}
-> $mainMethod?
^(METHOD { dupTree($atts) } { dupTree($mods) } { dupTree($type) }
member_name type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? $b { exceptions });
method_body [bool smotherExceptions] returns [CommonTree exceptionList]:
@ -832,8 +881,10 @@ remove_accessor_declaration:
///////////////////////////////////////////////////////
// enum declaration
///////////////////////////////////////////////////////
enum_declaration returns [string name]:
'enum' identifier { $name = $identifier.text; } enum_base? enum_body ';'? ;
enum_declaration returns [string name]
scope TypeContext;
:
'enum' identifier { $name = $identifier.text; $TypeContext::typeName = $identifier.text; } enum_base? enum_body ';'? ;
enum_base:
':' integral_type ;
enum_body:
@ -887,8 +938,10 @@ integral_type:
'sbyte' | 'byte' | 'short' | 'ushort' | 'int' | 'uint' | 'long' | 'ulong' | 'char' ;
// B.2.12 Delegates
delegate_declaration returns [string name]:
'delegate' return_type identifier { $name = $identifier.text; } variant_generic_parameter_list?
delegate_declaration returns [string name]
scope TypeContext;
:
'delegate' return_type identifier { $name = $identifier.text; $TypeContext::typeName = $identifier.text; } variant_generic_parameter_list?
'(' formal_parameter_list? ')' type_parameter_constraints_clauses? ';' ->
'delegate' return_type identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
'(' formal_parameter_list? ')' ';';
@ -951,8 +1004,10 @@ parameter_array:
'params' type identifier ;
///////////////////////////////////////////////////////
interface_declaration returns [string name]:
c='interface' identifier { $name = $identifier.text; } variant_generic_parameter_list?
interface_declaration returns [string name]
scope TypeContext;
:
c='interface' identifier { $name = $identifier.text; $TypeContext::typeName = $identifier.text; } variant_generic_parameter_list?
interface_base? type_parameter_constraints_clauses? interface_body ';'?
-> ^(INTERFACE[$c.Token] identifier type_parameter_constraints_clauses? variant_generic_parameter_list? interface_base? interface_body );
@ -997,8 +1052,10 @@ interface_accessor_declaration [CommonTree atts, CommonTree mods, CommonTree typ
;
///////////////////////////////////////////////////////
struct_declaration returns [string name]:
c='struct' identifier type_parameter_list? { $name = mkTypeName($identifier.text, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body ';'?
struct_declaration returns [string name]
scope TypeContext;
:
c='struct' identifier { $TypeContext::typeName = $identifier.text; } type_parameter_list? { $name = mkTypeName($identifier.text, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body ';'?
-> ^(CLASS[$c.Token, "class"] identifier type_parameter_constraints_clauses? type_parameter_list? class_base? class_body );
// UNUSED, HOPEFULLY
@ -1395,3 +1452,37 @@ magicSmotherExceptions[CommonTree body]:
magicThrowable:
-> EXCEPTION["Throwable"]
;
// METHOD{ public static TYPE{ void } main PARAMS{ TYPE{ String [ ] } args } { APPLY{ .{ System exit } ARGS{ APPLY{ .{ Program Main } } } } ;
magicMainArgs[bool isOn, IToken tok]:
-> { isOn }?
^(ARGS[tok, "ARGS"] IDENTIFIER[tok, "args"])
->
;
magicMainApply[bool isOn, IToken tok, String klass, CommonTree args]:
-> { isOn }?
^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] IDENTIFIER[tok,klass] IDENTIFIER[tok,"Main"]) { dupTree(args) } )
->
;
magicMainExit[bool isOn, bool retInt, IToken tok, CommonTree body]:
-> { isOn && retInt }?
^(APPLY[tok, "APPLY"] ^(DOT[tok,"."] IDENTIFIER[tok,"System"] IDENTIFIER[tok,"exit"]) ^(ARGS[tok, "ARGS"] { dupTree(body) } ) )
-> { isOn }?
{ dupTree(body) }
->
;
magicMainWrapper[bool isOn, IToken tok, CommonTree body]:
-> { isOn }?
^(METHOD[tok, "METHOD"]
PUBLIC[tok, "public"] STATIC[tok,"static"]
^(TYPE[tok, "TYPE"] IDENTIFIER[tok, "void"])
IDENTIFIER[tok, "main"] ^(PARAMS[tok, "PARAMS"] ^(TYPE[tok, "TYPE"] IDENTIFIER[tok,"String"] OPEN_BRACKET[tok, "["] CLOSE_BRACKET[tok, "]"]) IDENTIFIER[tok, "args"])
OPEN_BRACE[tok, "{"] { dupTree(body) } SEMI[tok, ";"] CLOSE_BRACE[tok, "}"]
EXCEPTION[tok, "Throwable"])
->
;

View File

@ -49,6 +49,8 @@ tokens {
RETURN = 'return';
PRIVATE = 'private';
PUBLIC = 'public';
PROTECTED = 'protected';
STATIC = 'static';
PRIVATE = 'private';
TRY = 'try';