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

progress on outputting expressions and if then else

This commit is contained in:
Kevin Glynn 2010-12-09 17:30:11 +01:00
parent 75ffb63350
commit 55363bc038
5 changed files with 153 additions and 99 deletions

View File

@ -7,37 +7,43 @@ namespace RusticiSoftware.Translator.CSharp
public class CS2JSettings
{
public bool DisplayTokens { get; set; }
public bool DisplayTokens { get; set; }
// dump parse trees to stdout
public bool DumpCSharp { get; set; }
public bool DumpJavaSyntax { get; set; }
public bool DumpJava { get; set; }
// dump parse trees to stdout
public bool DumpCSharp { get; set; }
public bool DumpJavaSyntax { get; set; }
public bool DumpJava { get; set; }
public bool DumpXmls { get; set; }
public bool DumpEnums { get; set; }
public string OutDir { get; set; }
public string CheatDir { get; set; }
public IList<string> NetRoot { get; set; }
public IList<string> ExNetRoot { get; set; }
public IList<string> AppRoot { get; set; }
public IList<string> ExAppRoot { get; set; }
public IList<string> Exclude { get; set; }
public IList<string> MacroDefines { get; set; }
public string XmlDir { get; set; }
public string EnumDir { get; set; }
public int Verbosity { get; set; }
public bool DumpXmls { get; set; }
public bool DumpEnums { get; set; }
public string OutDir { get; set; }
public string CheatDir { get; set; }
public IList<string> NetRoot { get; set; }
public IList<string> ExNetRoot { get; set; }
public IList<string> AppRoot { get; set; }
public IList<string> ExAppRoot { get; set; }
public IList<string> Exclude { get; set; }
public IList<string> MacroDefines { get; set; }
public string XmlDir { get; set; }
public string EnumDir { get; set; }
public int Verbosity { get; set; }
public int DebugLevel { get; set; }
public bool Warnings { get; set; }
public int DebugLevel { get; set; }
private bool translatorKeepParens = true;
public bool TranslatorKeepParens
{
get; set;
}
public bool Warnings { get; set; }
public CS2JSettings ()
{
public CS2JSettings ()
{
DisplayTokens = false;
// dump parse trees to stdout
DisplayTokens = false;
// dump parse trees to stdout
DumpCSharp = false;
DumpJavaSyntax = false;
DumpJava = false;
@ -53,11 +59,13 @@ namespace RusticiSoftware.Translator.CSharp
Exclude = new List<string>();
MacroDefines = new List<string>();
XmlDir = Path.Combine(Directory.GetCurrentDirectory(), "tmpXMLs");
EnumDir = Path.Combine(Directory.GetCurrentDirectory(), "enums");
EnumDir = Path.Combine(Directory.GetCurrentDirectory(), "enums");
Verbosity = 0;
DebugLevel = 0;
Warnings = false;
}
TranslatorKeepParens = true;
}
}
}

View File

@ -38,7 +38,7 @@ namespace RusticiSoftware.Translator.CSharp
Console.Out.WriteLine(" [-v] (be [somewhat more] verbose, repeat for more verbosity)");
Console.Out.WriteLine(" [-D <macroVariable>] (define <macroVariable>, option can be repeated)");
Console.Out.WriteLine(" [-showtokens] (the lexer prints the tokenized input to the console)");
Console.Out.WriteLine(" [-dumpcsharp] [-dumpjavasyntax] [-dumpjava] (show parse tree at various stages of the translation)");
Console.Out.WriteLine(" [-dumpcsharp] [-dumpjavasyntax] [-dumpjava] (show parse tree at various stages of the translation)");
Console.Out.WriteLine(" [-dumpxml] [-xmldir <directory to dump xml database>] (dump the translation repository as xml files)");
Console.Out.WriteLine(" [-dumpenums <enum xml file>] (create an xml file documenting enums)");
Console.Out.WriteLine(" [-odir <root of translated classes>]");
@ -48,6 +48,7 @@ namespace RusticiSoftware.Translator.CSharp
Console.Out.WriteLine(" [-appdir <root of C# application>]");
Console.Out.WriteLine(" [-exappdir <directories/files to be excluded from translation repository>+] (can be multiple directories/files, separated by semi-colons)");
Console.Out.WriteLine(" [-exclude <directories/files to be excluded from translation>+] (can be multiple directories/files, separated by semi-colons)");
Console.Out.WriteLine(" [-translator-keep-parens <true/false>] (keep parens from source, default true)");
Console.Out.WriteLine(" <directory or file name to be translated>");
Environment.Exit(0);
}
@ -96,6 +97,7 @@ namespace RusticiSoftware.Translator.CSharp
.Add ("appdir=", dirs => addDirectories(cfg.AppRoot, dirs))
.Add ("exappdir=", dirs => addDirectories(cfg.ExAppRoot, dirs))
.Add ("exclude=", dirs => addDirectories(cfg.Exclude, dirs))
.Add ("translator-keep-parens=", v => cfg.TranslatorKeepParens = Boolean.Parse(v))
;
//TODO: fix enum dump

