2010-11-18 14:23:17 +01:00
|
|
|
// JavaMaker.g
|
2010-11-07 21:57:24 +01:00
|
|
|
//
|
|
|
|
// Convert C# parse tree to a Java parse tree
|
|
|
|
//
|
|
|
|
// Kevin Glynn
|
|
|
|
// kevin.glynn@twigletsoftware.com
|
|
|
|
// November 2010
|
|
|
|
tree grammar JavaMaker;
|
|
|
|
|
|
|
|
options {
|
|
|
|
tokenVocab=cs;
|
|
|
|
ASTLabelType=CommonTree;
|
|
|
|
language=CSharp2;
|
|
|
|
superClass='RusticiSoftware.Translator.CSharp.CommonWalker';
|
|
|
|
output=AST;
|
|
|
|
}
|
|
|
|
|
2010-11-10 19:03:09 +01:00
|
|
|
// A scope to keep track of the namespaces available at any point in the program
|
|
|
|
scope NSContext {
|
|
|
|
int filler;
|
|
|
|
string currentNS;
|
|
|
|
}
|
|
|
|
|
2010-11-07 21:57:24 +01:00
|
|
|
@namespace { RusticiSoftware.Translator.CSharp }
|
|
|
|
|
|
|
|
@header
|
|
|
|
{
|
2010-11-16 16:01:56 +01:00
|
|
|
using System.Globalization;
|
2010-11-07 21:57:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@members
|
|
|
|
{
|
2010-11-15 11:47:32 +01:00
|
|
|
// 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
|
|
|
|
// We also build a lit 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)
|
|
|
|
public IDictionary<string, CommonTree> CUMap { get; set; }
|
|
|
|
public IList<string> CUKeys { get; set; }
|
2010-11-07 21:57:24 +01:00
|
|
|
|
2010-11-10 19:03:09 +01:00
|
|
|
protected string ParentNameSpace {
|
|
|
|
get {
|
|
|
|
return ((NSContext_scope)$NSContext.ToArray()[$NSContext.Count-2]).currentNS;
|
|
|
|
}
|
|
|
|
}
|
2010-11-16 17:29:08 +01:00
|
|
|
|
|
|
|
|
|
|
|
// TREE CONSTRUCTION
|
|
|
|
protected CommonTree mkPayloadList(List<string> payloads) {
|
|
|
|
CommonTree root = (CommonTree)adaptor.Nil;
|
|
|
|
|
|
|
|
foreach (string p in payloads) {
|
|
|
|
adaptor.AddChild(root, (CommonTree)adaptor.Create(PAYLOAD, p));
|
|
|
|
}
|
|
|
|
return root;
|
|
|
|
}
|
2010-11-18 14:23:17 +01:00
|
|
|
|
|
|
|
protected CommonTree mangleModifiersForType(CommonTree modifiers) {
|
|
|
|
if (modifiers == null || modifiers.Children == null)
|
|
|
|
return modifiers;
|
|
|
|
CommonTree stripped = (CommonTree)modifiers.DupNode();
|
|
|
|
for (int i = 0; i < modifiers.Children.Count; i++) {
|
|
|
|
if (((CommonTree)modifiers.Children[i]).Token.Text != "static") {
|
|
|
|
adaptor.AddChild(stripped, modifiers.Children[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return stripped;
|
|
|
|
}
|
2010-11-24 07:42:25 +01:00
|
|
|
|
|
|
|
// TODO: Read reserved words from a file so that they can be extended by customer
|
|
|
|
private readonly static string[] javaReserved = new string[] { "int", "protected", "package" };
|
|
|
|
|
|
|
|
protected string fixBrokenId(string id)
|
|
|
|
{
|
|
|
|
// Console.WriteLine(id);
|
|
|
|
foreach (string k in javaReserved)
|
|
|
|
{
|
|
|
|
if (k == id)
|
|
|
|
{
|
|
|
|
return "__" + id;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return id;
|
|
|
|
}
|
2010-11-07 21:57:24 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
/********************************************************************************************
|
|
|
|
Parser section
|
|
|
|
*********************************************************************************************/
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
2010-11-15 11:47:32 +01:00
|
|
|
compilation_unit
|
2010-11-10 19:03:09 +01:00
|
|
|
scope NSContext;
|
2010-11-07 21:57:24 +01:00
|
|
|
@init {
|
2010-11-10 19:03:09 +01:00
|
|
|
$NSContext::currentNS = "";
|
2010-11-07 21:57:24 +01:00
|
|
|
}
|
|
|
|
:
|
|
|
|
namespace_body;
|
|
|
|
|
2010-11-10 19:03:09 +01:00
|
|
|
namespace_declaration
|
|
|
|
scope NSContext;
|
|
|
|
:
|
|
|
|
'namespace' qi=qualified_identifier
|
|
|
|
{
|
|
|
|
// extend parent namespace
|
|
|
|
$NSContext::currentNS = this.ParentNameSpace + $qi.thetext;
|
|
|
|
}
|
|
|
|
namespace_block ';'? ;
|
2010-11-07 21:57:24 +01:00
|
|
|
namespace_block:
|
|
|
|
'{' namespace_body '}' ;
|
|
|
|
namespace_body:
|
|
|
|
extern_alias_directives? using_directives? global_attributes? namespace_member_declarations? ;
|
|
|
|
extern_alias_directives:
|
|
|
|
extern_alias_directive+ ;
|
|
|
|
extern_alias_directive:
|
2010-11-10 19:03:09 +01:00
|
|
|
e='extern' 'alias' i=identifier ';' { Warning($e.line, "[UNSUPPORTED] External Alias " + $i.text); } ;
|
2010-11-07 21:57:24 +01:00
|
|
|
using_directives:
|
|
|
|
using_directive+ ;
|
|
|
|
using_directive:
|
|
|
|
(using_alias_directive
|
|
|
|
| using_namespace_directive) ;
|
|
|
|
using_alias_directive:
|
|
|
|
'using' identifier '=' namespace_or_type_name ';' ;
|
|
|
|
using_namespace_directive:
|
|
|
|
'using' namespace_name ';' ;
|
|
|
|
namespace_member_declarations:
|
|
|
|
namespace_member_declaration+ ;
|
2010-11-16 13:51:43 +01:00
|
|
|
namespace_member_declaration
|
|
|
|
@init { string ns = $NSContext::currentNS;
|
|
|
|
bool isCompUnit = false;}
|
2010-11-13 19:11:47 +01:00
|
|
|
@after {
|
2010-11-16 13:51:43 +01:00
|
|
|
if (isCompUnit) {
|
|
|
|
CUMap.Add(ns+"."+$ty.name, $namespace_member_declaration.tree);
|
|
|
|
CUKeys.Add(ns+"."+$ty.name);
|
|
|
|
};
|
2010-11-13 19:11:47 +01:00
|
|
|
}
|
|
|
|
:
|
2010-11-16 13:51:43 +01:00
|
|
|
namespace_declaration
|
2010-11-24 07:50:39 +01:00
|
|
|
| attributes? modifiers? ty=type_declaration { isCompUnit = true; } -> ^(PACKAGE[$ty.start.Token, "package"] PAYLOAD[ns] { mangleModifiersForType($modifiers.tree) } type_declaration);
|
2010-11-16 13:51:43 +01:00
|
|
|
// type_declaration is only called at the top level, so each of the types declared
|
|
|
|
// here will become a Java compilation unit (and go to its own file)
|
2010-11-13 19:11:47 +01:00
|
|
|
type_declaration returns [string name]
|
2010-11-07 21:57:24 +01:00
|
|
|
:
|
2010-11-13 19:11:47 +01:00
|
|
|
('partial') => p='partial'! { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); }
|
|
|
|
(pc=class_declaration { $name=$pc.name; }
|
|
|
|
| ps=struct_declaration { $name=$ps.name; }
|
|
|
|
| pi=interface_declaration { $name=$pi.name; })
|
|
|
|
| c=class_declaration { $name=$c.name; }
|
|
|
|
| s=struct_declaration { $name=$s.name; }
|
|
|
|
| i=interface_declaration { $name=$i.name; }
|
|
|
|
| e=enum_declaration { $name=$e.name; }
|
|
|
|
| d=delegate_declaration { $name=$d.name; }
|
|
|
|
;
|
2010-11-07 21:57:24 +01:00
|
|
|
// Identifiers
|
2010-11-10 19:03:09 +01:00
|
|
|
qualified_identifier returns [string thetext]:
|
|
|
|
i1=identifier { $thetext = $i1.text; } ('.' ip=identifier { $thetext += "." + $ip.text; } )*;
|
2010-11-07 21:57:24 +01:00
|
|
|
namespace_name
|
|
|
|
: namespace_or_type_name ;
|
|
|
|
|
|
|
|
modifiers:
|
|
|
|
modifier+ ;
|
|
|
|
modifier:
|
2010-11-16 13:51:43 +01:00
|
|
|
'new' | 'public' | 'protected' | 'private' | 'internal' -> /* translate to package-private */| 'unsafe' -> | 'abstract' | 'sealed' -> FINAL["final"] | 'static'
|
|
|
|
| 'readonly' -> FINAL["final"] | 'volatile' | 'extern' | 'virtual' | 'override';
|
2010-11-18 14:23:17 +01:00
|
|
|
|
2010-11-07 21:57:24 +01:00
|
|
|
class_member_declaration:
|
|
|
|
attributes?
|
|
|
|
m=modifiers?
|
|
|
|
( 'const' type constant_declarators ';'
|
|
|
|
| event_declaration // 'event'
|
2010-11-10 19:03:09 +01:00
|
|
|
| p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (method_declaration
|
2010-11-07 21:57:24 +01:00
|
|
|
| interface_declaration
|
|
|
|
| class_declaration
|
|
|
|
| struct_declaration)
|
|
|
|
| interface_declaration // 'interface'
|
|
|
|
| 'void' method_declaration
|
|
|
|
| type ( (member_name '(') => method_declaration
|
|
|
|
| (member_name '{') => property_declaration
|
|
|
|
| (member_name '.' 'this') => type_name '.' indexer_declaration
|
|
|
|
| indexer_declaration //this
|
|
|
|
| field_declaration // qid
|
|
|
|
| operator_declaration
|
|
|
|
)
|
|
|
|
// common_modifiers// (method_modifiers | field_modifiers)
|
|
|
|
|
|
|
|
| class_declaration // 'class'
|
|
|
|
| struct_declaration // 'struct'
|
|
|
|
| enum_declaration // 'enum'
|
|
|
|
| delegate_declaration // 'delegate'
|
|
|
|
| conversion_operator_declaration
|
|
|
|
| constructor_declaration // | static_constructor_declaration
|
|
|
|
| destructor_declaration
|
|
|
|
)
|
|
|
|
;
|
|
|
|
|
|
|
|
primary_expression:
|
|
|
|
('this' brackets) => 'this' brackets primary_expression_part*
|
|
|
|
| ('base' brackets) => 'this' brackets primary_expression_part*
|
|
|
|
| primary_expression_start primary_expression_part*
|
|
|
|
| 'new' ( (object_creation_expression ('.'|'->'|'[')) =>
|
|
|
|
object_creation_expression primary_expression_part+ // new Foo(arg, arg).Member
|
|
|
|
// try the simple one first, this has no argS and no expressions
|
|
|
|
// symantically could be object creation
|
|
|
|
| (delegate_creation_expression) => delegate_creation_expression// new FooDelegate (MyFunction)
|
|
|
|
| object_creation_expression
|
|
|
|
| anonymous_object_creation_expression) // new {int X, string Y}
|
|
|
|
| sizeof_expression // sizeof (struct)
|
|
|
|
| checked_expression // checked (...
|
|
|
|
| unchecked_expression // unchecked {...}
|
|
|
|
| default_value_expression // default
|
|
|
|
| anonymous_method_expression // delegate (int foo) {}
|
|
|
|
;
|
|
|
|
|
|
|
|
primary_expression_start:
|
|
|
|
predefined_type
|
|
|
|
| (identifier generic_argument_list) => identifier generic_argument_list
|
|
|
|
| identifier ('::' identifier)?
|
|
|
|
| 'this'
|
|
|
|
| 'base'
|
|
|
|
| paren_expression
|
|
|
|
| typeof_expression // typeof(Foo).Name
|
|
|
|
| literal
|
|
|
|
;
|
|
|
|
|
|
|
|
primary_expression_part:
|
|
|
|
access_identifier
|
|
|
|
| brackets_or_arguments
|
|
|
|
| '++'
|
|
|
|
| '--' ;
|
|
|
|
access_identifier:
|
|
|
|
access_operator type_or_generic ;
|
|
|
|
access_operator:
|
|
|
|
'.' | '->' ;
|
|
|
|
brackets_or_arguments:
|
|
|
|
brackets | arguments ;
|
|
|
|
brackets:
|
|
|
|
'[' expression_list? ']' ;
|
|
|
|
paren_expression:
|
|
|
|
'(' expression ')' ;
|
|
|
|
arguments:
|
|
|
|
'(' argument_list? ')' ;
|
|
|
|
argument_list:
|
|
|
|
argument (',' argument)*;
|
|
|
|
// 4.0
|
|
|
|
argument:
|
|
|
|
argument_name argument_value
|
|
|
|
| argument_value;
|
|
|
|
argument_name:
|
|
|
|
identifier ':';
|
|
|
|
argument_value:
|
|
|
|
expression
|
|
|
|
| ref_variable_reference
|
|
|
|
| 'out' variable_reference ;
|
|
|
|
ref_variable_reference:
|
|
|
|
'ref'
|
|
|
|
(('(' type ')') => '(' type ')' (ref_variable_reference | variable_reference) // SomeFunc(ref (int) ref foo)
|
|
|
|
// SomeFunc(ref (int) foo)
|
|
|
|
| variable_reference); // SomeFunc(ref foo)
|
|
|
|
// lvalue
|
|
|
|
variable_reference:
|
|
|
|
expression;
|
|
|
|
rank_specifiers:
|
|
|
|
rank_specifier+ ;
|
2010-11-20 15:28:25 +01:00
|
|
|
// convert dimension separators into additional dimensions, so [,,] -> [] [] []
|
2010-11-07 21:57:24 +01:00
|
|
|
rank_specifier:
|
2010-11-20 15:28:25 +01:00
|
|
|
o='[' dim_separators? c=']' -> $o $c dim_separators?;
|
|
|
|
dim_separators
|
|
|
|
@init {
|
|
|
|
CommonTree ret = (CommonTree)adaptor.Nil;
|
|
|
|
}
|
|
|
|
@after {
|
|
|
|
$dim_separators.tree = ret;
|
|
|
|
}:
|
|
|
|
(c=',' { adaptor.AddChild(ret, adaptor.Create(OPEN_BRACKET, $c.token, "["));adaptor.AddChild(ret, adaptor.Create(CLOSE_BRACKET, $c.token, "]")); })+ -> ;
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
delegate_creation_expression:
|
|
|
|
// 'new'
|
|
|
|
type_name '(' type_name ')' ;
|
|
|
|
anonymous_object_creation_expression:
|
|
|
|
// 'new'
|
|
|
|
anonymous_object_initializer ;
|
|
|
|
anonymous_object_initializer:
|
|
|
|
'{' (member_declarator_list ','?)? '}';
|
|
|
|
member_declarator_list:
|
|
|
|
member_declarator (',' member_declarator)* ;
|
|
|
|
member_declarator:
|
|
|
|
qid ('=' expression)? ;
|
|
|
|
primary_or_array_creation_expression:
|
|
|
|
(array_creation_expression) => array_creation_expression
|
|
|
|
| primary_expression
|
|
|
|
;
|
|
|
|
// new Type[2] { }
|
|
|
|
array_creation_expression:
|
|
|
|
'new'
|
|
|
|
(type ('[' expression_list ']'
|
|
|
|
( rank_specifiers? array_initializer? // new int[4]
|
|
|
|
// | invocation_part*
|
|
|
|
| ( ((arguments ('['|'.'|'->')) => arguments invocation_part)// new object[2].GetEnumerator()
|
|
|
|
| invocation_part)* arguments
|
|
|
|
) // new int[4]()
|
|
|
|
| array_initializer
|
|
|
|
)
|
|
|
|
| rank_specifier // [,]
|
|
|
|
(array_initializer // var a = new[] { 1, 10, 100, 1000 }; // int[]
|
|
|
|
)
|
|
|
|
) ;
|
|
|
|
array_initializer:
|
|
|
|
'{' variable_initializer_list? ','? '}' ;
|
|
|
|
variable_initializer_list:
|
|
|
|
variable_initializer (',' variable_initializer)* ;
|
|
|
|
variable_initializer:
|
|
|
|
expression | array_initializer ;
|
|
|
|
sizeof_expression:
|
|
|
|
'sizeof' '(' unmanaged_type ')';
|
|
|
|
checked_expression:
|
|
|
|
'checked' '(' expression ')' ;
|
|
|
|
unchecked_expression:
|
|
|
|
'unchecked' '(' expression ')' ;
|
|
|
|
default_value_expression:
|
|
|
|
'default' '(' type ')' ;
|
|
|
|
anonymous_method_expression:
|
|
|
|
'delegate' explicit_anonymous_function_signature? block;
|
|
|
|
explicit_anonymous_function_signature:
|
|
|
|
'(' explicit_anonymous_function_parameter_list? ')' ;
|
|
|
|
explicit_anonymous_function_parameter_list:
|
|
|
|
explicit_anonymous_function_parameter (',' explicit_anonymous_function_parameter)* ;
|
|
|
|
explicit_anonymous_function_parameter:
|
|
|
|
anonymous_function_parameter_modifier? type identifier;
|
|
|
|
anonymous_function_parameter_modifier:
|
|
|
|
'ref' | 'out';
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
object_creation_expression:
|
|
|
|
// 'new'
|
|
|
|
type
|
|
|
|
( '(' argument_list? ')' object_or_collection_initializer?
|
|
|
|
| object_or_collection_initializer )
|
|
|
|
;
|
|
|
|
object_or_collection_initializer:
|
|
|
|
'{' (object_initializer
|
|
|
|
| collection_initializer) ;
|
|
|
|
collection_initializer:
|
|
|
|
element_initializer_list ','? '}' ;
|
|
|
|
element_initializer_list:
|
|
|
|
element_initializer (',' element_initializer)* ;
|
|
|
|
element_initializer:
|
|
|
|
non_assignment_expression
|
|
|
|
| '{' expression_list '}' ;
|
|
|
|
// object-initializer eg's
|
|
|
|
// Rectangle r = new Rectangle {
|
|
|
|
// P1 = new Point { X = 0, Y = 1 },
|
|
|
|
// P2 = new Point { X = 2, Y = 3 }
|
|
|
|
// };
|
|
|
|
// TODO: comma should only follow a member_initializer_list
|
|
|
|
object_initializer:
|
|
|
|
member_initializer_list? ','? '}' ;
|
|
|
|
member_initializer_list:
|
|
|
|
member_initializer (',' member_initializer) ;
|
|
|
|
member_initializer:
|
|
|
|
identifier '=' initializer_value ;
|
|
|
|
initializer_value:
|
|
|
|
expression
|
|
|
|
| object_or_collection_initializer ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
typeof_expression:
|
|
|
|
'typeof' '(' ((unbound_type_name) => unbound_type_name
|
|
|
|
| type
|
|
|
|
| 'void') ')' ;
|
|
|
|
// unbound type examples
|
|
|
|
//foo<bar<X<>>>
|
|
|
|
//bar::foo<>
|
|
|
|
//foo1::foo2.foo3<,,>
|
|
|
|
unbound_type_name: // qualified_identifier v2
|
|
|
|
// unbound_type_name_start unbound_type_name_part* ;
|
|
|
|
unbound_type_name_start
|
|
|
|
(((generic_dimension_specifier '.') => generic_dimension_specifier unbound_type_name_part)
|
|
|
|
| unbound_type_name_part)*
|
|
|
|
generic_dimension_specifier
|
|
|
|
;
|
|
|
|
|
|
|
|
unbound_type_name_start:
|
|
|
|
identifier ('::' identifier)?;
|
|
|
|
unbound_type_name_part:
|
|
|
|
'.' identifier;
|
|
|
|
generic_dimension_specifier:
|
|
|
|
'<' commas? '>' ;
|
|
|
|
commas:
|
|
|
|
','+ ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Type Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
type_name returns [string thetext]:
|
|
|
|
namespace_or_type_name { $thetext = $namespace_or_type_name.thetext; };
|
|
|
|
namespace_or_type_name returns [string thetext]:
|
|
|
|
t1=type_or_generic { $thetext=t1.type+formatTyargs($t1.generic_arguments); } ('::' tc=type_or_generic { $thetext+="::"+tc.type+formatTyargs($tc.generic_arguments); })? ('.' tn=type_or_generic { $thetext+="."+tn.type+formatTyargs($tn.generic_arguments); } )* ;
|
|
|
|
type_or_generic returns [string type, List<string> generic_arguments]
|
|
|
|
@init {
|
|
|
|
$generic_arguments = new List<String>();
|
|
|
|
}
|
|
|
|
@after{
|
|
|
|
$type = $t.text;
|
|
|
|
}:
|
|
|
|
(identifier generic_argument_list) => t=identifier ga=generic_argument_list { $generic_arguments = $ga.tyargs; }
|
|
|
|
| t=identifier ;
|
2010-11-10 19:03:09 +01:00
|
|
|
|
|
|
|
// keving: as far as I can see this is (<interfacename>.)?identifier (<tyargs>)? at lease for C# 3.0 and less.
|
|
|
|
qid returns [string name, List<String> tyargs]: // qualified_identifier v2
|
|
|
|
qid_start qid_part* { $name=$qid_start.name; $tyargs = $qid_start.tyargs; }
|
2010-11-07 21:57:24 +01:00
|
|
|
;
|
2010-11-10 19:03:09 +01:00
|
|
|
qid_start returns [string name, List<String> tyargs]:
|
|
|
|
predefined_type { $name = $predefined_type.thetext; }
|
|
|
|
| (identifier generic_argument_list) => identifier generic_argument_list { $name = $identifier.text; $tyargs = $generic_argument_list.tyargs; }
|
2010-11-07 21:57:24 +01:00
|
|
|
// | 'this'
|
|
|
|
// | 'base'
|
2010-11-10 19:03:09 +01:00
|
|
|
| i1=identifier { $name = $i1.text; } ('::' inext=identifier { $name+="::" + $inext.text; })?
|
|
|
|
| literal { $name = $literal.text; }
|
2010-11-07 21:57:24 +01:00
|
|
|
; // 0.ToString() is legal
|
|
|
|
|
|
|
|
|
|
|
|
qid_part:
|
|
|
|
access_identifier ;
|
|
|
|
|
|
|
|
generic_argument_list returns [List<string> tyargs]
|
|
|
|
@after {
|
|
|
|
$tyargs = $ta.tyargs;
|
|
|
|
}
|
|
|
|
:
|
|
|
|
'<' ta=type_arguments '>' ;
|
|
|
|
type_arguments returns [List<string> tyargs]
|
|
|
|
@init {
|
|
|
|
$tyargs = new List<string>();
|
|
|
|
}
|
|
|
|
:
|
|
|
|
t1=type { $tyargs.Add($t1.thetext); } (',' tn=type { $tyargs.Add($tn.thetext); })* ;
|
|
|
|
|
|
|
|
type returns [string thetext]:
|
|
|
|
((predefined_type | type_name) rank_specifiers) => (p1=predefined_type { $thetext = $p1.thetext; } | tn1=type_name { $thetext = $tn1.thetext; }) rs=rank_specifiers { $thetext += $rs.text; } ('*' { $thetext += "*"; })*
|
|
|
|
| ((predefined_type | type_name) ('*'+ | '?')) => (p2=predefined_type { $thetext = $p2.thetext; } | tn2=type_name { $thetext = $tn2.thetext; }) (('*' { $thetext += "*"; })+ | '?' { $thetext += "?"; })
|
|
|
|
| (p3=predefined_type { $thetext = $p3.thetext; } | tn3=type_name { $thetext = $tn3.thetext; })
|
|
|
|
| 'void' { $thetext = "System.Void"; } ('*' { $thetext += "*"; })+
|
|
|
|
;
|
|
|
|
non_nullable_type:
|
|
|
|
(predefined_type | type_name)
|
|
|
|
( rank_specifiers '*'*
|
|
|
|
| ('*'+)?
|
|
|
|
)
|
|
|
|
| 'void' '*'+ ;
|
|
|
|
|
|
|
|
non_array_type:
|
|
|
|
type;
|
|
|
|
array_type:
|
|
|
|
type;
|
|
|
|
unmanaged_type:
|
|
|
|
type;
|
|
|
|
class_type:
|
|
|
|
type;
|
|
|
|
pointer_type:
|
|
|
|
type;
|
|
|
|
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Statement Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
block:
|
|
|
|
';'
|
|
|
|
| '{' statement_list? '}';
|
|
|
|
statement_list:
|
|
|
|
statement+ ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Expression Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
expression:
|
|
|
|
(unary_expression assignment_operator) => assignment
|
|
|
|
| non_assignment_expression
|
|
|
|
;
|
|
|
|
expression_list:
|
|
|
|
expression (',' expression)* ;
|
|
|
|
assignment:
|
|
|
|
unary_expression assignment_operator expression ;
|
|
|
|
unary_expression:
|
|
|
|
//('(' arguments ')' ('[' | '.' | '(')) => primary_or_array_creation_expression
|
|
|
|
(cast_expression) => cast_expression
|
|
|
|
| primary_or_array_creation_expression
|
|
|
|
| '+' unary_expression
|
|
|
|
| '-' unary_expression
|
|
|
|
| '!' unary_expression
|
|
|
|
| '~' unary_expression
|
|
|
|
| pre_increment_expression
|
|
|
|
| pre_decrement_expression
|
|
|
|
| pointer_indirection_expression
|
|
|
|
| addressof_expression
|
|
|
|
;
|
|
|
|
cast_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
//'(' type ')' unary_expression ;
|
|
|
|
'(' type ')' unary_expression -> ^(CAST_EXPR type SEP unary_expression);
|
2010-11-07 21:57:24 +01:00
|
|
|
assignment_operator:
|
|
|
|
'=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>' '>=' ;
|
|
|
|
pre_increment_expression:
|
|
|
|
'++' unary_expression ;
|
|
|
|
pre_decrement_expression:
|
|
|
|
'--' unary_expression ;
|
|
|
|
pointer_indirection_expression:
|
|
|
|
'*' unary_expression ;
|
|
|
|
addressof_expression:
|
|
|
|
'&' unary_expression ;
|
|
|
|
|
|
|
|
non_assignment_expression:
|
|
|
|
//'non ASSIGNment'
|
|
|
|
(anonymous_function_signature '=>') => lambda_expression
|
|
|
|
| (query_expression) => query_expression
|
|
|
|
| conditional_expression
|
|
|
|
;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Conditional Expression Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
multiplicative_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
(u1=unary_expression -> $u1) ((op='*'|op='/'|op='%') un=unary_expression -> ^($op $multiplicative_expression $un) )* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
additive_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
multiplicative_expression (('+'|'-')^ multiplicative_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
// >> check needed (no whitespace)
|
|
|
|
shift_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
a1=additive_expression ((so='<<' a3=additive_expression -> ^($so $a1 $a3))
|
|
|
|
| ('>' '>' a2=additive_expression -> ^(RIGHT_SHIFT $a1 $a2))
|
|
|
|
)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
relational_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
(s1=shift_expression -> $s1)
|
|
|
|
( ((o='<'|o='>'|o='>='|o='<=') s2=shift_expression -> ^($o $relational_expression $s2))
|
|
|
|
| (i='is' t=non_nullable_type -> ^(INSTANCEOF[$i.Token,"instanceof"] $relational_expression $t)
|
|
|
|
| i1='as' t1=non_nullable_type -> ^(COND_EXPR[$i1.Token, "?:"]
|
|
|
|
^(INSTANCEOF[$i1.Token,"instanceof"] { (CommonTree)adaptor.DupTree($relational_expression.tree) } { (CommonTree)adaptor.DupTree($t1.tree) } )
|
|
|
|
^(CAST_EXPR[$i1.Token, "(cast)"] { (CommonTree)adaptor.DupTree($t1.tree) } SEP[$i1.Token, "SEP"] { (CommonTree)adaptor.DupTree($relational_expression.tree) })
|
|
|
|
^(CAST_EXPR[$i1.Token, "(cast)"] { (CommonTree)adaptor.DupTree($t1.tree) } SEP[$i1.Token, "SEP"] NULL[$i1.Token, "null"])))
|
2010-11-07 21:57:24 +01:00
|
|
|
)* ;
|
|
|
|
equality_expression:
|
|
|
|
relational_expression
|
2010-11-24 07:52:54 +01:00
|
|
|
(('=='|'!=')^ relational_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
and_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
equality_expression ('&'^ equality_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
exclusive_or_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
and_expression ('^'^ and_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
inclusive_or_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
exclusive_or_expression ('|'^ exclusive_or_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
conditional_and_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
inclusive_or_expression ('&&'^ inclusive_or_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
conditional_or_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
conditional_and_expression ('||'^ conditional_and_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
null_coalescing_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
conditional_or_expression ('??'^ conditional_or_expression)* ;
|
2010-11-07 21:57:24 +01:00
|
|
|
conditional_expression:
|
2010-11-24 07:52:54 +01:00
|
|
|
(null_coalescing_expression '?' expression ':') => e1=null_coalescing_expression q='?' e2=expression ':' e3=expression -> ^(COND_EXPR[$q.Token, "?:"] $e1 $e2 $e3)
|
|
|
|
| null_coalescing_expression ;
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// lambda Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
lambda_expression:
|
|
|
|
anonymous_function_signature '=>' anonymous_function_body;
|
|
|
|
anonymous_function_signature:
|
|
|
|
'(' (explicit_anonymous_function_parameter_list
|
|
|
|
| implicit_anonymous_function_parameter_list)? ')'
|
|
|
|
| implicit_anonymous_function_parameter_list
|
|
|
|
;
|
|
|
|
implicit_anonymous_function_parameter_list:
|
|
|
|
implicit_anonymous_function_parameter (',' implicit_anonymous_function_parameter)* ;
|
|
|
|
implicit_anonymous_function_parameter:
|
|
|
|
identifier;
|
|
|
|
anonymous_function_body:
|
|
|
|
expression
|
|
|
|
| block ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// LINQ Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
query_expression:
|
|
|
|
from_clause query_body ;
|
|
|
|
query_body:
|
|
|
|
// match 'into' to closest query_body
|
|
|
|
query_body_clauses? select_or_group_clause (('into') => query_continuation)? ;
|
|
|
|
query_continuation:
|
|
|
|
'into' identifier query_body;
|
|
|
|
query_body_clauses:
|
|
|
|
query_body_clause+ ;
|
|
|
|
query_body_clause:
|
|
|
|
from_clause
|
|
|
|
| let_clause
|
|
|
|
| where_clause
|
|
|
|
| join_clause
|
|
|
|
| orderby_clause;
|
|
|
|
from_clause:
|
|
|
|
'from' type? identifier 'in' expression ;
|
|
|
|
join_clause:
|
|
|
|
'join' type? identifier 'in' expression 'on' expression 'equals' expression ('into' identifier)? ;
|
|
|
|
let_clause:
|
|
|
|
'let' identifier '=' expression;
|
|
|
|
orderby_clause:
|
|
|
|
'orderby' ordering_list ;
|
|
|
|
ordering_list:
|
|
|
|
ordering (',' ordering)* ;
|
|
|
|
ordering:
|
|
|
|
expression ordering_direction
|
|
|
|
;
|
|
|
|
ordering_direction:
|
|
|
|
'ascending'
|
|
|
|
| 'descending' ;
|
|
|
|
select_or_group_clause:
|
|
|
|
select_clause
|
|
|
|
| group_clause ;
|
|
|
|
select_clause:
|
|
|
|
'select' expression ;
|
|
|
|
group_clause:
|
|
|
|
'group' expression 'by' expression ;
|
|
|
|
where_clause:
|
|
|
|
'where' boolean_expression ;
|
|
|
|
boolean_expression:
|
|
|
|
expression;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// B.2.13 Attributes
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
global_attributes:
|
|
|
|
global_attribute+ ;
|
|
|
|
global_attribute:
|
|
|
|
'[' global_attribute_target_specifier attribute_list ','? ']' ;
|
|
|
|
global_attribute_target_specifier:
|
|
|
|
global_attribute_target ':' ;
|
|
|
|
global_attribute_target:
|
|
|
|
'assembly' | 'module' ;
|
|
|
|
attributes:
|
|
|
|
attribute_sections ;
|
|
|
|
attribute_sections:
|
|
|
|
attribute_section+ ;
|
|
|
|
attribute_section:
|
|
|
|
'[' attribute_target_specifier? attribute_list ','? ']' ;
|
|
|
|
attribute_target_specifier:
|
|
|
|
attribute_target ':' ;
|
|
|
|
attribute_target:
|
|
|
|
'field' | 'event' | 'method' | 'param' | 'property' | 'return' | 'type' ;
|
|
|
|
attribute_list:
|
|
|
|
attribute (',' attribute)* ;
|
|
|
|
attribute:
|
|
|
|
type_name attribute_arguments? ;
|
|
|
|
// TODO: allows a mix of named/positional arguments in any order
|
|
|
|
attribute_arguments:
|
|
|
|
'(' (')' // empty
|
|
|
|
| (positional_argument ((',' identifier '=') => named_argument
|
|
|
|
|',' positional_argument)*
|
|
|
|
) ')'
|
|
|
|
) ;
|
|
|
|
positional_argument_list:
|
|
|
|
positional_argument (',' positional_argument)* ;
|
|
|
|
positional_argument:
|
|
|
|
attribute_argument_expression ;
|
|
|
|
named_argument_list:
|
|
|
|
named_argument (',' named_argument)* ;
|
|
|
|
named_argument:
|
|
|
|
identifier '=' attribute_argument_expression ;
|
|
|
|
attribute_argument_expression:
|
|
|
|
expression ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Class Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
class_declaration returns [string name]:
|
2010-11-19 16:49:43 +01:00
|
|
|
c='class' identifier 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]
|
|
|
|
@init {
|
|
|
|
List<string> names = new List<string>();
|
|
|
|
}:
|
|
|
|
'<'! attributes? t1=type_parameter { names.Add($t1.name); } ( ','! attributes? tn=type_parameter { names.Add($tn.name); })* '>'! ;
|
|
|
|
|
|
|
|
type_parameter returns [string name]:
|
|
|
|
identifier { $name = $identifier.text; } ;
|
|
|
|
|
2010-11-07 21:57:24 +01:00
|
|
|
class_base:
|
2010-11-18 14:23:17 +01:00
|
|
|
// just put all types in a single list. In NetMaker we will extract the base class if necessary
|
|
|
|
':' interface_type_list -> ^(IMPLEMENTS interface_type_list);
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
interface_type_list:
|
2010-11-18 14:23:17 +01:00
|
|
|
ts+=type (',' ts+=type)* -> $ts+;
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
class_body:
|
|
|
|
'{' class_member_declarations? '}' ;
|
|
|
|
class_member_declarations:
|
|
|
|
class_member_declaration+ ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
constant_declaration:
|
|
|
|
'const' type constant_declarators ';' ;
|
|
|
|
constant_declarators:
|
|
|
|
constant_declarator (',' constant_declarator)* ;
|
|
|
|
constant_declarator:
|
|
|
|
identifier ('=' constant_expression)? ;
|
|
|
|
constant_expression:
|
|
|
|
expression;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
field_declaration:
|
|
|
|
variable_declarators ';' ;
|
|
|
|
variable_declarators:
|
|
|
|
variable_declarator (',' variable_declarator)* ;
|
|
|
|
variable_declarator:
|
|
|
|
type_name ('=' variable_initializer)? ; // eg. event EventHandler IInterface.VariableName = Foo;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
method_declaration:
|
|
|
|
method_header method_body ;
|
|
|
|
method_header:
|
|
|
|
member_name '(' formal_parameter_list? ')' type_parameter_constraints_clauses? ;
|
|
|
|
method_body:
|
|
|
|
block ;
|
2010-11-10 19:03:09 +01:00
|
|
|
member_name returns [string name, List<String> tyargs]:
|
|
|
|
qid { $name = $qid.name; $tyargs = $qid.tyargs; } ; // IInterface<int>.Method logic added.
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
property_declaration:
|
|
|
|
member_name '{' accessor_declarations '}' ;
|
|
|
|
accessor_declarations:
|
|
|
|
attributes?
|
|
|
|
(get_accessor_declaration attributes? set_accessor_declaration?
|
|
|
|
| set_accessor_declaration attributes? get_accessor_declaration?) ;
|
|
|
|
get_accessor_declaration:
|
|
|
|
accessor_modifier? 'get' accessor_body ;
|
|
|
|
set_accessor_declaration:
|
|
|
|
accessor_modifier? 'set' accessor_body ;
|
|
|
|
accessor_modifier:
|
|
|
|
'public' | 'protected' | 'private' | 'internal' ;
|
|
|
|
accessor_body:
|
|
|
|
block ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
event_declaration:
|
|
|
|
'event' type
|
|
|
|
((member_name '{') => member_name '{' event_accessor_declarations '}'
|
|
|
|
| variable_declarators ';') // typename=foo;
|
|
|
|
;
|
|
|
|
event_modifiers:
|
|
|
|
modifier+ ;
|
|
|
|
event_accessor_declarations:
|
|
|
|
attributes? ((add_accessor_declaration attributes? remove_accessor_declaration)
|
|
|
|
| (remove_accessor_declaration attributes? add_accessor_declaration)) ;
|
|
|
|
add_accessor_declaration:
|
|
|
|
'add' block ;
|
|
|
|
remove_accessor_declaration:
|
|
|
|
'remove' block ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// enum declaration
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
enum_declaration returns [string name]:
|
|
|
|
'enum' identifier { $name = $identifier.text; } enum_base? enum_body ';'? ;
|
|
|
|
enum_base:
|
|
|
|
':' integral_type ;
|
|
|
|
enum_body:
|
2010-11-16 13:51:43 +01:00
|
|
|
'{' (enum_member_declarations ','?)? '}' -> ^(ENUM_BODY enum_member_declarations) ;
|
|
|
|
enum_member_declarations
|
|
|
|
@init {
|
|
|
|
SortedList<int,CommonTree> members = new SortedList<int,CommonTree>();
|
|
|
|
int next = 0;
|
|
|
|
}
|
|
|
|
@after{
|
|
|
|
$enum_member_declarations.tree = (CommonTree)adaptor.Nil;
|
|
|
|
int dummyCounter = 0;
|
|
|
|
for (int i = 0; i < next; i++) {
|
|
|
|
if (members.ContainsKey(i)) {
|
|
|
|
adaptor.AddChild($enum_member_declarations.tree, members[i]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
adaptor.AddChild($enum_member_declarations.tree, adaptor.Create(IDENTIFIER, $e.start.Token, "__dummyEnum__" + dummyCounter++));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|
|
|
|
:
|
|
|
|
e=enum_member_declaration[members,ref next] (',' enum_member_declaration[members, ref next])*
|
|
|
|
->
|
|
|
|
;
|
2010-11-16 16:01:56 +01:00
|
|
|
enum_member_declaration[ SortedList<int,CommonTree> members, ref int next]
|
|
|
|
@init {
|
|
|
|
int calcValue = 0;
|
|
|
|
}:
|
|
|
|
// Fill in members, a map from enum's value to AST
|
|
|
|
attributes? identifier { $members[$next] = $identifier.tree; $next++; }
|
|
|
|
((eq='=' ( ((NUMBER | Hex_number) (','|'}')) =>
|
|
|
|
{ Console.Out.WriteLine($i); $members.Remove($next-1); }
|
|
|
|
(i=NUMBER { calcValue = Int32.Parse($i.text); }
|
|
|
|
| i=Hex_number { calcValue = Int32.Parse($i.text.Substring(2), NumberStyles.AllowHexSpecifier); } )
|
|
|
|
{ if (calcValue < 0 || calcValue > Int32.MaxValue) {
|
|
|
|
Warning($eq.line, "[UNSUPPORTED] enum member's value initialization ignored, only numeric literals in the range 0..MAXINT supported for enum values");
|
|
|
|
calcValue = $next-1;
|
|
|
|
}
|
|
|
|
else if (calcValue < $next-1) {
|
|
|
|
Warning($eq.line, "[UNSUPPORTED] enum member's value initialization ignored, value has already been assigned and enum values must be unique");
|
|
|
|
calcValue = $next-1;
|
|
|
|
}
|
|
|
|
$members[calcValue] = $identifier.tree; $next = calcValue + 1; }
|
|
|
|
| expression { Warning($eq.line, "[UNSUPPORTED] enum member's value initialization ignored, only numeric literals supported for enum values"); } ))?)! ;
|
2010-11-07 21:57:24 +01:00
|
|
|
//enum_modifiers:
|
|
|
|
// enum_modifier+ ;
|
|
|
|
//enum_modifier:
|
|
|
|
// 'new' | 'public' | 'protected' | 'internal' | 'private' ;
|
|
|
|
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?
|
2010-11-19 16:49:43 +01:00
|
|
|
'(' formal_parameter_list? ')' type_parameter_constraints_clauses? ';' ->
|
|
|
|
'delegate' return_type identifier type_parameter_constraints_clauses? variant_generic_parameter_list?
|
|
|
|
'(' formal_parameter_list? ')' ';';
|
2010-11-07 21:57:24 +01:00
|
|
|
delegate_modifiers:
|
|
|
|
modifier+ ;
|
|
|
|
// 4.0
|
2010-11-10 19:03:09 +01:00
|
|
|
variant_generic_parameter_list returns [List<string> tyargs]
|
|
|
|
@init {
|
|
|
|
$tyargs = new List<string>();
|
|
|
|
}:
|
2010-11-19 16:49:43 +01:00
|
|
|
'<'! variant_type_parameters[$tyargs] '>'! ;
|
2010-11-10 19:03:09 +01:00
|
|
|
variant_type_parameters [List<String> tyargs]:
|
2010-11-19 16:49:43 +01:00
|
|
|
v1=variant_type_variable_name { tyargs.Add($v1.text); } (',' vn=variant_type_variable_name { tyargs.Add($vn.text); })* -> variant_type_variable_name+ ;
|
2010-11-07 21:57:24 +01:00
|
|
|
variant_type_variable_name:
|
|
|
|
attributes? variance_annotation? type_variable_name ;
|
|
|
|
variance_annotation:
|
2010-11-19 16:49:43 +01:00
|
|
|
'in' -> IN | 'out' -> OUT;
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
type_parameter_constraints_clauses:
|
2010-11-19 16:49:43 +01:00
|
|
|
type_parameter_constraints_clause (',' type_parameter_constraints_clause)* -> type_parameter_constraints_clause+ ;
|
2010-11-07 21:57:24 +01:00
|
|
|
type_parameter_constraints_clause:
|
2010-11-19 16:49:43 +01:00
|
|
|
'where' type_variable_name ':' type_parameter_constraint_list -> ^(TYPE_PARAM_CONSTRAINT type_variable_name type_parameter_constraint_list?) ;
|
2010-11-07 21:57:24 +01:00
|
|
|
// class, Circle, new()
|
|
|
|
type_parameter_constraint_list:
|
2010-11-19 16:49:43 +01:00
|
|
|
('class' | 'struct') (',' secondary_constraint_list)? (',' constructor_constraint)? -> secondary_constraint_list?
|
|
|
|
| secondary_constraint_list (',' constructor_constraint)? -> secondary_constraint_list
|
|
|
|
| constructor_constraint -> ;
|
2010-11-07 21:57:24 +01:00
|
|
|
//primary_constraint:
|
|
|
|
// class_type
|
|
|
|
// | 'class'
|
|
|
|
// | 'struct' ;
|
|
|
|
secondary_constraint_list:
|
2010-11-19 16:49:43 +01:00
|
|
|
secondary_constraint (',' secondary_constraint)* -> secondary_constraint+ ;
|
2010-11-07 21:57:24 +01:00
|
|
|
secondary_constraint:
|
|
|
|
type_name ; // | type_variable_name) ;
|
|
|
|
type_variable_name:
|
|
|
|
identifier ;
|
2010-11-19 16:49:43 +01:00
|
|
|
// keving: TOTEST we drop new constraints, but what will happen in Java for this case?
|
2010-11-07 21:57:24 +01:00
|
|
|
constructor_constraint:
|
|
|
|
'new' '(' ')' ;
|
|
|
|
return_type:
|
|
|
|
type
|
|
|
|
| 'void';
|
|
|
|
formal_parameter_list:
|
|
|
|
formal_parameter (',' formal_parameter)* ;
|
|
|
|
formal_parameter:
|
|
|
|
attributes? (fixed_parameter | parameter_array)
|
|
|
|
| '__arglist'; // __arglist is undocumented, see google
|
|
|
|
fixed_parameters:
|
|
|
|
fixed_parameter (',' fixed_parameter)* ;
|
|
|
|
// 4.0
|
|
|
|
fixed_parameter:
|
|
|
|
parameter_modifier? type identifier default_argument? ;
|
|
|
|
// 4.0
|
|
|
|
default_argument:
|
|
|
|
'=' expression;
|
|
|
|
parameter_modifier:
|
|
|
|
'ref' | 'out' | 'this' ;
|
|
|
|
parameter_array:
|
|
|
|
'params' type identifier ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
interface_declaration returns [string name]:
|
2010-11-18 14:23:17 +01:00
|
|
|
c='interface' identifier { $name = $identifier.text; } variant_generic_parameter_list?
|
|
|
|
interface_base? type_parameter_constraints_clauses? interface_body ';'?
|
2010-11-19 16:49:43 +01:00
|
|
|
-> ^(INTERFACE[$c.Token] identifier type_parameter_constraints_clauses? variant_generic_parameter_list? interface_base? interface_body );
|
2010-11-18 14:23:17 +01:00
|
|
|
|
|
|
|
interface_base:
|
|
|
|
':' interface_type_list -> ^(EXTENDS interface_type_list);
|
|
|
|
|
2010-11-07 21:57:24 +01:00
|
|
|
interface_modifiers:
|
|
|
|
modifier+ ;
|
|
|
|
interface_body:
|
|
|
|
'{' interface_member_declarations? '}' ;
|
|
|
|
interface_member_declarations:
|
|
|
|
interface_member_declaration+ ;
|
|
|
|
interface_member_declaration:
|
|
|
|
attributes? modifiers?
|
|
|
|
('void' interface_method_declaration
|
|
|
|
| interface_event_declaration
|
|
|
|
| type ( (member_name '(') => interface_method_declaration
|
|
|
|
| (member_name '{') => interface_property_declaration
|
|
|
|
| interface_indexer_declaration)
|
|
|
|
)
|
|
|
|
;
|
|
|
|
interface_property_declaration:
|
|
|
|
identifier '{' interface_accessor_declarations '}' ;
|
|
|
|
interface_method_declaration:
|
|
|
|
identifier generic_argument_list?
|
|
|
|
'(' formal_parameter_list? ')' type_parameter_constraints_clauses? ';' ;
|
|
|
|
interface_event_declaration:
|
|
|
|
//attributes? 'new'?
|
|
|
|
'event' type identifier ';' ;
|
|
|
|
interface_indexer_declaration:
|
|
|
|
// attributes? 'new'? type
|
|
|
|
'this' '[' formal_parameter_list ']' '{' interface_accessor_declarations '}' ;
|
|
|
|
interface_accessor_declarations:
|
|
|
|
attributes?
|
|
|
|
(interface_get_accessor_declaration attributes? interface_set_accessor_declaration?
|
|
|
|
| interface_set_accessor_declaration attributes? interface_get_accessor_declaration?) ;
|
|
|
|
interface_get_accessor_declaration:
|
|
|
|
'get' ';' ; // no body / modifiers
|
|
|
|
interface_set_accessor_declaration:
|
|
|
|
'set' ';' ; // no body / modifiers
|
|
|
|
method_modifiers:
|
|
|
|
modifier+ ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
struct_declaration returns [string name]:
|
2010-11-19 16:49:43 +01:00
|
|
|
c='struct' identifier 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 );
|
2010-11-18 14:23:17 +01:00
|
|
|
|
|
|
|
// UNUSED, HOPEFULLY
|
2010-11-07 21:57:24 +01:00
|
|
|
struct_modifiers:
|
|
|
|
struct_modifier+ ;
|
|
|
|
struct_modifier:
|
|
|
|
'new' | 'public' | 'protected' | 'internal' | 'private' | 'unsafe' ;
|
|
|
|
struct_interfaces:
|
|
|
|
':' interface_type_list;
|
|
|
|
struct_body:
|
|
|
|
'{' struct_member_declarations? '}';
|
|
|
|
struct_member_declarations:
|
|
|
|
struct_member_declaration+ ;
|
|
|
|
struct_member_declaration:
|
|
|
|
attributes? m=modifiers?
|
|
|
|
( 'const' type constant_declarators ';'
|
|
|
|
| event_declaration // 'event'
|
2010-11-10 19:03:09 +01:00
|
|
|
| p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (method_declaration
|
2010-11-07 21:57:24 +01:00
|
|
|
| interface_declaration
|
|
|
|
| class_declaration
|
|
|
|
| struct_declaration)
|
|
|
|
|
|
|
|
| interface_declaration // 'interface'
|
|
|
|
| class_declaration // 'class'
|
|
|
|
| 'void' method_declaration
|
|
|
|
| type ( (member_name '(') => method_declaration
|
|
|
|
| (member_name '{') => property_declaration
|
|
|
|
| (member_name '.' 'this') => type_name '.' indexer_declaration
|
|
|
|
| indexer_declaration //this
|
|
|
|
| field_declaration // qid
|
|
|
|
| operator_declaration
|
|
|
|
)
|
|
|
|
// common_modifiers// (method_modifiers | field_modifiers)
|
|
|
|
|
|
|
|
| struct_declaration // 'struct'
|
|
|
|
| enum_declaration // 'enum'
|
|
|
|
| delegate_declaration // 'delegate'
|
|
|
|
| conversion_operator_declaration
|
|
|
|
| constructor_declaration // | static_constructor_declaration
|
|
|
|
)
|
|
|
|
;
|
2010-11-18 14:23:17 +01:00
|
|
|
// UNUSED END
|
2010-11-07 21:57:24 +01:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
indexer_declaration:
|
|
|
|
indexer_declarator '{' accessor_declarations '}' ;
|
|
|
|
indexer_declarator:
|
|
|
|
//(type_name '.')?
|
|
|
|
'this' '[' formal_parameter_list ']' ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
operator_declaration:
|
|
|
|
operator_declarator operator_body ;
|
|
|
|
operator_declarator:
|
|
|
|
'operator'
|
|
|
|
(('+' | '-') '(' type identifier (binary_operator_declarator | unary_operator_declarator)
|
|
|
|
| overloadable_unary_operator '(' type identifier unary_operator_declarator
|
|
|
|
| overloadable_binary_operator '(' type identifier binary_operator_declarator) ;
|
|
|
|
unary_operator_declarator:
|
|
|
|
')' ;
|
|
|
|
overloadable_unary_operator:
|
|
|
|
/*'+' | '-' | */ '!' | '~' | '++' | '--' | 'true' | 'false' ;
|
|
|
|
binary_operator_declarator:
|
|
|
|
',' type identifier ')' ;
|
|
|
|
// >> check needed
|
|
|
|
overloadable_binary_operator:
|
|
|
|
/*'+' | '-' | */ '*' | '/' | '%' | '&' | '|' | '^' | '<<' | '>' '>' | '==' | '!=' | '>' | '<' | '>=' | '<=' ;
|
|
|
|
|
|
|
|
conversion_operator_declaration:
|
|
|
|
conversion_operator_declarator operator_body ;
|
|
|
|
conversion_operator_declarator:
|
|
|
|
('implicit' | 'explicit') 'operator' type '(' type identifier ')' ;
|
|
|
|
operator_body:
|
|
|
|
block ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
constructor_declaration:
|
|
|
|
constructor_declarator constructor_body ;
|
|
|
|
constructor_declarator:
|
|
|
|
identifier '(' formal_parameter_list? ')' constructor_initializer? ;
|
|
|
|
constructor_initializer:
|
|
|
|
':' ('base' | 'this') '(' argument_list? ')' ;
|
|
|
|
constructor_body:
|
|
|
|
block ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
//static_constructor_declaration:
|
|
|
|
// identifier '(' ')' static_constructor_body ;
|
|
|
|
//static_constructor_body:
|
|
|
|
// block ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
destructor_declaration:
|
|
|
|
'~' identifier '(' ')' destructor_body ;
|
|
|
|
destructor_body:
|
|
|
|
block ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
invocation_expression:
|
|
|
|
invocation_start (((arguments ('['|'.'|'->')) => arguments invocation_part)
|
|
|
|
| invocation_part)* arguments ;
|
|
|
|
invocation_start:
|
|
|
|
predefined_type
|
|
|
|
| (identifier generic_argument_list) => identifier generic_argument_list
|
|
|
|
| 'this'
|
|
|
|
| 'base'
|
|
|
|
| identifier ('::' identifier)?
|
|
|
|
| typeof_expression // typeof(Foo).Name
|
|
|
|
;
|
|
|
|
invocation_part:
|
|
|
|
access_identifier
|
|
|
|
| brackets ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
statement:
|
|
|
|
(declaration_statement) => declaration_statement
|
|
|
|
| (identifier ':') => labeled_statement
|
|
|
|
| embedded_statement
|
|
|
|
;
|
|
|
|
embedded_statement:
|
|
|
|
block
|
|
|
|
| selection_statement // if, switch
|
|
|
|
| iteration_statement // while, do, for, foreach
|
|
|
|
| jump_statement // break, continue, goto, return, throw
|
|
|
|
| try_statement
|
|
|
|
| checked_statement
|
|
|
|
| unchecked_statement
|
|
|
|
| lock_statement
|
|
|
|
| using_statement
|
|
|
|
| yield_statement
|
|
|
|
| unsafe_statement
|
|
|
|
| fixed_statement
|
|
|
|
| expression_statement // expression!
|
|
|
|
;
|
|
|
|
fixed_statement:
|
|
|
|
'fixed' '(' pointer_type fixed_pointer_declarators ')' embedded_statement ;
|
|
|
|
fixed_pointer_declarators:
|
|
|
|
fixed_pointer_declarator (',' fixed_pointer_declarator)* ;
|
|
|
|
fixed_pointer_declarator:
|
|
|
|
identifier '=' fixed_pointer_initializer ;
|
|
|
|
fixed_pointer_initializer:
|
|
|
|
//'&' variable_reference // unary_expression covers this
|
|
|
|
expression;
|
|
|
|
unsafe_statement:
|
|
|
|
'unsafe' block;
|
|
|
|
labeled_statement:
|
|
|
|
identifier ':' statement ;
|
|
|
|
declaration_statement:
|
|
|
|
(local_variable_declaration
|
|
|
|
| local_constant_declaration) ';' ;
|
|
|
|
local_variable_declaration:
|
|
|
|
local_variable_type local_variable_declarators ;
|
|
|
|
local_variable_type:
|
|
|
|
('var') => 'var'
|
|
|
|
| ('dynamic') => 'dynamic'
|
|
|
|
| type ;
|
|
|
|
local_variable_declarators:
|
|
|
|
local_variable_declarator (',' local_variable_declarator)* ;
|
|
|
|
local_variable_declarator:
|
|
|
|
identifier ('=' local_variable_initializer)? ;
|
|
|
|
local_variable_initializer:
|
|
|
|
expression
|
|
|
|
| array_initializer
|
|
|
|
| stackalloc_initializer;
|
|
|
|
stackalloc_initializer:
|
|
|
|
'stackalloc' unmanaged_type '[' expression ']' ;
|
|
|
|
local_constant_declaration:
|
|
|
|
'const' type constant_declarators ;
|
|
|
|
expression_statement:
|
|
|
|
expression ';' ;
|
|
|
|
|
|
|
|
// TODO: should be assignment, call, increment, decrement, and new object expressions
|
|
|
|
statement_expression:
|
|
|
|
expression
|
|
|
|
;
|
|
|
|
selection_statement:
|
|
|
|
if_statement
|
|
|
|
| switch_statement ;
|
|
|
|
if_statement:
|
|
|
|
// else goes with closest if
|
|
|
|
'if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)?
|
|
|
|
;
|
|
|
|
else_statement:
|
|
|
|
'else' embedded_statement ;
|
|
|
|
switch_statement:
|
|
|
|
'switch' '(' expression ')' switch_block ;
|
|
|
|
switch_block:
|
|
|
|
'{' switch_sections? '}' ;
|
|
|
|
switch_sections:
|
|
|
|
switch_section+ ;
|
|
|
|
switch_section:
|
|
|
|
switch_labels statement_list ;
|
|
|
|
switch_labels:
|
|
|
|
switch_label+ ;
|
|
|
|
switch_label:
|
|
|
|
('case' constant_expression ':')
|
|
|
|
| ('default' ':') ;
|
|
|
|
iteration_statement:
|
|
|
|
while_statement
|
|
|
|
| do_statement
|
|
|
|
| for_statement
|
|
|
|
| foreach_statement ;
|
|
|
|
while_statement:
|
|
|
|
'while' '(' boolean_expression ')' embedded_statement ;
|
|
|
|
do_statement:
|
|
|
|
'do' embedded_statement 'while' '(' boolean_expression ')' ';' ;
|
|
|
|
for_statement:
|
|
|
|
'for' '(' for_initializer? ';' for_condition? ';' for_iterator? ')' embedded_statement ;
|
|
|
|
for_initializer:
|
|
|
|
(local_variable_declaration) => local_variable_declaration
|
|
|
|
| statement_expression_list
|
|
|
|
;
|
|
|
|
for_condition:
|
|
|
|
boolean_expression ;
|
|
|
|
for_iterator:
|
|
|
|
statement_expression_list ;
|
|
|
|
statement_expression_list:
|
|
|
|
statement_expression (',' statement_expression)* ;
|
|
|
|
foreach_statement:
|
|
|
|
'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement ;
|
|
|
|
jump_statement:
|
|
|
|
break_statement
|
|
|
|
| continue_statement
|
|
|
|
| goto_statement
|
|
|
|
| return_statement
|
|
|
|
| throw_statement ;
|
|
|
|
break_statement:
|
|
|
|
'break' ';' ;
|
|
|
|
continue_statement:
|
|
|
|
'continue' ';' ;
|
|
|
|
goto_statement:
|
|
|
|
'goto' ( identifier
|
|
|
|
| 'case' constant_expression
|
|
|
|
| 'default') ';' ;
|
|
|
|
return_statement:
|
|
|
|
'return' expression? ';' ;
|
|
|
|
throw_statement:
|
|
|
|
'throw' expression? ';' ;
|
|
|
|
try_statement:
|
|
|
|
'try' block ( catch_clauses finally_clause?
|
|
|
|
| finally_clause);
|
|
|
|
//TODO one or both
|
|
|
|
catch_clauses:
|
|
|
|
'catch' (specific_catch_clauses | general_catch_clause) ;
|
|
|
|
specific_catch_clauses:
|
|
|
|
specific_catch_clause ('catch' (specific_catch_clause | general_catch_clause))*;
|
|
|
|
specific_catch_clause:
|
|
|
|
'(' class_type identifier? ')' block ;
|
|
|
|
general_catch_clause:
|
|
|
|
block ;
|
|
|
|
finally_clause:
|
|
|
|
'finally' block ;
|
|
|
|
checked_statement:
|
|
|
|
'checked' block ;
|
|
|
|
unchecked_statement:
|
|
|
|
'unchecked' block ;
|
|
|
|
lock_statement:
|
|
|
|
'lock' '(' expression ')' embedded_statement ;
|
|
|
|
using_statement:
|
|
|
|
'using' '(' resource_acquisition ')' embedded_statement ;
|
|
|
|
resource_acquisition:
|
|
|
|
(local_variable_declaration) => local_variable_declaration
|
|
|
|
| expression ;
|
|
|
|
yield_statement:
|
|
|
|
'yield' ('return' expression ';'
|
|
|
|
| 'break' ';') ;
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
// Lexar Section
|
|
|
|
///////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
predefined_type returns [string thetext]:
|
|
|
|
'bool' { $thetext = "System.Boolean"; }
|
|
|
|
| 'byte' { $thetext = "System.Byte"; }
|
|
|
|
| 'char' { $thetext = "System.Char"; }
|
|
|
|
| 'decimal' { $thetext = "System.Decimal"; }
|
|
|
|
| 'double' { $thetext = "System.Double"; }
|
|
|
|
| 'float' { $thetext = "System.Single"; }
|
|
|
|
| 'int' { $thetext = "System.Int32"; }
|
|
|
|
| 'long' { $thetext = "System.Int64"; }
|
|
|
|
| 'object' { $thetext = "System.Object"; }
|
|
|
|
| 'sbyte' { $thetext = "System.SByte"; }
|
|
|
|
| 'short' { $thetext = "System.Int16"; }
|
|
|
|
| 'string' { $thetext = "System.String"; }
|
|
|
|
| 'uint' { $thetext = "System.UInt32"; }
|
|
|
|
| 'ulong' { $thetext = "System.UInt64"; }
|
|
|
|
| 'ushort' { $thetext = "System.UInt16"; }
|
|
|
|
;
|
|
|
|
|
2010-11-24 07:42:25 +01:00
|
|
|
identifier
|
|
|
|
@after {
|
|
|
|
string fixedId = fixBrokenId($identifier.tree.Token.Text);
|
|
|
|
$identifier.tree.Token.Text = fixedId;
|
|
|
|
}:
|
2010-11-07 21:57:24 +01:00
|
|
|
IDENTIFIER | also_keyword;
|
|
|
|
|
|
|
|
keyword:
|
|
|
|
'abstract' | 'as' | 'base' | 'bool' | 'break' | 'byte' | 'case' | 'catch' | 'char' | 'checked' | 'class' | 'const' | 'continue' | 'decimal' | 'default' | 'delegate' | 'do' | 'double' | 'else' | 'enum' | 'event' | 'explicit' | 'extern' | 'false' | 'finally' | 'fixed' | 'float' | 'for' | 'foreach' | 'goto' | 'if' | 'implicit' | 'in' | 'int' | 'interface' | 'internal' | 'is' | 'lock' | 'long' | 'namespace' | 'new' | 'null' | 'object' | 'operator' | 'out' | 'override' | 'params' | 'private' | 'protected' | 'public' | 'readonly' | 'ref' | 'return' | 'sbyte' | 'sealed' | 'short' | 'sizeof' | 'stackalloc' | 'static' | 'string' | 'struct' | 'switch' | 'this' | 'throw' | 'true' | 'try' | 'typeof' | 'uint' | 'ulong' | 'unchecked' | 'unsafe' | 'ushort' | 'using' | 'virtual' | 'void' | 'volatile' ;
|
|
|
|
|
|
|
|
also_keyword:
|
|
|
|
'add' | 'alias' | 'assembly' | 'module' | 'field' | 'method' | 'param' | 'property' | 'type' | 'yield'
|
|
|
|
| 'from' | 'into' | 'join' | 'on' | 'where' | 'orderby' | 'group' | 'by' | 'ascending' | 'descending'
|
|
|
|
| 'equals' | 'select' | 'pragma' | 'let' | 'remove' | 'get' | 'set' | 'var' | '__arglist' | 'dynamic' | 'elif'
|
|
|
|
| 'endif' | 'define' | 'undef';
|
|
|
|
|
|
|
|
literal:
|
|
|
|
Real_literal
|
|
|
|
| NUMBER
|
|
|
|
| Hex_number
|
|
|
|
| Character_literal
|
|
|
|
| STRINGLITERAL
|
|
|
|
| Verbatim_string_literal
|
|
|
|
| TRUE
|
|
|
|
| FALSE
|
|
|
|
| NULL
|
|
|
|
;
|
|
|
|
|