mirror of
https://github.com/twiglet/cs2j.git
synced 2025-01-18 13:15:17 +01:00
implement top level partial types
This commit is contained in:
parent
24ea1b1fc3
commit
0b8e05d0a6
@ -45,6 +45,8 @@ namespace Twiglet.CS2J.Translator
|
|||||||
|
|
||||||
public delegate void FileProcessor(string fName);
|
public delegate void FileProcessor(string fName);
|
||||||
|
|
||||||
|
private static Dictionary<string, ClassDescriptorSerialized> partialTypes = new Dictionary<string, ClassDescriptorSerialized>();
|
||||||
|
|
||||||
private static void showVersion()
|
private static void showVersion()
|
||||||
{
|
{
|
||||||
Console.Out.WriteLine(Path.GetFileNameWithoutExtension(System.Environment.GetCommandLineArgs()[0]) + ": " + VERSION);
|
Console.Out.WriteLine(Path.GetFileNameWithoutExtension(System.Environment.GetCommandLineArgs()[0]) + ": " + VERSION);
|
||||||
@ -207,6 +209,10 @@ namespace Twiglet.CS2J.Translator
|
|||||||
foreach (string r in csDir)
|
foreach (string r in csDir)
|
||||||
doFile(r, ".cs", translateFile, cfg.Exclude); // translate it
|
doFile(r, ".cs", translateFile, cfg.Exclude); // translate it
|
||||||
|
|
||||||
|
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out collected partial types");
|
||||||
|
foreach (KeyValuePair<string, ClassDescriptorSerialized> entry in partialTypes)
|
||||||
|
emitPartialType(entry.Key, entry.Value);
|
||||||
|
|
||||||
if (cfg.DumpEnums)
|
if (cfg.DumpEnums)
|
||||||
{
|
{
|
||||||
enumXmlWriter.WriteEndElement();
|
enumXmlWriter.WriteEndElement();
|
||||||
@ -531,12 +537,31 @@ namespace Twiglet.CS2J.Translator
|
|||||||
|
|
||||||
outputMaker.Cfg = cfg;
|
outputMaker.Cfg = cfg;
|
||||||
outputMaker.EmittedCommentTokenIdx = saveEmittedCommentTokenIdx;
|
outputMaker.EmittedCommentTokenIdx = saveEmittedCommentTokenIdx;
|
||||||
|
outputMaker.IsPartial = javaMaker.CUMap[typeName].IsPartial;
|
||||||
|
if (outputMaker.IsPartial)
|
||||||
|
{
|
||||||
|
if (!partialTypes.ContainsKey(typeName))
|
||||||
|
{
|
||||||
|
partialTypes[typeName] = new ClassDescriptorSerialized(claName);
|
||||||
|
partialTypes[typeName].FileName = javaFName;
|
||||||
|
}
|
||||||
|
outputMaker.PartialDescriptor = partialTypes[typeName];
|
||||||
|
}
|
||||||
|
|
||||||
outputMaker.IsLast = i == (javaMaker.CUKeys.Count - 1);
|
outputMaker.IsLast = i == (javaMaker.CUKeys.Count - 1);
|
||||||
|
|
||||||
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", javaFName);
|
if (!outputMaker.IsPartial)
|
||||||
StreamWriter javaW = new StreamWriter(javaFName);
|
{
|
||||||
javaW.Write(limit(outputMaker.compilation_unit().ToString()));
|
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", javaFName);
|
||||||
javaW.Close();
|
StreamWriter javaW = new StreamWriter(javaFName);
|
||||||
|
javaW.Write(limit(outputMaker.compilation_unit().ToString()));
|
||||||
|
javaW.Close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// fill out partialTypes[typeName]
|
||||||
|
outputMaker.compilation_unit();
|
||||||
|
}
|
||||||
saveEmittedCommentTokenIdx = outputMaker.EmittedCommentTokenIdx;
|
saveEmittedCommentTokenIdx = outputMaker.EmittedCommentTokenIdx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -546,5 +571,29 @@ namespace Twiglet.CS2J.Translator
|
|||||||
System.Console.Out.WriteLine("");
|
System.Console.Out.WriteLine("");
|
||||||
System.Console.Out.WriteLine("");
|
System.Console.Out.WriteLine("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void emitPartialType(string name, ClassDescriptorSerialized serTy)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Pretty print as text
|
||||||
|
Dictionary<string,object> args = new Dictionary<string,object>();
|
||||||
|
args["now"] = DateTime.Now;
|
||||||
|
args["includeDate"] = cfg.TranslatorAddTimeStamp;
|
||||||
|
args["packageName"] = serTy.Package;
|
||||||
|
args["imports"] = serTy.Imports;
|
||||||
|
args["modifiers"] = serTy.Mods;
|
||||||
|
args["name"] = serTy.Identifier;
|
||||||
|
args["extends"] = serTy.ClassBase;
|
||||||
|
args["imps"] = serTy.ClassImplements;
|
||||||
|
args["body"] = serTy.ClassBody;
|
||||||
|
|
||||||
|
StringTemplate st = templates.GetInstanceOf("partial_type", args);
|
||||||
|
|
||||||
|
// new STAttrMap().Add("now", DateTime.Now).Add("includeDate", Cfg.TranslatorAddTimeStamp).Add("packageName", (((nm != null) ? nm.Text : null) != null && ((nm != null) ? nm.Text : null).Length > 0 ? ((nm != null) ? nm.Text : null) : null)).Add("imports", ((imports1 != null) ? imports1.ST : null)).Add("type", ((type_declaration2 != null) ? type_declaration2.ST : null)).Add("endComments", CollectedComments ));
|
||||||
|
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Writing out {0}", serTy.FileName);
|
||||||
|
StreamWriter javaW = new StreamWriter(serTy.FileName);
|
||||||
|
javaW.Write(limit(st.ToString()));
|
||||||
|
javaW.Close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -40,8 +40,27 @@ package(now, includeDate, packageName, imports, comments, modifiers, type, endCo
|
|||||||
<endComments; separator=""\n"">
|
<endComments; separator=""\n"">
|
||||||
>>
|
>>
|
||||||
|
|
||||||
|
import_list(nss) ::= <<
|
||||||
|
<nss:{x | import <x>;}; separator=""\n"">
|
||||||
|
>>
|
||||||
|
|
||||||
import_template(ns) ::= ""import <ns>;""
|
import_template(ns) ::= ""import <ns>;""
|
||||||
|
|
||||||
|
// ****** output partial type ******
|
||||||
|
partial_type(now, includeDate, packageName, imports, modifiers, comments, attributes, name, typeparams, extends, imps, body) ::= <<
|
||||||
|
<itsmine(now=now,includeDate=includeDate)>
|
||||||
|
<if(packageName)>package <packageName>;<endif>
|
||||||
|
|
||||||
|
<comments; separator=""\n"">
|
||||||
|
<import_list(imports)>
|
||||||
|
|
||||||
|
<modifiers(modifiers)>class <name> <typeparams> <extends><if(imps)> implements <imps; separator="",""><endif>
|
||||||
|
{
|
||||||
|
<body>
|
||||||
|
}
|
||||||
|
|
||||||
|
>>
|
||||||
|
|
||||||
// ******* CLASSES ***********
|
// ******* CLASSES ***********
|
||||||
|
|
||||||
class(modifiers, comments, attributes, name, typeparams, extends, imps, body) ::= <<
|
class(modifiers, comments, attributes, name, typeparams, extends, imps, body) ::= <<
|
||||||
@ -347,3 +366,4 @@ verbatim_string(payload) ::= <<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -234,12 +234,19 @@ namespace Twiglet.CS2J.Translator.Transform
|
|||||||
// Wraps a compilation unit with its imports search path
|
// Wraps a compilation unit with its imports search path
|
||||||
public class CUnit {
|
public class CUnit {
|
||||||
|
|
||||||
public CUnit(CommonTree inTree, List<string> inSearchPath, List<string> inAliasKeys, List<string> inAliasValues) {
|
public CUnit(CommonTree inTree, List<string> inSearchPath, List<string> inAliasKeys, List<string> inAliasValues)
|
||||||
|
: this(inTree, inSearchPath, inAliasKeys, inAliasValues, false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public CUnit(CommonTree inTree, List<string> inSearchPath, List<string> inAliasKeys, List<string> inAliasValues, bool inIsPartial) {
|
||||||
Tree = inTree;
|
Tree = inTree;
|
||||||
SearchPath = inSearchPath;
|
SearchPath = inSearchPath;
|
||||||
NameSpaceAliasKeys = inAliasKeys;
|
NameSpaceAliasKeys = inAliasKeys;
|
||||||
NameSpaceAliasValues = inAliasValues;
|
NameSpaceAliasValues = inAliasValues;
|
||||||
|
IsPartial = inIsPartial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public CommonTree Tree {get; set;}
|
public CommonTree Tree {get; set;}
|
||||||
|
|
||||||
// namespaces in scope
|
// namespaces in scope
|
||||||
@ -248,6 +255,64 @@ namespace Twiglet.CS2J.Translator.Transform
|
|||||||
// aliases for namespaces
|
// aliases for namespaces
|
||||||
public List<string> NameSpaceAliasKeys {get; set;}
|
public List<string> NameSpaceAliasKeys {get; set;}
|
||||||
public List<string> NameSpaceAliasValues {get; set;}
|
public List<string> NameSpaceAliasValues {get; set;}
|
||||||
|
public bool IsPartial {get; set;}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClassDescriptor {
|
||||||
|
public IToken Token { get;set; }
|
||||||
|
public String Comments { get;set; }
|
||||||
|
public CommonTree Atts { get;set; }
|
||||||
|
public CommonTree Mods { get;set; }
|
||||||
|
public CommonTree Identifier { get;set; }
|
||||||
|
public CommonTree TypeParameterList { get;set; }
|
||||||
|
public CommonTree ClassBase { get;set; }
|
||||||
|
public CommonTree TypeParameterConstraintsClauses { get;set; }
|
||||||
|
public CommonTree ClassBody { get;set; }
|
||||||
|
public Dictionary<String, ClassDescriptor> PartialTypes { get;set; }
|
||||||
|
|
||||||
|
public ClassDescriptor(IToken inToken, String inComments, CommonTree inAtts, CommonTree inMods, CommonTree inIdentifier, CommonTree inTypeParameterList, CommonTree inClassBase, CommonTree inTypeParameterConstraintsClauses, CommonTree inClassBody, Dictionary<String, ClassDescriptor> inPartialTypes) {
|
||||||
|
Token = inToken;
|
||||||
|
Comments = inComments;
|
||||||
|
Atts = inAtts;
|
||||||
|
Mods = inMods;
|
||||||
|
Identifier = inIdentifier;
|
||||||
|
TypeParameterList = inTypeParameterList;
|
||||||
|
ClassBase = inClassBase;
|
||||||
|
TypeParameterConstraintsClauses = inTypeParameterConstraintsClauses;
|
||||||
|
ClassBody = inClassBody;
|
||||||
|
PartialTypes = inPartialTypes;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ClassDescriptorSerialized {
|
||||||
|
public String FileName { get;set; }
|
||||||
|
public List<String> Imports { get;set; }
|
||||||
|
public String Package { get;set; }
|
||||||
|
public String Comments { get;set; }
|
||||||
|
public String Atts { get;set; }
|
||||||
|
public List<String> Mods { get;set; }
|
||||||
|
public String Identifier { get;set; }
|
||||||
|
public String TypeParameterList { get;set; }
|
||||||
|
public String ClassBase { get;set; }
|
||||||
|
public List<String> ClassImplements { get;set; }
|
||||||
|
public String TypeParameterConstraintsClauses { get;set; }
|
||||||
|
public String ClassBody { get;set; }
|
||||||
|
|
||||||
|
public ClassDescriptorSerialized(string name)
|
||||||
|
{
|
||||||
|
FileName = "";
|
||||||
|
Comments = "";
|
||||||
|
Imports = new List<String>();
|
||||||
|
Package = "";
|
||||||
|
Atts = "";
|
||||||
|
Mods = new List<String>();
|
||||||
|
Identifier = name;
|
||||||
|
TypeParameterList = "";
|
||||||
|
ClassBase = "";
|
||||||
|
ClassImplements = new List<String>();
|
||||||
|
TypeParameterConstraintsClauses = "";
|
||||||
|
ClassBody = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ scope NSContext {
|
|||||||
// A scope to keep track of the current type context
|
// A scope to keep track of the current type context
|
||||||
scope TypeContext {
|
scope TypeContext {
|
||||||
string typeName;
|
string typeName;
|
||||||
|
Dictionary<String,ClassDescriptor> partialTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@namespace { Twiglet.CS2J.Translator.Transform }
|
@namespace { Twiglet.CS2J.Translator.Transform }
|
||||||
@ -42,6 +43,7 @@ scope TypeContext {
|
|||||||
using System;
|
using System;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@members
|
@members
|
||||||
@ -49,11 +51,29 @@ scope TypeContext {
|
|||||||
|
|
||||||
// Since a CS file may comtain multiple top level types (and so generate multiple Java
|
// Since a CS file may comtain multiple top level types (and so generate multiple Java
|
||||||
// files) we build a map from type name to AST for each top level type
|
// files) we build a map from type name to AST for each top level type
|
||||||
// We also build a lit of type names so that we can maintain the order (so comments
|
// We also build a list of type names so that we can maintain the order (so comments
|
||||||
// at the end of the file will get included when we emit the java for the last type)
|
// at the end of the file will get included when we emit the java for the last type)
|
||||||
public IDictionary<string, CUnit> CUMap { get; set; }
|
public IDictionary<string, CUnit> CUMap { get; set; }
|
||||||
public IList<string> CUKeys { get; set; }
|
public IList<string> CUKeys { get; set; }
|
||||||
|
|
||||||
|
// we keep track of the end position of the previous class / struct member
|
||||||
|
// so that we can collect comments for a partial type definition
|
||||||
|
private int prevMemberEndTokenIndex = -1;
|
||||||
|
|
||||||
|
protected string snaffleComments(int startIndex, int endIndex) {
|
||||||
|
StringBuilder ret = new StringBuilder();
|
||||||
|
List<IToken> toks = ((CommonTokenStream)this.GetTreeNodeStream().TokenStream).GetTokens(startIndex,endIndex);
|
||||||
|
if (toks != null) {
|
||||||
|
foreach (IToken tok in toks) {
|
||||||
|
if (tok.Channel == TokenChannels.Hidden) {
|
||||||
|
ret.Append(new Regex("(\\n|\\r)+").Replace(tok.Text, Environment.NewLine).Trim());
|
||||||
|
// Hide from Pretty Printer
|
||||||
|
tok.Channel = TokenChannels.Hidden - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret.ToString();
|
||||||
|
}
|
||||||
protected string ParentNameSpace {
|
protected string ParentNameSpace {
|
||||||
get {
|
get {
|
||||||
return ((NSContext_scope)$NSContext.ToArray()[1]).currentNS;
|
return ((NSContext_scope)$NSContext.ToArray()[1]).currentNS;
|
||||||
@ -140,7 +160,7 @@ scope TypeContext {
|
|||||||
// null, or
|
// null, or
|
||||||
// a single token, or
|
// a single token, or
|
||||||
// a list of tokens (^(NIL ......))
|
// a list of tokens (^(NIL ......))
|
||||||
protected CommonTree addModifier(IToken tok, CommonTree mods, CommonTree modToAdd) {
|
protected CommonTree addModifier(CommonTree mods, CommonTree modToAdd) {
|
||||||
|
|
||||||
CommonTree root = (CommonTree)adaptor.Nil;
|
CommonTree root = (CommonTree)adaptor.Nil;
|
||||||
|
|
||||||
@ -149,7 +169,7 @@ scope TypeContext {
|
|||||||
if (mods != null) {
|
if (mods != null) {
|
||||||
// Is root node the one we are looking for?
|
// Is root node the one we are looking for?
|
||||||
if (!mods.IsNil) {
|
if (!mods.IsNil) {
|
||||||
if (adaptor.GetType(mods) == adaptor.GetType(modToAdd)) {
|
if (adaptor.GetType(mods) == adaptor.GetType(modToAdd) && adaptor.GetText(mods) == adaptor.GetText(modToAdd)) {
|
||||||
modSeen = true;
|
modSeen = true;
|
||||||
}
|
}
|
||||||
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(mods));
|
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(mods));
|
||||||
@ -157,7 +177,7 @@ scope TypeContext {
|
|||||||
else {
|
else {
|
||||||
for (int i = 0; i < adaptor.GetChildCount(mods); i++) {
|
for (int i = 0; i < adaptor.GetChildCount(mods); i++) {
|
||||||
CommonTree child = (CommonTree)adaptor.GetChild(mods,i);
|
CommonTree child = (CommonTree)adaptor.GetChild(mods,i);
|
||||||
if (adaptor.GetType(child) == adaptor.GetType(modToAdd)) {
|
if (adaptor.GetType(child) == adaptor.GetType(modToAdd) && adaptor.GetText(child) == adaptor.GetText(modToAdd)) {
|
||||||
modSeen = true;
|
modSeen = true;
|
||||||
}
|
}
|
||||||
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(child));
|
adaptor.AddChild(root, (CommonTree)adaptor.DupTree(child));
|
||||||
@ -172,6 +192,24 @@ scope TypeContext {
|
|||||||
return root;
|
return root;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add all modifiers in modToAdd tree
|
||||||
|
protected CommonTree mergeModifiers(CommonTree mods, CommonTree modToAdd) {
|
||||||
|
|
||||||
|
if (modToAdd == null)
|
||||||
|
return mods;
|
||||||
|
|
||||||
|
if (!modToAdd.IsNil) {
|
||||||
|
return addModifier(mods, modToAdd);
|
||||||
|
}
|
||||||
|
|
||||||
|
CommonTree ret = mods;
|
||||||
|
for (int i = 0; i < adaptor.GetChildCount(modToAdd); i++) {
|
||||||
|
ret = addModifier(mods, (CommonTree)adaptor.GetChild(modToAdd, i));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// mods is a list of modifiers. removes is a list of token types, we remove all modifiers appearing in removes
|
// mods is a list of modifiers. removes is a list of token types, we remove all modifiers appearing in removes
|
||||||
protected CommonTree mkRemoveMods(CommonTree mods, int[] removes) {
|
protected CommonTree mkRemoveMods(CommonTree mods, int[] removes) {
|
||||||
|
|
||||||
@ -467,6 +505,73 @@ scope TypeContext {
|
|||||||
}
|
}
|
||||||
return ret.ToString();
|
return ret.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merges part into combined
|
||||||
|
protected void mergePartialTypes(ClassDescriptor combined, ClassDescriptor part) {
|
||||||
|
|
||||||
|
// append comments
|
||||||
|
combined.Comments += part.Comments;
|
||||||
|
|
||||||
|
// union all attributes
|
||||||
|
CommonTree attRoot = (CommonTree)adaptor.Nil;
|
||||||
|
adaptor.AddChild(attRoot, combined.Atts);
|
||||||
|
adaptor.AddChild(attRoot, part.Atts);
|
||||||
|
combined.Atts = (CommonTree)adaptor.RulePostProcessing(attRoot);
|
||||||
|
|
||||||
|
// merge all modifiers
|
||||||
|
combined.Mods = mergeModifiers(combined.Mods, part.Mods);
|
||||||
|
|
||||||
|
// type parameter list must be the same on all parts
|
||||||
|
|
||||||
|
// all parts that have a TypeParameterConstraintsClauses must agree
|
||||||
|
if (combined.TypeParameterConstraintsClauses == null)
|
||||||
|
combined.TypeParameterConstraintsClauses = part.TypeParameterConstraintsClauses;
|
||||||
|
|
||||||
|
// merge all base classes, interfaces
|
||||||
|
combined.ClassBase = mergeModifiers(combined.ClassBase, part.ClassBase);
|
||||||
|
|
||||||
|
// union all class_body
|
||||||
|
CommonTree bodyRoot = (CommonTree)adaptor.Nil;
|
||||||
|
adaptor.AddChild(bodyRoot, combined.ClassBody);
|
||||||
|
adaptor.AddChild(bodyRoot, part.ClassBody);
|
||||||
|
combined.ClassBody = (CommonTree)adaptor.RulePostProcessing(bodyRoot);
|
||||||
|
|
||||||
|
// merge partial sub-types
|
||||||
|
foreach (string key in combined.PartialTypes.Keys) {
|
||||||
|
if (part.PartialTypes.ContainsKey(key)) {
|
||||||
|
mergePartialTypes(combined.PartialTypes[key], part.PartialTypes[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add types in part but not combined
|
||||||
|
foreach (string key in part.PartialTypes.Keys) {
|
||||||
|
if (!combined.PartialTypes.ContainsKey(key)) {
|
||||||
|
combined.PartialTypes[key] = part.PartialTypes[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected CommonTree emitPartialTypes(Dictionary<string,ClassDescriptor> partialTypes) {
|
||||||
|
CommonTree root = (CommonTree)adaptor.Nil;
|
||||||
|
foreach (ClassDescriptor part in partialTypes.Values) {
|
||||||
|
root.AddChild((CommonTree)magicClassFromDescriptor(part.Token, part).Tree);
|
||||||
|
}
|
||||||
|
return (CommonTree)adaptor.RulePostProcessing(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void mergeCompUnits(CUnit cu, List<string> searchPath, List<string> aliasKeys, List<string> aliasNamespaces) {
|
||||||
|
foreach (string s in searchPath) {
|
||||||
|
if (!cu.SearchPath.Contains(s)) {
|
||||||
|
cu.SearchPath.Add(s);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < aliasKeys.Count; i++) {
|
||||||
|
// TODO: ?? Assume alias -> namespace mapping is the same in all files ....
|
||||||
|
if (!cu.NameSpaceAliasKeys.Contains(aliasKeys[i])) {
|
||||||
|
cu.NameSpaceAliasKeys.Add(aliasKeys[i]);
|
||||||
|
cu.NameSpaceAliasValues.Add(aliasNamespaces[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,12 +582,15 @@ scope TypeContext {
|
|||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
public compilation_unit
|
public compilation_unit
|
||||||
scope NSContext;
|
scope NSContext, TypeContext;
|
||||||
@init {
|
@init {
|
||||||
$NSContext::currentNS = "";
|
$NSContext::currentNS = "";
|
||||||
$NSContext::namespaces = new List<string>();
|
$NSContext::namespaces = new List<string>();
|
||||||
$NSContext::aliasKeys = new List<string>();
|
$NSContext::aliasKeys = new List<string>();
|
||||||
$NSContext::aliasNamespaces = new List<string>();
|
$NSContext::aliasNamespaces = new List<string>();
|
||||||
|
|
||||||
|
$TypeContext::typeName = null;
|
||||||
|
$TypeContext::partialTypes = new Dictionary<String,ClassDescriptor>();
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
namespace_body;
|
namespace_body;
|
||||||
@ -523,24 +631,37 @@ using_namespace_directive:
|
|||||||
namespace_member_declarations:
|
namespace_member_declarations:
|
||||||
namespace_member_declaration+ ;
|
namespace_member_declaration+ ;
|
||||||
namespace_member_declaration
|
namespace_member_declaration
|
||||||
|
scope TypeContext;
|
||||||
@init { string ns = $NSContext::currentNS;
|
@init { string ns = $NSContext::currentNS;
|
||||||
bool isCompUnit = false;
|
bool isCompUnit = false;
|
||||||
CommonTree atts = null;
|
CommonTree atts = null;
|
||||||
CommonTree mods = null;
|
CommonTree mods = null;
|
||||||
|
$TypeContext::partialTypes = new Dictionary<string, ClassDescriptor>();
|
||||||
}
|
}
|
||||||
@after {
|
@after {
|
||||||
if (isCompUnit) {
|
if (isCompUnit) {
|
||||||
foreach (KeyValuePair<String, CommonTree> treeEntry in $ty.compUnits) {
|
foreach (KeyValuePair<String, CommonTree> treeEntry in $ty.compUnits) {
|
||||||
if (treeEntry.Value != null) {
|
if (treeEntry.Value != null) {
|
||||||
if (CUKeys.Contains(ns+"."+treeEntry.Key)) {
|
string fqn = ns+(String.IsNullOrEmpty(ns) ? "" : ".")+treeEntry.Key;
|
||||||
{ Warning(treeEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + ns+"."+treeEntry.Key); }
|
if (CUKeys.Contains(fqn)) {
|
||||||
|
Warning(treeEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + fqn);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
CUMap.Add(ns+"."+treeEntry.Key, new CUnit(mkPackage(treeEntry.Value.Token, treeEntry.Value, ns),CollectSearchPath,CollectAliasKeys,CollectAliasNamespaces));
|
CUMap.Add(fqn, new CUnit(mkPackage(treeEntry.Value.Token, treeEntry.Value, ns),CollectSearchPath,CollectAliasKeys,CollectAliasNamespaces));
|
||||||
CUKeys.Add(ns+"."+treeEntry.Key);
|
CUKeys.Add(fqn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
foreach (KeyValuePair<String, ClassDescriptor> partialEntry in $TypeContext::partialTypes) {
|
||||||
|
string fqn = ns+(String.IsNullOrEmpty(ns) ? "" : ".")+partialEntry.Key;
|
||||||
|
if (CUKeys.Contains(fqn)) {
|
||||||
|
Warning(partialEntry.Value.Token.Line, "[UNSUPPORTED] Cannot have a class with multiple generic type overloadings: " + fqn);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
CUMap.Add(fqn, new CUnit(mkPackage(partialEntry.Value.Token, (CommonTree)magicClassFromDescriptor(partialEntry.Value.Token, partialEntry.Value).Tree, ns), CollectSearchPath, CollectAliasKeys, CollectAliasNamespaces, true));
|
||||||
|
CUKeys.Add(fqn);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}:
|
}:
|
||||||
namespace_declaration
|
namespace_declaration
|
||||||
@ -553,12 +674,11 @@ type_declaration[CommonTree atts, CommonTree mods] returns [Dictionary<String,Co
|
|||||||
$compUnits = new Dictionary<String,CommonTree>();
|
$compUnits = new Dictionary<String,CommonTree>();
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
('partial') => p='partial'! { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); }
|
('partial') => p='partial'! (pc=class_declaration[$atts, $mods, true /* toplevel */, true /* isPartial */]
|
||||||
(pc=class_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($pc.name, $pc.tree); }
|
| ps=struct_declaration[$atts, $mods, true /* toplevel */, true /* isPartial */]
|
||||||
| ps=struct_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($ps.name, $ps.tree); }
|
|
||||||
| pi=interface_declaration[$atts, $mods] { $compUnits.Add($pi.name, $pi.tree); } )
|
| pi=interface_declaration[$atts, $mods] { $compUnits.Add($pi.name, $pi.tree); } )
|
||||||
| c=class_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($c.name, $c.tree); }
|
| c=class_declaration[$atts, $mods, true /* toplevel */, false /* isPartial */] { $compUnits.Add($c.name, $c.tree); }
|
||||||
| s=struct_declaration[$atts, $mods, true /* toplevel */] { $compUnits.Add($s.name, $s.tree); }
|
| s=struct_declaration[$atts, $mods, true /* toplevel */, false /* isPartial */] { $compUnits.Add($s.name, $s.tree); }
|
||||||
| i=interface_declaration[$atts, $mods] { $compUnits.Add($i.name, $i.tree); }
|
| i=interface_declaration[$atts, $mods] { $compUnits.Add($i.name, $i.tree); }
|
||||||
| e=enum_declaration[$atts, $mods] { $compUnits.Add($e.name, $e.tree); }
|
| e=enum_declaration[$atts, $mods] { $compUnits.Add($e.name, $e.tree); }
|
||||||
| d=delegate_declaration[$atts, $mods, true /* toplevel */] { $compUnits = $d.compUnits; }
|
| d=delegate_declaration[$atts, $mods, true /* toplevel */] { $compUnits = $d.compUnits; }
|
||||||
@ -578,18 +698,24 @@ modifier:
|
|||||||
'new' -> /* No new in Java*/ | 'public' | 'protected' | 'private' | 'internal' -> /* translate to package-private */| 'unsafe' -> | 'abstract' | 'sealed' -> FINAL["final"] | 'static'
|
'new' -> /* No new in Java*/ | 'public' | 'protected' | 'private' | 'internal' -> /* translate to package-private */| 'unsafe' -> | 'abstract' | 'sealed' -> FINAL["final"] | 'static'
|
||||||
| 'readonly' -> /* no equivalent in C# (this is like a const that can be initialized separately in the constructor) */ | 'volatile' | e='extern' { Warning($e.line, "[UNSUPPORTED] 'extern' modifier"); } | 'virtual' -> | 'override' -> /* not in Java, maybe convert to override annotation */;
|
| 'readonly' -> /* no equivalent in C# (this is like a const that can be initialized separately in the constructor) */ | 'volatile' | e='extern' { Warning($e.line, "[UNSUPPORTED] 'extern' modifier"); } | 'virtual' -> | 'override' -> /* not in Java, maybe convert to override annotation */;
|
||||||
|
|
||||||
class_member_declaration:
|
class_member_declaration
|
||||||
|
@after {
|
||||||
|
this.prevMemberEndTokenIndex = adaptor.GetTokenStopIndex($class_member_declaration.tree);
|
||||||
|
}:
|
||||||
a=attributes?
|
a=attributes?
|
||||||
m=modifiers?
|
m=modifiers?
|
||||||
( c='const' ct=type constant_declarators ';' -> ^(FIELD[$c.token, "FIELD"] $a? $m? { addConstModifiers($c.token, $m.modList) } $ct constant_declarators)
|
( c='const' ct=type constant_declarators ';' -> ^(FIELD[$c.token, "FIELD"] $a? $m? { addConstModifiers($c.token, $m.modList) } $ct constant_declarators)
|
||||||
| ev=event_declaration[$a.tree, $m.tree] -> $ev
|
| ev=event_declaration[$a.tree, $m.tree] -> $ev
|
||||||
| 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
|
| p='partial' (v1=void_type m3=method_declaration[$a.tree, $m.tree, $m.modList, $v1.tree, $v1.text, true /* isPartial */] -> { $m3.tree != null}? $m3
|
||||||
|
->
|
||||||
| pi=interface_declaration[$a.tree, $m.tree] -> $pi
|
| pi=interface_declaration[$a.tree, $m.tree] -> $pi
|
||||||
| pc=class_declaration[$a.tree, $m.tree, false /* toplevel */] -> $pc
|
| pc=class_declaration[$a.tree, $m.tree, false /* toplevel */, true /* isPartial */] -> { $pc.tree != null}? $pc
|
||||||
| ps=struct_declaration[$a.tree, $m.tree, false /* toplevel */] -> $ps)
|
->
|
||||||
|
| ps=struct_declaration[$a.tree, $m.tree, false /* toplevel */, true /* isPartial */] -> { ps.tree != null}? $ps
|
||||||
|
-> )
|
||||||
| i=interface_declaration[$a.tree, $m.tree] -> $i
|
| i=interface_declaration[$a.tree, $m.tree] -> $i
|
||||||
| v2=void_type m1=method_declaration[$a.tree, $m.tree, $m.modList, $v2.tree, $v2.text] -> $m1
|
| v2=void_type m1=method_declaration[$a.tree, $m.tree, $m.modList, $v2.tree, $v2.text, false /* isPartial */] -> $m1
|
||||||
| t=type ( (member_name type_parameter_list? '(') => m2=method_declaration[$a.tree, $m.tree, $m.modList, $t.tree, $t.text] -> $m2
|
| t=type ( (member_name type_parameter_list? '(') => m2=method_declaration[$a.tree, $m.tree, $m.modList, $t.tree, $t.text, false /* isPartial */] -> $m2
|
||||||
| (member_name '{') => pd=property_declaration[$a.tree, $m.tree, $t.tree] -> $pd
|
| (member_name '{') => pd=property_declaration[$a.tree, $m.tree, $t.tree] -> $pd
|
||||||
| (type_name '.' 'this') => tn=type_name '.' ix1=indexer_declaration[$a.tree, $m.tree, $t.tree, $tn.tree] -> $ix1
|
| (type_name '.' 'this') => tn=type_name '.' ix1=indexer_declaration[$a.tree, $m.tree, $t.tree, $tn.tree] -> $ix1
|
||||||
| ix2=indexer_declaration[$a.tree, $m.tree, $t.tree, null] -> $ix2 //this
|
| ix2=indexer_declaration[$a.tree, $m.tree, $t.tree, null] -> $ix2 //this
|
||||||
@ -598,8 +724,8 @@ class_member_declaration:
|
|||||||
)
|
)
|
||||||
// common_modifiers// (method_modifiers | field_modifiers)
|
// common_modifiers// (method_modifiers | field_modifiers)
|
||||||
|
|
||||||
| cd=class_declaration[$a.tree, $m.tree, false /* toplevel */] -> $cd
|
| cd=class_declaration[$a.tree, $m.tree, false /* toplevel */, false /* isPartial */] -> $cd
|
||||||
| sd=struct_declaration[$a.tree, $m.tree, false /* toplevel */] -> $sd
|
| sd=struct_declaration[$a.tree, $m.tree, false /* toplevel */, false /* isPartial */] -> $sd
|
||||||
| ed=enum_declaration[$a.tree, $m.tree] -> $ed
|
| ed=enum_declaration[$a.tree, $m.tree] -> $ed
|
||||||
| dd=delegate_declaration[$a.tree, $m.tree, false /* toplevel */] -> { mkFlattenDictionary($dd.tree.Token,$dd.compUnits) }
|
| dd=delegate_declaration[$a.tree, $m.tree, false /* toplevel */] -> { mkFlattenDictionary($dd.tree.Token,$dd.compUnits) }
|
||||||
| co3=conversion_operator_declaration -> ^(CONVERSION_OPERATOR[$co3.start.Token, "CONVERSION"] $a? $m? $co3)
|
| co3=conversion_operator_declaration -> ^(CONVERSION_OPERATOR[$co3.start.Token, "CONVERSION"] $a? $m? $co3)
|
||||||
@ -923,9 +1049,9 @@ pointer_type:
|
|||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
// Statement Section
|
// Statement Section
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
block:
|
block returns [bool isEmpty]:
|
||||||
';'
|
';' { $isEmpty = true; }
|
||||||
| '{' statement_list? '}';
|
| '{' statement_list? '}' { $isEmpty = false; };
|
||||||
statement_list:
|
statement_list:
|
||||||
statement[/* isStatementListCtxt */ true]+ ;
|
statement[/* isStatementListCtxt */ true]+ ;
|
||||||
|
|
||||||
@ -1132,11 +1258,42 @@ attribute_argument_expression:
|
|||||||
// Class Section
|
// Class Section
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
class_declaration[CommonTree atts, CommonTree mods, bool toplevel] returns [string name]
|
class_declaration[CommonTree atts, CommonTree mods, bool toplevel, bool isPartial] returns [string name]
|
||||||
scope TypeContext;
|
scope TypeContext;
|
||||||
|
@init{
|
||||||
|
$TypeContext::partialTypes = new Dictionary<String,ClassDescriptor>();
|
||||||
|
int prevMemberEndIndex = this.prevMemberEndTokenIndex;
|
||||||
|
IToken endToken = null;
|
||||||
|
}
|
||||||
:
|
:
|
||||||
c='class' identifier { $TypeContext::typeName = $identifier.text; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.text, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body ';'?
|
c='class' identifier { $TypeContext::typeName = $identifier.thetext; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.thetext, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? class_body[$isPartial] { endToken = $class_body.endToken; } (s=';' { endToken = $s.token; })?
|
||||||
-> ^(CLASS[$c.Token] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($c.token, $mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? class_body );
|
{
|
||||||
|
if ($isPartial) {
|
||||||
|
|
||||||
|
// Strip off braces
|
||||||
|
CommonTree newClassBody = dupTree($class_body.tree);
|
||||||
|
int bodyChildren = adaptor.GetChildCount(newClassBody);
|
||||||
|
if (bodyChildren >= 2 && ((CommonTree)adaptor.GetChild(newClassBody, 0)).Type == OPEN_BRACE && ((CommonTree)adaptor.GetChild(newClassBody, bodyChildren - 1)).Type == CLOSE_BRACE) {
|
||||||
|
adaptor.DeleteChild(newClassBody, bodyChildren - 1);
|
||||||
|
adaptor.DeleteChild(newClassBody, 0);
|
||||||
|
newClassBody = (CommonTree)adaptor.RulePostProcessing(newClassBody);
|
||||||
|
}
|
||||||
|
if (!toplevel) {
|
||||||
|
$mods = addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static"));
|
||||||
|
}
|
||||||
|
ClassDescriptor klass = new ClassDescriptor($c.token, snaffleComments(prevMemberEndIndex, $c.token.TokenIndex), $atts, $mods, $identifier.tree, $type_parameter_list.tree, $class_base.tree, $type_parameter_constraints_clauses.tree, newClassBody, $TypeContext::partialTypes);
|
||||||
|
// add to parent's context
|
||||||
|
Dictionary<String,ClassDescriptor> parentPartialTypes = ((TypeContext_scope)$TypeContext.ToArray()[1]).partialTypes;
|
||||||
|
if (parentPartialTypes.ContainsKey($identifier.thetext)) {
|
||||||
|
mergePartialTypes(parentPartialTypes[$identifier.thetext], klass);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parentPartialTypes[$identifier.thetext] = klass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-> {$isPartial}?
|
||||||
|
-> ^(CLASS[$c.Token] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? class_body );
|
||||||
|
|
||||||
type_parameter_list returns [List<string> names]
|
type_parameter_list returns [List<string> names]
|
||||||
@init {
|
@init {
|
||||||
@ -1145,7 +1302,7 @@ type_parameter_list returns [List<string> names]
|
|||||||
'<'! attributes? t1=type_parameter { names.Add($t1.name); } ( ','! attributes? tn=type_parameter { names.Add($tn.name); })* '>'! ;
|
'<'! attributes? t1=type_parameter { names.Add($t1.name); } ( ','! attributes? tn=type_parameter { names.Add($tn.name); })* '>'! ;
|
||||||
|
|
||||||
type_parameter returns [string name]:
|
type_parameter returns [string name]:
|
||||||
identifier { $name = $identifier.text; } ;
|
identifier { $name = $identifier.thetext; } ;
|
||||||
|
|
||||||
class_base:
|
class_base:
|
||||||
// just put all types in a single list. In NetMaker we will extract the base class if necessary
|
// just put all types in a single list. In NetMaker we will extract the base class if necessary
|
||||||
@ -1154,8 +1311,10 @@ class_base:
|
|||||||
//interface_type_list:
|
//interface_type_list:
|
||||||
// ts+=type (',' ts+=type)* -> $ts+;
|
// ts+=type (',' ts+=type)* -> $ts+;
|
||||||
|
|
||||||
class_body:
|
class_body[bool isPartial] returns [IToken endToken]:
|
||||||
'{' class_member_declarations? '}' ;
|
'{' class_member_declarations? e='}' { $endToken = $e.token; }
|
||||||
|
-> {!$isPartial}? '{' class_member_declarations? { emitPartialTypes($TypeContext::partialTypes) } '}'
|
||||||
|
-> '{' class_member_declarations? '}' ;
|
||||||
class_member_declarations:
|
class_member_declarations:
|
||||||
class_member_declaration+ ;
|
class_member_declaration+ ;
|
||||||
|
|
||||||
@ -1178,7 +1337,7 @@ variable_declarator:
|
|||||||
type_name ('=' variable_initializer)? ; // eg. event EventHandler IInterface.VariableName = Foo;
|
type_name ('=' variable_initializer)? ; // eg. event EventHandler IInterface.VariableName = Foo;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
method_declaration [CommonTree atts, CommonTree mods, List<string> modList, CommonTree type, string typeText]
|
method_declaration [CommonTree atts, CommonTree mods, List<string> modList, CommonTree type, string typeText, bool isPartial]
|
||||||
@init {
|
@init {
|
||||||
bool isToString = false;
|
bool isToString = false;
|
||||||
bool isEquals = false;
|
bool isEquals = false;
|
||||||
@ -1247,14 +1406,17 @@ method_declaration [CommonTree atts, CommonTree mods, List<string> modList, Comm
|
|||||||
}
|
}
|
||||||
exceptions = IsJavaish ? $throw_exceptions.tree : $b.exceptionList;
|
exceptions = IsJavaish ? $throw_exceptions.tree : $b.exceptionList;
|
||||||
}
|
}
|
||||||
-> $mainMethod?
|
-> {!($isPartial && $b.isEmpty)}?
|
||||||
|
$mainMethod?
|
||||||
^(METHOD { dupTree($atts) } { dupTree($mods) } { dupTree($type) }
|
^(METHOD { dupTree($atts) } { dupTree($mods) } { dupTree($type) }
|
||||||
magicIdentifier type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? $b { exceptions });
|
magicIdentifier type_parameter_constraints_clauses? type_parameter_list? formal_parameter_list? $b { exceptions })
|
||||||
|
->
|
||||||
|
;
|
||||||
|
|
||||||
method_body [bool smotherExceptions] returns [CommonTree exceptionList]:
|
method_body [bool smotherExceptions] returns [CommonTree exceptionList, bool isEmpty]:
|
||||||
{smotherExceptions}? b=block nb=magicSmotherExceptions[dupTree($b.tree) ]
|
{smotherExceptions}? b=block nb=magicSmotherExceptions[dupTree($b.tree) ]
|
||||||
-> $nb
|
-> $nb
|
||||||
| b=block el=magicThrowsException[true,$b.tree.Token] { $exceptionList=$el.tree; }
|
| b=block el=magicThrowsException[true,$b.tree.Token] { $exceptionList=$el.tree; $isEmpty = $b.isEmpty; }
|
||||||
-> $b
|
-> $b
|
||||||
;
|
;
|
||||||
|
|
||||||
@ -1328,7 +1490,7 @@ remove_accessor_declaration:
|
|||||||
enum_declaration[CommonTree atts, CommonTree mods] returns [string name]
|
enum_declaration[CommonTree atts, CommonTree mods] returns [string name]
|
||||||
scope TypeContext;
|
scope TypeContext;
|
||||||
:
|
:
|
||||||
e='enum' identifier { $name = $identifier.text; $TypeContext::typeName = $identifier.text; } enum_base? enum_body ';'?
|
e='enum' identifier { $name = $identifier.thetext; $TypeContext::typeName = $identifier.thetext; } enum_base? enum_body ';'?
|
||||||
-> ^(ENUM[$e.token, "ENUM"] { dupTree($atts) } { dupTree($mods) } identifier enum_base? enum_body);
|
-> ^(ENUM[$e.token, "ENUM"] { dupTree($atts) } { dupTree($mods) } identifier enum_base? enum_body);
|
||||||
enum_base:
|
enum_base:
|
||||||
':' integral_type ;
|
':' integral_type ;
|
||||||
@ -1404,7 +1566,7 @@ scope TypeContext;
|
|||||||
$compUnits.Add(delName, dupTree($delegate_declaration.tree));
|
$compUnits.Add(delName, dupTree($delegate_declaration.tree));
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
d='delegate' return_type identifier { delName = $identifier.text; $TypeContext::typeName = $identifier.text; } variant_generic_parameter_list? {ifTree = mkType($d.token, $identifier.tree, $variant_generic_parameter_list.tyargs); }
|
d='delegate' return_type identifier { delName = $identifier.thetext; $TypeContext::typeName = $identifier.thetext; } variant_generic_parameter_list? {ifTree = mkType($d.token, $identifier.tree, $variant_generic_parameter_list.tyargs); }
|
||||||
'(' formal_parameter_list? ')' type_parameter_constraints_clauses? ';'
|
'(' formal_parameter_list? ')' type_parameter_constraints_clauses? ';'
|
||||||
magicDelegateInterface[$d.token, $return_type.tree, $identifier.tree, $formal_parameter_list.tree, $variant_generic_parameter_list.tyargs]
|
magicDelegateInterface[$d.token, $return_type.tree, $identifier.tree, $formal_parameter_list.tree, $variant_generic_parameter_list.tyargs]
|
||||||
magicMultiInvokerMethod[$d.token, $return_type.tree, $return_type.thetext == "Void" || $return_type.thetext == "System.Void", ifTree, $formal_parameter_list.tree, mkArgsFromParams($d.token, $formal_parameter_list.tree), $variant_generic_parameter_list.tyargs]
|
magicMultiInvokerMethod[$d.token, $return_type.tree, $return_type.thetext == "Void" || $return_type.thetext == "System.Void", ifTree, $formal_parameter_list.tree, mkArgsFromParams($d.token, $formal_parameter_list.tree), $variant_generic_parameter_list.tyargs]
|
||||||
@ -1415,14 +1577,14 @@ scope TypeContext;
|
|||||||
AddToImports("java.util.ArrayList");
|
AddToImports("java.util.ArrayList");
|
||||||
AddToImports("CS2JNet.JavaSupport.util.ListSupport");
|
AddToImports("CS2JNet.JavaSupport.util.ListSupport");
|
||||||
}
|
}
|
||||||
magicMultiDelClass[$d.token, $atts, toplevel ? dupTree($mods) : addModifier($d.token, $mods, (CommonTree)adaptor.Create(STATIC, $d.token, "static")), multiDelName, ifTree, $type_parameter_constraints_clauses.tree, $variant_generic_parameter_list.tree, $magicMultiInvokerMethod.tree, delClassMemberNodes]
|
magicMultiDelClass[$d.token, $atts, toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $d.token, "static")), multiDelName, ifTree, $type_parameter_constraints_clauses.tree, $variant_generic_parameter_list.tree, $magicMultiInvokerMethod.tree, delClassMemberNodes]
|
||||||
{
|
{
|
||||||
$compUnits.Add(multiDelName, $magicMultiDelClass.tree);
|
$compUnits.Add(multiDelName, $magicMultiDelClass.tree);
|
||||||
}
|
}
|
||||||
->
|
->
|
||||||
// ^(DELEGATE[$d.token, "DELEGATE"] { dupTree($atts) } { dupTree($mods) } return_type identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
|
// ^(DELEGATE[$d.token, "DELEGATE"] { dupTree($atts) } { dupTree($mods) } return_type identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
|
||||||
// '(' formal_parameter_list? ')' );
|
// '(' formal_parameter_list? ')' );
|
||||||
^(INTERFACE[$d.token, "interface"] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($d.token, $mods, (CommonTree)adaptor.Create(STATIC, $d.token, "static")) } identifier { dupTree($type_parameter_constraints_clauses.tree) } { dupTree($variant_generic_parameter_list.tree) } magicDelegateInterface)
|
^(INTERFACE[$d.token, "interface"] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $d.token, "static")) } identifier { dupTree($type_parameter_constraints_clauses.tree) } { dupTree($variant_generic_parameter_list.tree) } magicDelegateInterface)
|
||||||
;
|
;
|
||||||
delegate_modifiers:
|
delegate_modifiers:
|
||||||
modifier+ ;
|
modifier+ ;
|
||||||
@ -1505,7 +1667,7 @@ parameter_array:
|
|||||||
interface_declaration[CommonTree atts, CommonTree mods] returns [string name]
|
interface_declaration[CommonTree atts, CommonTree mods] returns [string name]
|
||||||
scope TypeContext;
|
scope TypeContext;
|
||||||
:
|
:
|
||||||
c='interface' identifier { $name = $identifier.text; $TypeContext::typeName = $identifier.text; } variant_generic_parameter_list?
|
c='interface' identifier { $name = $identifier.thetext; $TypeContext::typeName = $identifier.thetext; } variant_generic_parameter_list?
|
||||||
interface_base? type_parameter_constraints_clauses? interface_body ';'?
|
interface_base? type_parameter_constraints_clauses? interface_body ';'?
|
||||||
-> ^(INTERFACE[$c.Token, "interface"] { dupTree($atts) } { dupTree($mods) } identifier type_parameter_constraints_clauses? variant_generic_parameter_list? interface_base? interface_body );
|
-> ^(INTERFACE[$c.Token, "interface"] { dupTree($atts) } { dupTree($mods) } identifier type_parameter_constraints_clauses? variant_generic_parameter_list? interface_base? interface_body );
|
||||||
|
|
||||||
@ -1551,14 +1713,48 @@ interface_accessor_declaration [CommonTree atts, CommonTree mods, CommonTree typ
|
|||||||
;
|
;
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
struct_declaration[CommonTree atts, CommonTree mods, bool toplevel] returns [string name]
|
struct_declaration[CommonTree atts, CommonTree mods, bool toplevel, bool isPartial] returns [string name]
|
||||||
scope TypeContext;
|
scope TypeContext;
|
||||||
|
@init {
|
||||||
|
$TypeContext::partialTypes = new Dictionary<String,ClassDescriptor>();
|
||||||
|
IToken endToken = null;
|
||||||
|
}
|
||||||
:
|
:
|
||||||
c='struct' identifier { $TypeContext::typeName = $identifier.text; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.text, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? struct_body[$identifier.text] ';'?
|
c='struct' identifier { $TypeContext::typeName = $identifier.thetext; } type_parameter_list? { $name = mkGenericTypeAlias($identifier.thetext, $type_parameter_list.names); } class_base? type_parameter_constraints_clauses? struct_body[$isPartial, $identifier.thetext] { endToken = $struct_body.endToken; } (s=';' { endToken = $s.token; })?
|
||||||
-> ^(CLASS[$c.Token, "class"] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($c.token, $mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? struct_body );
|
{
|
||||||
|
if ($isPartial) {
|
||||||
|
|
||||||
struct_body [string structName]:
|
// Strip off braces
|
||||||
o='{' magicDefaultConstructor[$o.token, structName] class_member_declarations? '}' ;
|
CommonTree newClassBody = dupTree($struct_body.tree);
|
||||||
|
int bodyChildren = adaptor.GetChildCount(newClassBody);
|
||||||
|
if (bodyChildren >= 2 && ((CommonTree)adaptor.GetChild(newClassBody, 0)).Type == OPEN_BRACE && ((CommonTree)adaptor.GetChild(newClassBody, bodyChildren - 1)).Type == CLOSE_BRACE) {
|
||||||
|
adaptor.DeleteChild(newClassBody, bodyChildren - 1);
|
||||||
|
adaptor.DeleteChild(newClassBody, 0);
|
||||||
|
newClassBody = (CommonTree)adaptor.RulePostProcessing(newClassBody);
|
||||||
|
}
|
||||||
|
if (!toplevel) {
|
||||||
|
$mods = addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static"));
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassDescriptor klass = new ClassDescriptor($c.token, snaffleComments(this.prevMemberEndTokenIndex, $c.token.TokenIndex), $atts, $mods, $identifier.tree, $type_parameter_list.tree, $class_base.tree, $type_parameter_constraints_clauses.tree, newClassBody, $TypeContext::partialTypes);
|
||||||
|
|
||||||
|
// add to parent's context
|
||||||
|
Dictionary<String,ClassDescriptor> parentPartialTypes = ((TypeContext_scope)$TypeContext.ToArray()[1]).partialTypes;
|
||||||
|
if (!parentPartialTypes.ContainsKey($identifier.thetext)) {
|
||||||
|
mergePartialTypes(parentPartialTypes[$identifier.thetext], klass);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parentPartialTypes[$identifier.thetext] = klass;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-> {$isPartial}?
|
||||||
|
-> ^(CLASS[$c.Token, "class"] { dupTree($atts) } { toplevel ? dupTree($mods) : addModifier($mods, (CommonTree)adaptor.Create(STATIC, $c.token, "static")) } identifier type_parameter_constraints_clauses? type_parameter_list? class_base? struct_body );
|
||||||
|
|
||||||
|
struct_body [bool isPartial, string structName] returns [IToken endToken]:
|
||||||
|
o='{' magicDefaultConstructor[$o.token, structName] class_member_declarations? e='}' { $endToken = $e.token; }
|
||||||
|
-> {$isPartial}? '{' magicDefaultConstructor class_member_declarations? { emitPartialTypes($TypeContext::partialTypes) } '}'
|
||||||
|
-> '{' magicDefaultConstructor class_member_declarations? '}' ;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
@ -1702,7 +1898,7 @@ local_variable_declarators returns [List<string> variableNames]
|
|||||||
}:
|
}:
|
||||||
i1=local_variable_declarator { $variableNames.Add($i1.variableName); } (',' ip=local_variable_declarator { $variableNames.Add($ip.variableName); })* ;
|
i1=local_variable_declarator { $variableNames.Add($i1.variableName); } (',' ip=local_variable_declarator { $variableNames.Add($ip.variableName); })* ;
|
||||||
local_variable_declarator returns [string variableName]:
|
local_variable_declarator returns [string variableName]:
|
||||||
identifier { $variableName = $identifier.text; } ('=' local_variable_initializer)? ;
|
identifier { $variableName = $identifier.thetext; } ('=' local_variable_initializer)? ;
|
||||||
local_variable_initializer:
|
local_variable_initializer:
|
||||||
expression
|
expression
|
||||||
| array_initializer
|
| array_initializer
|
||||||
@ -1867,10 +2063,11 @@ predefined_type returns [string thetext]
|
|||||||
| 'ushort' { $thetext = "System.UInt16"; }
|
| 'ushort' { $thetext = "System.UInt16"; }
|
||||||
;
|
;
|
||||||
|
|
||||||
identifier
|
identifier returns [string thetext]
|
||||||
@after {
|
@after {
|
||||||
string fixedId = fixBrokenId($identifier.tree.Token.Text);
|
string fixedId = fixBrokenId($identifier.tree.Token.Text);
|
||||||
$identifier.tree.Token.Text = fixedId;
|
$identifier.tree.Token.Text = fixedId;
|
||||||
|
$thetext = $identifier.tree.Token.Text;
|
||||||
}:
|
}:
|
||||||
IDENTIFIER | also_keyword;
|
IDENTIFIER | also_keyword;
|
||||||
|
|
||||||
@ -2155,3 +2352,5 @@ magicMultiDelClass[IToken tok, CommonTree atts, CommonTree mods, string classNam
|
|||||||
OPEN_BRACE[tok, "{"] {dupTree(invokeMethod)} { dupTree(members) } CLOSE_BRACE[tok, "}"])
|
OPEN_BRACE[tok, "{"] {dupTree(invokeMethod)} { dupTree(members) } CLOSE_BRACE[tok, "}"])
|
||||||
;
|
;
|
||||||
|
|
||||||
|
magicClassFromDescriptor[IToken tok, ClassDescriptor klass]:
|
||||||
|
-> ^(CLASS[tok] PAYLOAD[tok, klass.Comments] { dupTree(klass.Atts) } { dupTree(klass.Mods) } { dupTree(klass.Identifier) } { dupTree(klass.TypeParameterConstraintsClauses) } { dupTree(klass.TypeParameterList) } { dupTree(klass.ClassBase) } OPEN_BRACE[tok, "{"] { dupTree(klass.ClassBody) } { emitPartialTypes(klass.PartialTypes) } CLOSE_BRACE[tok, "}"] );
|
||||||
|
@ -25,9 +25,11 @@ options {
|
|||||||
@members
|
@members
|
||||||
{
|
{
|
||||||
|
|
||||||
|
public bool IsPartial { get; set; }
|
||||||
public bool IsLast { get; set; }
|
public bool IsLast { get; set; }
|
||||||
public int EmittedCommentTokenIdx { get; set; }
|
public int EmittedCommentTokenIdx { get; set; }
|
||||||
|
public ClassDescriptorSerialized PartialDescriptor { get; set; }
|
||||||
|
|
||||||
private List<string> collectedComments = null;
|
private List<string> collectedComments = null;
|
||||||
List<string> CollectedComments {
|
List<string> CollectedComments {
|
||||||
get {
|
get {
|
||||||
@ -288,7 +290,9 @@ options {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected string mkString(object s) {
|
||||||
|
return (s == null ? String.Empty : s.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -297,14 +301,30 @@ public compilation_unit
|
|||||||
initPrecedence();
|
initPrecedence();
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
^(PACKAGE nm=PAYLOAD imports? type_declaration { if (IsLast) collectComments(); }) ->
|
^(PACKAGE nm=PAYLOAD imports? type_declaration)
|
||||||
|
|
||||||
|
{
|
||||||
|
if (IsLast) collectComments();
|
||||||
|
if (IsPartial) {
|
||||||
|
// Merge into existing descriptor
|
||||||
|
PartialDescriptor.Package = ($nm.text != null && $nm.text.Length > 0 ? $nm.text : null);
|
||||||
|
if ($imports.importList != null && $imports.importList.Count > 0) {
|
||||||
|
foreach (string m in $imports.importList) {
|
||||||
|
if (!PartialDescriptor.Imports.Contains(m)) {
|
||||||
|
PartialDescriptor.Imports.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
->
|
||||||
package(now = {DateTime.Now}, includeDate = {Cfg.TranslatorAddTimeStamp}, packageName = {($nm.text != null && $nm.text.Length > 0 ? $nm.text : null)},
|
package(now = {DateTime.Now}, includeDate = {Cfg.TranslatorAddTimeStamp}, packageName = {($nm.text != null && $nm.text.Length > 0 ? $nm.text : null)},
|
||||||
imports = {$imports.st},
|
imports = {$imports.st},
|
||||||
type = {$type_declaration.st},
|
type = {$type_declaration.st},
|
||||||
endComments = { CollectedComments });
|
endComments = { CollectedComments });
|
||||||
|
|
||||||
type_declaration:
|
type_declaration:
|
||||||
class_declaration -> { $class_declaration.st }
|
class_declaration[true] -> { $class_declaration.st }
|
||||||
| interface_declaration -> { $interface_declaration.st }
|
| interface_declaration -> { $interface_declaration.st }
|
||||||
| enum_declaration -> { $enum_declaration.st }
|
| enum_declaration -> { $enum_declaration.st }
|
||||||
| annotation_declaration -> { $annotation_declaration.st }
|
| annotation_declaration -> { $annotation_declaration.st }
|
||||||
@ -315,21 +335,36 @@ qualified_identifier:
|
|||||||
namespace_name
|
namespace_name
|
||||||
: namespace_or_type_name ;
|
: namespace_or_type_name ;
|
||||||
|
|
||||||
modifiers:
|
modifiers returns [List<string> modList]
|
||||||
ms+=modifier+ -> modifiers(mods={$ms});
|
|
||||||
modifier
|
|
||||||
@init {
|
@init {
|
||||||
string thetext = null;
|
$modList = new List<string>();
|
||||||
}
|
}:
|
||||||
:
|
(modifier { $modList.Add($modifier.thetext); })+ -> modifiers(mods={$modList});
|
||||||
(m='new' | m='public' | m='protected' | m='private' | m='abstract' | m='sealed' | m='static'
|
|
||||||
| m='readonly' | m='volatile' | m='extern' { thetext = "/* [UNSUPPORTED] 'extern' modifier not supported */"; } | m='virtual' | m='override' | m=FINAL)
|
|
||||||
-> string(payload={ (thetext == null ? $m.text : thetext) });
|
|
||||||
|
|
||||||
imports:
|
modifier returns [string thetext]
|
||||||
imps+=importns+ -> seplist(items = { $imps }, sep= { "\n" });
|
:
|
||||||
importns:
|
(m='new' { $thetext = "new"; }
|
||||||
IMPORT PAYLOAD -> import_template(ns = { $PAYLOAD.text });
|
| m='public' { $thetext = "public"; }
|
||||||
|
| m='protected' { $thetext = "protected"; }
|
||||||
|
| m='private' { $thetext = "private"; }
|
||||||
|
| m='abstract' { $thetext = "abstract"; }
|
||||||
|
| m='sealed' { $thetext = "sealed"; }
|
||||||
|
| m='static' { $thetext = "static"; }
|
||||||
|
| m='readonly' { $thetext = "readonly"; }
|
||||||
|
| m='volatile' { $thetext = "volatile"; }
|
||||||
|
| m='extern' { $thetext = "/* [UNSUPPORTED] 'extern' modifier not supported */"; }
|
||||||
|
| m='virtual' { $thetext = "virtual"; }
|
||||||
|
| m='override' { $thetext = "override"; }
|
||||||
|
| m=FINAL{ $thetext = "final"; })
|
||||||
|
-> string(payload= { $thetext });
|
||||||
|
|
||||||
|
imports returns [List<string> importList]
|
||||||
|
@init {
|
||||||
|
$importList = new List<string>();
|
||||||
|
}:
|
||||||
|
(importns { $importList.Add($importns.thetext); })+ -> import_list(nss = { $importList });
|
||||||
|
importns returns [string thetext]:
|
||||||
|
IMPORT PAYLOAD { $thetext = $PAYLOAD.text; } -> import_template(ns = { $PAYLOAD.text });
|
||||||
|
|
||||||
class_member_declaration returns [List<string> preComments]:
|
class_member_declaration returns [List<string> preComments]:
|
||||||
^(CONST attributes? modifiers? type { $preComments = CollectedComments; } constant_declarators)
|
^(CONST attributes? modifiers? type { $preComments = CollectedComments; } constant_declarators)
|
||||||
@ -338,7 +373,7 @@ class_member_declaration returns [List<string> preComments]:
|
|||||||
{ $preComments = CollectedComments; } method_body exception*)
|
{ $preComments = CollectedComments; } method_body exception*)
|
||||||
-> method(modifiers={$modifiers.st}, type={$type.st}, name={ $member_name.st }, typeparams = { $type_parameter_list.st }, params={ $formal_parameter_list.st }, exceptions = { $exception.st }, bodyIsSemi = { $method_body.isSemi }, body={ $method_body.st })
|
-> method(modifiers={$modifiers.st}, type={$type.st}, name={ $member_name.st }, typeparams = { $type_parameter_list.st }, params={ $formal_parameter_list.st }, exceptions = { $exception.st }, bodyIsSemi = { $method_body.isSemi }, body={ $method_body.st })
|
||||||
| interface_declaration -> { $interface_declaration.st }
|
| interface_declaration -> { $interface_declaration.st }
|
||||||
| class_declaration -> { $class_declaration.st }
|
| class_declaration[false] -> { $class_declaration.st }
|
||||||
| ^(FIELD attributes? modifiers? type { $preComments = CollectedComments; } field_declaration) -> field(modifiers={$modifiers.st}, type={$type.st}, field={$field_declaration.st})
|
| ^(FIELD attributes? modifiers? type { $preComments = CollectedComments; } field_declaration) -> field(modifiers={$modifiers.st}, type={$type.st}, field={$field_declaration.st})
|
||||||
| ^(OPERATOR attributes? modifiers? type { $preComments = CollectedComments; } operator_declaration)
|
| ^(OPERATOR attributes? modifiers? type { $preComments = CollectedComments; } operator_declaration)
|
||||||
| enum_declaration -> { $enum_declaration.st }
|
| enum_declaration -> { $enum_declaration.st }
|
||||||
@ -884,9 +919,9 @@ global_attribute_target_specifier:
|
|||||||
global_attribute_target:
|
global_attribute_target:
|
||||||
'assembly' | 'module' ;
|
'assembly' | 'module' ;
|
||||||
attributes:
|
attributes:
|
||||||
attribute_sections ;
|
attribute_sections -> { $attribute_sections.st } ;
|
||||||
attribute_sections:
|
attribute_sections:
|
||||||
attribute_section+ ;
|
ass+=attribute_section+ ;
|
||||||
attribute_section:
|
attribute_section:
|
||||||
^(ATTRIBUTE attribute_target_specifier? attribute_list) ;
|
^(ATTRIBUTE attribute_target_specifier? attribute_list) ;
|
||||||
attribute_target_specifier:
|
attribute_target_specifier:
|
||||||
@ -919,13 +954,58 @@ attribute_argument_expression:
|
|||||||
// Class Section
|
// Class Section
|
||||||
///////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////
|
||||||
|
|
||||||
class_declaration
|
class_declaration[bool topLevel]
|
||||||
@init {
|
@init {
|
||||||
List<string> preComments = null;
|
List<string> preComments = null;
|
||||||
}:
|
}:
|
||||||
^(c=CLASS
|
^(c=CLASS PAYLOAD?
|
||||||
attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list[$type_parameter_constraints_clauses.tpConstraints]?
|
||||||
class_extends? class_implements? { preComments = CollectedComments; } class_body )
|
class_extends? class_implements? { preComments = CollectedComments; preComments.Add($PAYLOAD.text); } class_body )
|
||||||
|
{
|
||||||
|
if (IsPartial && topLevel) {
|
||||||
|
// Merge into existing descriptor
|
||||||
|
if (preComments != null) {
|
||||||
|
foreach (String comment in preComments) {
|
||||||
|
PartialDescriptor.Comments += comment ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Union all attributes
|
||||||
|
// we don't push through attributes yet
|
||||||
|
PartialDescriptor.Atts += mkString($attributes.st);
|
||||||
|
|
||||||
|
// Merge modifiers
|
||||||
|
if ($modifiers.modList != null && $modifiers.modList.Count > 0) {
|
||||||
|
foreach (string m in $modifiers.modList) {
|
||||||
|
if (!PartialDescriptor.Mods.Contains(m)) {
|
||||||
|
PartialDescriptor.Mods.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(PartialDescriptor.TypeParameterList)) {
|
||||||
|
PartialDescriptor.TypeParameterList = mkString($type_parameter_list.st);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(PartialDescriptor.TypeParameterConstraintsClauses)) {
|
||||||
|
PartialDescriptor.TypeParameterConstraintsClauses = mkString($type_parameter_constraints_clauses.st);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($class_implements.implementList != null && $class_implements.implementList.Count > 0) {
|
||||||
|
foreach (string m in $class_implements.implementList) {
|
||||||
|
if (!PartialDescriptor.ClassImplements.Contains(m)) {
|
||||||
|
PartialDescriptor.ClassImplements.Add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (String.IsNullOrEmpty(PartialDescriptor.ClassBase)) {
|
||||||
|
PartialDescriptor.ClassBase = mkString($class_extends.st);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Union the class bodies
|
||||||
|
PartialDescriptor.ClassBody += mkString($class_body.st);
|
||||||
|
}
|
||||||
|
}
|
||||||
-> class(modifiers = { $modifiers.st }, name={ $identifier.st }, typeparams= {$type_parameter_list.st}, comments = { preComments },
|
-> class(modifiers = { $modifiers.st }, name={ $identifier.st }, typeparams= {$type_parameter_list.st}, comments = { preComments },
|
||||||
extends = { $class_extends.st }, imps = { $class_implements.st }, body={$class_body.st}) ;
|
extends = { $class_extends.st }, imps = { $class_implements.st }, body={$class_body.st}) ;
|
||||||
|
|
||||||
@ -942,10 +1022,13 @@ class_extends:
|
|||||||
ts+=class_extend+ -> extends(types = { $ts }) ;
|
ts+=class_extend+ -> extends(types = { $ts }) ;
|
||||||
class_extend:
|
class_extend:
|
||||||
^(EXTENDS ts=type) -> { $ts.st } ;
|
^(EXTENDS ts=type) -> { $ts.st } ;
|
||||||
class_implements:
|
class_implements returns [List<String> implementList]
|
||||||
ts+=class_implement+ -> imps(types = { $ts }) ;
|
@init {
|
||||||
class_implement:
|
$implementList = new List<String>();
|
||||||
^(IMPLEMENTS ts=type) -> { $ts.st };
|
}:
|
||||||
|
(class_implement {$implementList.Add($class_implement.st.ToString()); })+ -> imps(types = { $implementList }) ;
|
||||||
|
class_implement returns [string implement]:
|
||||||
|
^(IMPLEMENTS ts=type) { $implement = $ts.st.ToString(); } -> { $ts.st };
|
||||||
|
|
||||||
interface_type_list:
|
interface_type_list:
|
||||||
ts+=type (',' ts+=type)* -> commalist(items={ $ts });
|
ts+=type (',' ts+=type)* -> commalist(items={ $ts });
|
||||||
|
@ -2212,7 +2212,7 @@ scope NSContext,SymTab;
|
|||||||
$SymTab::symtab = new Dictionary<string, TypeRepTemplate>();
|
$SymTab::symtab = new Dictionary<string, TypeRepTemplate>();
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
^(c=CLASS attributes? modifiers? identifier type_parameter_constraints_clauses?
|
^(c=CLASS PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses?
|
||||||
type_parameter_list?
|
type_parameter_list?
|
||||||
{ $NSContext::currentNS = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.thetext, $type_parameter_list.tyParams); if (CompUnitName == null) CompUnitName = $NSContext::currentNS; }
|
{ $NSContext::currentNS = NSPrefix(ParentNameSpace) + mkGenericTypeAlias($identifier.thetext, $type_parameter_list.tyParams); if (CompUnitName == null) CompUnitName = $NSContext::currentNS; }
|
||||||
class_implements?
|
class_implements?
|
||||||
@ -2251,7 +2251,7 @@ scope NSContext,SymTab;
|
|||||||
}
|
}
|
||||||
class_body magicAnnotation[$modifiers.tree, $identifier.tree, null, $c.token])
|
class_body magicAnnotation[$modifiers.tree, $identifier.tree, null, $c.token])
|
||||||
-> {$class_implements.hasExtends && $class_implements.extendDotNetType.IsA(AppEnv.Search("System.Attribute", new UnknownRepTemplate("System.Attribute")), AppEnv)}? magicAnnotation
|
-> {$class_implements.hasExtends && $class_implements.extendDotNetType.IsA(AppEnv.Search("System.Attribute", new UnknownRepTemplate("System.Attribute")), AppEnv)}? magicAnnotation
|
||||||
-> ^($c attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list? class_implements? class_body);
|
-> ^($c PAYLOAD? attributes? modifiers? identifier type_parameter_constraints_clauses? type_parameter_list? class_implements? class_body);
|
||||||
|
|
||||||
type_parameter_list returns [List<string> tyParams]
|
type_parameter_list returns [List<string> tyParams]
|
||||||
@init {
|
@init {
|
||||||
@ -2265,20 +2265,27 @@ type_parameter returns [string thetext]:
|
|||||||
class_extends:
|
class_extends:
|
||||||
class_extend+ ;
|
class_extend+ ;
|
||||||
class_extend:
|
class_extend:
|
||||||
^(EXTENDS type) ;
|
^(EXTENDS type);
|
||||||
|
|
||||||
// If first implements type is a class then convert to extends
|
// If first implements type is a class then convert to extends
|
||||||
class_implements returns [bool hasExtends, TypeRepTemplate extendDotNetType]:
|
class_implements returns [bool hasExtends, TypeRepTemplate extendDotNetType]
|
||||||
class_implement_or_extend { $hasExtends = $class_implement_or_extend.hasExtends; $extendDotNetType = $class_implement_or_extend.extendDotNetType; }
|
|
||||||
class_implement* ;
|
|
||||||
|
|
||||||
class_implement_or_extend returns [bool hasExtends, TypeRepTemplate extendDotNetType]
|
|
||||||
@init {
|
@init {
|
||||||
$hasExtends = false;
|
CommonTree extends = null;
|
||||||
}:
|
}:
|
||||||
^(i=IMPLEMENTS t=type
|
(class_implement_or_extend[extends == null] { if ($class_implement_or_extend.extends != null) {
|
||||||
{ if ($t.dotNetType is ClassRepTemplate) {
|
extends = $class_implement_or_extend.extends;
|
||||||
$hasExtends = true;
|
$hasExtends = true;
|
||||||
|
$extendDotNetType = $class_implement_or_extend.extendDotNetType;
|
||||||
|
}})+
|
||||||
|
-> { extends } class_implement_or_extend*;
|
||||||
|
|
||||||
|
class_implement_or_extend[bool lookingForBase] returns [CommonTree extends, TypeRepTemplate extendDotNetType]
|
||||||
|
@init {
|
||||||
|
$extends = null;
|
||||||
|
}:
|
||||||
|
^(i=IMPLEMENTS t=type magicExtends[$lookingForBase && $t.dotNetType is ClassRepTemplate, $i.token, $t.tree]
|
||||||
|
{ if ($lookingForBase && $t.dotNetType is ClassRepTemplate) {
|
||||||
|
$extends = $magicExtends.tree;
|
||||||
$extendDotNetType = $t.dotNetType;
|
$extendDotNetType = $t.dotNetType;
|
||||||
}
|
}
|
||||||
if($t.dotNetType.IsA(ICollectionType,AppEnv)) $NSContext::IsICollection = true;
|
if($t.dotNetType.IsA(ICollectionType,AppEnv)) $NSContext::IsICollection = true;
|
||||||
@ -2287,19 +2294,9 @@ class_implement_or_extend returns [bool hasExtends, TypeRepTemplate extendDotNet
|
|||||||
$NSContext::GenericICollectionTyVar = $t.dotNetType.TypeParams[0];
|
$NSContext::GenericICollectionTyVar = $t.dotNetType.TypeParams[0];
|
||||||
}
|
}
|
||||||
} )
|
} )
|
||||||
-> { $t.dotNetType is ClassRepTemplate }? ^(EXTENDS[$i.token, "extends"] type)
|
-> { $lookingForBase && $t.dotNetType is ClassRepTemplate }?
|
||||||
-> ^($i $t);
|
-> ^($i $t);
|
||||||
|
|
||||||
class_implement:
|
|
||||||
^(IMPLEMENTS t=type
|
|
||||||
{
|
|
||||||
if($t.dotNetType.IsA(ICollectionType,AppEnv)) $NSContext::IsICollection = true;
|
|
||||||
if($t.dotNetType.IsA(GenericICollectionType,AppEnv) && $t.dotNetType.TypeParams.Length > 0) {
|
|
||||||
$NSContext::IsGenericICollection = true;
|
|
||||||
$NSContext::GenericICollectionTyVar = $t.dotNetType.TypeParams[0];
|
|
||||||
}
|
|
||||||
}) ;
|
|
||||||
|
|
||||||
class_body
|
class_body
|
||||||
@init {
|
@init {
|
||||||
CommonTree collectorNodes = null;
|
CommonTree collectorNodes = null;
|
||||||
@ -3295,3 +3292,8 @@ magicTypeFromTemplate[bool isOn, IToken tok, TypeRepTemplate dotNetType]:
|
|||||||
-> { $isOn }? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, $dotNetType.mkFormattedTypeName(false, "<",">")])
|
-> { $isOn }? ^(TYPE[tok, "TYPE"] IDENTIFIER[tok, $dotNetType.mkFormattedTypeName(false, "<",">")])
|
||||||
->
|
->
|
||||||
;
|
;
|
||||||
|
|
||||||
|
magicExtends[bool isOn, IToken tok, CommonTree type]:
|
||||||
|
-> { $isOn }? ^(EXTENDS[tok, "extends"] { dupTree($type) })
|
||||||
|
->
|
||||||
|
;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user