View File

@ -511,10 +511,10 @@ unary_expression:
//('(' arguments ')' ('[' | '.' | '(')) => primary_or_array_creation_expression
(cast_expression) => cast_expression
| primary_or_array_creation_expression -> primary_or_array_creation_expression
| p='+' unary_expression -> ^(MONOPLUS[$p.token,"MONOPLUS"] unary_expression)
| m='-' unary_expression -> ^(MONOMINUS[$m.token, "MONOMINUS"] unary_expression)
| n='!' unary_expression -> ^(MONONOT[$n.token, "MONONOT"] unary_expression)
| t='~' unary_expression -> ^(MONOTWIDDLE[$t.token, "TWIDDLE"] unary_expression)
| p='+' unary_expression -> ^(MONOPLUS[$p.token,"+"] unary_expression)
| m='-' unary_expression -> ^(MONOMINUS[$m.token, "-"] unary_expression)
| n='!' unary_expression -> ^(MONONOT[$n.token, "!"] unary_expression)
| t='~' unary_expression -> ^(MONOTWIDDLE[$t.token, "~"] unary_expression)
| pre_increment_expression -> pre_increment_expression
| pre_decrement_expression -> pre_decrement_expression
| pointer_indirection_expression -> pointer_indirection_expression

View File

@ -208,6 +208,12 @@ options {
public int comparePrecedence(IToken op1, IToken op2) {
return Math.Sign(precedence[op2.Type]-precedence[op1.Type]);
}
public int comparePrecedence(IToken op1, int childPrec) {
return Math.Sign(childPrec-precedence[op1.Type]);
}
public int comparePrecedence(int parentPrec, int childPrec) {
return Math.Sign(childPrec-parentPrec);
}
}
compilation_unit
@ -296,7 +302,7 @@ class_member_declaration returns [List<String> preComments]:
//
primary_expression:
^(INDEX expression expression_list?)
| ^(APPLY expression argument_list?)
| ^(APPLY expression argument_list?) -> application(func= { $expression.st }, funcparens = { comparePrecedence(APPLY, $expression.precedence) <= 0 }, args = { $argument_list.st } )
| ^(POSTINC expression)
| ^(POSTDEC expression)
| primary_expression_start -> { $primary_expression_start.st }
@ -359,7 +365,7 @@ primary_expression_part:
access_identifier:
access_operator type_or_generic ;
access_operator:
'.' | '->' ;
(op='.' | op='->') -> string(payload = { $op.token.Text }) ;
brackets_or_arguments:
brackets | arguments ;
brackets:
@ -558,7 +564,7 @@ type
List<string> stars = new List<string>();
string opt = null;
}:
^(TYPE (tp=predefined_type {nm=$tp.st;} | tn=type_name {nm=$tn.st;} | tv='void' {nm=new StringTemplate("void");}) rank_specifiers? ('*' { stars.Add("*");})* ('?' { opt = "?";} )?) -> type(name={ nm }, stars={ stars }, rs={ $rank_specifiers.st }, opt={ opt })
^(TYPE (tp=predefined_type {nm=$tp.st;} | tn=type_name {nm=$tn.st;} | tv='void' { nm=%void();}) rank_specifiers? ('*' { stars.Add("*");})* ('?' { opt = "?";} )?) -> type(name={ nm }, stars={ stars }, rs={ $rank_specifiers.st }, opt={ opt })
;
non_nullable_type:
type -> { $type.st } ;
@ -591,33 +597,45 @@ statement_list:
///////////////////////////////////////////////////////
// Expression Section
///////////////////////////////////////////////////////
expression:
(unary_expression assignment_operator) => assignment
| non_assignment_expression -> { $non_assignment_expression.st }
expression returns [int precedence]:
(unary_expression assignment_operator) => assignment { $precedence = $assignment.precedence; } -> { $assignment.st }
| non_assignment_expression { $precedence = $non_assignment_expression.precedence; } -> { $non_assignment_expression.st }
;
expression_list:
expression (',' expression)* ;
assignment:
unary_expression assignment_operator expression ;
unary_expression:
assignment returns [int precedence]:
unary_expression assignment_operator expression { $precedence = $assignment_operator.precedence; }
-> assign(lhs={ $unary_expression.st }, assign = { $assignment_operator.st }, rhs = { $expression.st },
lhsparen={ comparePrecedence($assignment_operator.precedence, $unary_expression.precedence) <= 0 },
rhsparen={ comparePrecedence($assignment_operator.precedence, $expression.precedence) < 0});
unary_expression returns [int precedence]
@init {
// By default parens not needed
$precedence = int.MaxValue;
}:
//('(' arguments ')' ('[' | '.' | '(')) => primary_or_array_creation_expression
// ^(CAST_EXPR type expression)
^(CAST_EXPR type u0=unary_expression) -> cast_expr(type= { $type.st}, exp = { $u0.st})
^(CAST_EXPR type u0=unary_expression) { $precedence = precedence[CAST_EXPR]; } -> cast_expr(type= { $type.st}, exp = { $u0.st})
| primary_or_array_creation_expression -> { $primary_or_array_creation_expression.st }
| ^(MONOPLUS u1=unary_expression) -> op(op={"+"}, post={$u1.st})
| ^(MONOMINUS u2=unary_expression) -> op(op={"-"}, post={$u2.st})
| ^(MONONOT u3=unary_expression) -> op(op={"!"}, post={$u3.st})
| ^(MONOTWIDDLE u4=unary_expression) -> op(op={"~"}, post={$u4.st})
| ^(PREINC u5=unary_expression) -> op(op={"++"}, post={$u5.st})
| ^(PREDEC u6=unary_expression) -> op(op={"--"}, post={$u6.st})
| ^(MONOSTAR unary_expression)
| ^(ADDRESSOF unary_expression)
// PARENS is not stictly necessary because we insert parens where necessary. However
// we maintin parens inserted by original programmer since tey presumably thought
// it would improve understandability
| ^(PARENS expression) -> parens(e={$expression.st})
| ^((op=MONOPLUS | op=MONOMINUS | op=MONONOT | op=MONOTWIDDLE | op=PREINC | op=PREDEC) u1=unary_expression) { $precedence = precedence[$op.token.Type]; }
-> op(postparen={ comparePrecedence($op.token, $u1.precedence) > 0 }, op={ $op.token.Text }, post={$u1.st})
| ^((op=MONOSTAR|op=ADDRESSOF) u1=unary_expression)
{
StringTemplate opText = %op();
%{opText}.post = $u1.st;
%{opText}.op = $op.token.Text;
$st = %unsupported();
%{$st}.reason = "the " + ($op.token.Type == MONOSTAR ? "pointer indirection" : "address of") + " operator is not supported";
%{$st}.text = opText;
}
// PARENS is not strictly necessary because we insert parens where necessary. However
// we maintain parens inserted by original programmer since, presumably, they
// improve understandability
| ^(PARENS expression) { $precedence = Cfg.TranslatorKeepParens ? int.MaxValue : $expression.precedence; }
-> { Cfg.TranslatorKeepParens}? parens(e={$expression.st})
-> {$expression.st}
;
// (cast_expression) => cast_expression
// | primary_or_array_creation_expression -> { $primary_or_array_creation_expression.st }
// | '+' u1=unary_expression -> template(e={$u1.st}) "+<e>"
@ -631,8 +649,9 @@ unary_expression:
// ;
// cast_expression:
// ^(CAST_EXPR type unary_expression ) -> cast_expr(type= { $type.st}, exp = { $unary_expression.st});
assignment_operator:
'=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>' '>=' ;
assignment_operator returns [int precedence]:
(op='=' | op='+=' | op='-=' | op='*=' | op='/=' | op='%=' | op='&=' | op='|=' | op='^=' | op='<<=' | op=RIGHT_SHIFT_ASSIGN) { $precedence = precedence[$op.token.Type]; }
-> string(payload = { $op.token.Text });
// pre_increment_expression:
// '++' unary_expression ;
// pre_decrement_expression:
@ -642,32 +661,24 @@ unary_expression:
// addressof_expression:
// '&' unary_expression ;
non_assignment_expression:
non_assignment_expression returns [int precedence]
@init {
// By default parens not needed
$precedence = int.MaxValue;
}:
//'non ASSIGNment'
(anonymous_function_signature '=>') => lambda_expression
| (query_expression) => query_expression
| ^(COND_EXPR non_assignment_expression non_assignment_expression non_assignment_expression)
| ^('??' non_assignment_expression non_assignment_expression)
| ^('||' non_assignment_expression non_assignment_expression)
| ^('&&' non_assignment_expression non_assignment_expression)
| ^('|' non_assignment_expression non_assignment_expression)
| ^('^' non_assignment_expression non_assignment_expression)
| ^('&' non_assignment_expression non_assignment_expression)
| ^('==' non_assignment_expression non_assignment_expression)
| ^('!=' non_assignment_expression non_assignment_expression)
| ^('>' non_assignment_expression non_assignment_expression)
| ^('<' non_assignment_expression non_assignment_expression)
| ^('>=' non_assignment_expression non_assignment_expression)
| ^('<=' non_assignment_expression non_assignment_expression)
// All these operators have left to right associativity
| ^((op='=='|op='!='|op='||'|op='&&'|op='|'|op='^'|op='&'|op='>'|op='<'|op='>='|op='<='|op='<<'|op='>>'|op='+'|op='-'|op='*'|op='/'|op='%')
e1=non_assignment_expression e2=non_assignment_expression)
-> op(pre={ $e1.st }, op = { $op.token.Text }, post = { $e2.st }, space = { " " },
preparen={ comparePrecedence($op.token, $e1.precedence) < 0 },
postparen={ comparePrecedence($op.token, $e2.precedence) <= 0})
| ^(INSTANCEOF non_assignment_expression non_nullable_type)
| ^('<<' non_assignment_expression non_assignment_expression)
| ^('>>' non_assignment_expression non_assignment_expression)
| ^('+' non_assignment_expression non_assignment_expression)
| ^('-' non_assignment_expression non_assignment_expression)
| ^('*' non_assignment_expression non_assignment_expression)
| ^('/' non_assignment_expression non_assignment_expression)
| ^('%' non_assignment_expression non_assignment_expression)
| unary_expression -> { $unary_expression.st }
| unary_expression { $precedence = $unary_expression.precedence; }-> { $unary_expression.st }
;
///////////////////////////////////////////////////////
@ -732,7 +743,7 @@ group_clause:
where_clause:
'where' boolean_expression ;
boolean_expression:
expression;
expression -> { $expression.st };
///////////////////////////////////////////////////////
// B.2.13 Attributes
@ -1127,9 +1138,13 @@ statement_plus:
(identifier ':') => labeled_statement -> statement(statement = { $labeled_statement.st })
| embedded_statement -> statement(statement = { $embedded_statement.st })
;
embedded_statement:
block -> { $block.st }
| selection_statement -> { $selection_statement.st } // if, switch
embedded_statement returns [bool isSemi, bool isBraces, bool isIf]
@init {
$isBraces = false;
$isIf = false;
}:
block { $isSemi = $block.isSemi; $isBraces = !$block.isSemi;} -> { $block.st }
| selection_statement { $isIf = $selection_statement.isIf; }-> { $selection_statement.st } // if, switch
| iteration_statement -> { $iteration_statement.st } // while, do, for, foreach
| jump_statement -> { $jump_statement.st } // break, continue, goto, return, throw
| try_statement -> { $try_statement.st }
@ -1140,7 +1155,7 @@ embedded_statement:
| yield_statement
| unsafe_statement
| fixed_statement
| expression_statement -> { $expression_statement.st } // expression!
| expression_statement -> op( pre={ $expression_statement.st }, op={ ";" }) // make an expression a statement, need to terminate with semi
;
fixed_statement:
'fixed' '(' pointer_type fixed_pointer_declarators ')' embedded_statement ;
@ -1161,8 +1176,8 @@ declaration_statement:
local_variable_declaration:
local_variable_type local_variable_declarators -> local_variable_declaration(type={ $local_variable_type.st }, decs = { $local_variable_declarators.st } );
local_variable_type:
('var') => 'var' -> string(payload = {"/* [UNSUPPORTED] 'var' as type is unsupported */"} )
| ('dynamic') => 'dynamic' -> string(payload = {"/* [UNSUPPORTED] 'dynamic' as type is unsupported */"} )
('var') => 'var' -> unsupported(reason = {"'var' as type is unsupported"}, text = { "var" } )
| ('dynamic') => 'dynamic' -> unsupported(reason = {"'dynamic' as type is unsupported"}, text = { "dynamic" } )
| type -> { $type.st } ;
local_variable_declarators:
vs+=local_variable_declarator (',' vs+=local_variable_declarator)* -> list(items={$vs}, sep={", "});
@ -1185,15 +1200,18 @@ expression_statement:
statement_expression:
expression
;
selection_statement:
if_statement -> { $if_statement.st }
| switch_statement -> { $switch_statement.st };
selection_statement returns [bool isIf]:
if_statement { $isIf = true; }-> { $if_statement.st }
| switch_statement { $isIf = false; }-> { $switch_statement.st };
if_statement:
// else goes with closest if
^(IF boolean_expression SEP embedded_statement else_statement?) -> if(cond= { $boolean_expression.st }, then = { $embedded_statement.st }, else = { $else_statement.st })
^(IF boolean_expression SEP t=embedded_statement e=else_statement?)
-> if(cond= { $boolean_expression.st },
then = { $t.st }, thensemi = { $t.isSemi }, thenbraces = { $t.isBraces },
else = { $else_statement.st }, elsesemi = { $e.isSemi }, elsebraces = { $e.isBraces }, elseisif = { $e.isIf })
;
else_statement:
'else' embedded_statement -> { $embedded_statement.st } ;
else_statement returns [bool isSemi, bool isBraces, bool isIf]:
'else' s=embedded_statement { $isSemi = $s.isSemi; $isBraces = $s.isBraces; $isIf = $s.isIf; } -> { $embedded_statement.st } ;
switch_statement:
'switch' '(' expression ')' switch_block ;
switch_block:
@ -1247,7 +1265,7 @@ goto_statement:
return_statement:
'return' expression? ';' -> return(exp = { $expression.st });
throw_statement:
'throw' expression? ';' ;
'throw' expression? ';' -> throw(exp = { $expression.st });
try_statement:
'try' block ( catch_clauses finally_clause?
| finally_clause);

View File

@ -79,16 +79,17 @@ statement_list(statements) ::= <<
>>
statement(statement) ::= <<
<statement>;
<statement>
>>
//***** local var declarations:
local_variable_declaration(type,decs) ::= "<type> <decs>"
local_variable_declaration(type,decs) ::= "<type> <decs>;"
local_variable_declarator(name, init) ::= "<name><if(init)> = <init><endif>"
return(exp) ::= "return <exp>"
return(exp) ::= "return <exp>;"
throw(exp) ::= "throw <exp>;"
// ******* ENUMS ***********
@ -120,24 +121,49 @@ extends(types) ::= "<if(types)>extends <types; separator=\",\"><endif>"
imps(types) ::= "<if(types)>implements <types; separator=\",\"><endif>"
// ******* STATEMENTS *******
if(cond,then,else) ::= <<
if(cond,then,thensemi, thenbraces,else, elseisif, elsesemi,elsebraces) ::= <<
if (<cond>)
<then>
<block(statements = then, issemi = thensemi, isbraces = thenbraces)>
<if(else)>
else<if(elseisif)> <block(statements = else, issemi = elsesemi, isbraces = elsebraces)><else>
<block(statements = else, issemi = elsesemi, isbraces = elsebraces)>
<endif>
<endif>
>>
block(statements,issemi,isbraces) ::= <<
<if(issemi)>
;
<else>
<if(isbraces)>
{
<endif>
<statements>
<if(isbraces)>
}
<endif>
<endif>
>>
// ******* EXPRESSIONS *******
cast_expr(type, exp) ::= "(<type>)<exp>"
construct(type, args, inits) ::= "new <type>(<args>)<if(inits)> /* [UNIMPLEMENTED] <inits> */<endif>"
application(func, funcparens, args) ::= "<optparens(parens=funcparens,e=func)>(<args>)"
stackalloc(type, exp) ::= "stackalloc <type>[<exp>]"
// ******* TYPES ***********
void() ::= "void"
// ******* MISC ***********
optparens(parens, e) ::= "<if(parens)>(<endif><e><if(parens)>)<endif>"
parens(e) ::= "(<e>)"
rank_specifiers(rs) ::= "<rs>"
op(pre,op,post) ::= "<pre><op><post>"
op(pre,op,post,mkparen,space) ::= "<if(mkparen)>(<endif><pre><space><op><space><post><if(mkparen)>)<endif>"
assign(lhs,lhsparen,assign,rhs,rhsparen) ::= "<if(lhsparen)>(<endif><lhs><if(lhsparen)>)<endif> <assign> <if(rhsparen)>(<endif><rhs><if(rhsparen)>)<endif>"
generic_args(args) ::= "\<<args>\>"
parameter(annotation,param) ::= "/* <annotation> */ <param>"
inline_comment(payload, explanation) ::= "/* <explanation> <payload> */"