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-12-03 18:23:52 +01:00
2010-12-03 20:17:40 +01:00
// Map of C# built in types to Java equivalents
Dictionary<string, string> predefined_type_map = new Dictionary<string, string>()
{
{"bool", "boolean"},
{"object", "Object"},
{"string", "String"}
};
2010-12-03 18:23:52 +01:00
protected CommonTree mkHole() {
return mkHole(null);
}
protected CommonTree mkHole(IToken tok) {
return (CommonTree)adaptor.Create(KGHOLE, tok, "KGHOLE");
}
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'
2010-12-03 20:17:40 +01:00
| 'readonly' -> /* no equivalent in C# (this is like a const that can be initialized separately in the constructor) */ | 'volatile' | 'extern' | 'virtual' | 'override';
2010-11-18 14:23:17 +01:00
2010-11-07 21:57:24 +01:00
class_member_declaration:
2010-12-01 17:02:06 +01:00
a=attributes?
2010-11-07 21:57:24 +01:00
m=modifiers?
2010-12-01 17:02:06 +01:00
( c='const' ct=type constant_declarators ';' -> ^(CONST[$c.token, "CONST"] $a? $m? $ct constant_declarators)
| ed=event_declaration -> ^(EVENT[$ed.start.Token, "EVENT"] $a? $m? $ed)
| p='partial' { Warning($p.line, "[UNSUPPORTED] 'partial' definition"); } (v1='void' m3=method_declaration -> ^(METHOD[$v1.token, "METHOD"] $a? $m? ^(TYPE $v1) $m3)
| i1=interface_declaration -> ^(INTERFACE[$i1.start.Token, "INTERFACE"] $a? $m? $i1)
| c1=class_declaration -> ^(CLASS[$c1.start.Token, "CLASS"] $a? $m? $c1)
| s1=struct_declaration) -> ^(CLASS[$s1.start.Token, "CLASS"] $a? $m? $s1)
| i2=interface_declaration -> ^(INTERFACE[$i2.start.Token, "INTERFACE"] $a? $m? $i2) // 'interface'
| v='void' m1=method_declaration -> ^(METHOD[$v.token, "METHOD"] $a? $m? ^(TYPE[$v.token, "TYPE"] $v) $m1)
| t=type ( (member_name '(') => m2=method_declaration -> ^(METHOD[$t.start.Token, "METHOD"] $a? $m? $t $m2)
| (member_name '{') => property_declaration -> ^(PROPERTY[$t.start.Token, "PROPERTY"] $a? $m? $t property_declaration)
| (member_name '.' 'this') => type_name '.' ix1=indexer_declaration -> ^(INDEXER[$t.start.Token, "INDEXER"] $a? $m? $t type_name $ix1)
| ix2=indexer_declaration -> ^(INDEXER[$t.start.Token,"INDEXER"] $a? $m? $t $ix2) //this
| field_declaration -> ^(FIELD[$t.start.Token, "FIELD"] $a? $m? $t field_declaration) // qid
| operator_declaration -> ^(OPERATOR[$t.start.Token, "OPERATOR"] $a? $m? $t operator_declaration)
2010-11-07 21:57:24 +01:00
)
// common_modifiers// (method_modifiers | field_modifiers)
2010-12-01 17:02:06 +01:00
| c3=class_declaration -> ^(CLASS[$c3.start.Token, "CLASS"] $a? $m? $c3) // 'class'
| s3=struct_declaration -> ^(CLASS[$s3.start.Token, "CLASS"] $a? $m? $s3)
| e3=enum_declaration -> ^(ENUM[$e3.start.Token, "ENUM"] $a? $m? $e3)
| d3=delegate_declaration -> ^(DELEGATE[$d3.start.Token, "DELEGATE"] $a? $m? $d3)
| co3=conversion_operator_declaration -> ^(CONVERSION_OPERATOR[$co3.start.Token, "CONVERSION"] $a? $m? $co3)
| con3=constructor_declaration -> ^(CONSTRUCTOR[$con3.start.Token, "CONSTRUCTOR"] $a? $m? $con3)
| de3=destructor_declaration -> ^(DESTRUCTOR[$de3.start.Token, "DESTRUCTOR"] $a? $m? $de3)
2010-11-07 21:57:24 +01:00
)
;
primary_expression:
2010-12-01 17:02:06 +01:00
('this' brackets[null]) => (t='this' -> $t) (b1=brackets[$primary_expression.tree] -> $b1) (pp1=primary_expression_part[$primary_expression.tree] -> $pp1) *
| ('base' brackets[null]) => (b='this' -> $b) (b2=brackets[$primary_expression.tree] -> $b2) (pp2=primary_expression_part[$primary_expression.tree] -> $pp2) *
| (primary_expression_start -> primary_expression_start) (pp3=primary_expression_part[$primary_expression.tree] -> $pp3 )*
// keving:TODO fixup
2010-11-07 21:57:24 +01:00
| 'new' ( (object_creation_expression ('.'|'->'|'[')) =>
2010-12-03 18:23:52 +01:00
(oc1=object_creation_expression -> $oc1) (pp4=primary_expression_part[ $primary_expression.tree ] -> $pp4 )+ // new Foo(arg, arg).Member
2010-11-07 21:57:24 +01:00
// try the simple one first, this has no argS and no expressions
// symantically could be object creation
2010-12-03 18:23:52 +01:00
| (delegate_creation_expression) => delegate_creation_expression -> delegate_creation_expression // new FooDelegate (MyFunction)
| oc2=object_creation_expression -> $oc2
| anonymous_object_creation_expression -> anonymous_object_creation_expression) // new {int X, string Y}
2010-11-07 21:57:24 +01:00
| 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
;
2010-12-01 17:02:06 +01:00
primary_expression_part [CommonTree lhs]:
access_identifier[$lhs]
| brackets_or_arguments[$lhs]
| p='++' -> ^(POSTINC[$p.token, "POST++"] { (CommonTree)adaptor.DupTree($lhs) } )
| m='--' -> ^(POSTDEC[$m.token, "POST--"] { (CommonTree)adaptor.DupTree($lhs) } )
;
access_identifier [CommonTree lhs]:
access_operator type_or_generic -> ^(access_operator { (CommonTree)adaptor.DupTree($lhs) } type_or_generic);
2010-11-07 21:57:24 +01:00
access_operator:
'.' | '->' ;
2010-12-01 17:02:06 +01:00
brackets_or_arguments [CommonTree lhs]:
brackets[$lhs] | arguments[$lhs] ;
brackets [CommonTree lhs]:
'[' expression_list? ']' -> ^(INDEX { (CommonTree)adaptor.DupTree($lhs) } expression_list?);
// keving: TODO: drop this.
2010-11-07 21:57:24 +01:00
paren_expression:
2010-12-01 17:02:06 +01:00
'(' expression ')' -> ^(TEMPPARENS expression);
arguments [CommonTree lhs]:
'(' argument_list? ')' -> ^(APPLY { (CommonTree)adaptor.DupTree($lhs) } argument_list?);
2010-11-07 21:57:24 +01:00
argument_list:
2010-12-03 18:23:52 +01:00
a1=argument (',' an+=argument)* -> ^(ARGS[$a1.start.Token,"ARGS"] $a1 $an*);
2010-11-07 21:57:24 +01:00
// 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'
2010-12-03 18:23:52 +01:00
t1=type_name '(' t2=type_name ')' -> ^(NEW[$t1.start.Token, "NEW"] ^(TYPE[$t1.start.Token, "TYPE"] $t1) ^(ARGS[$t2.start.Token, "ARGS"] $t2));
2010-11-07 21:57:24 +01:00
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:
2010-12-01 17:02:06 +01:00
'new'^
2010-11-07 21:57:24 +01:00
(type ('[' expression_list ']'
( rank_specifiers? array_initializer? // new int[4]
// | invocation_part*
2010-12-01 17:02:06 +01:00
| ( ((arguments[null] ('['|'.'|'->')) => arguments[ (CommonTree)adaptor.Create(KGHOLE, "KGHOLE") ] invocation_part)// new object[2].GetEnumerator()
| invocation_part)* arguments[ (CommonTree)adaptor.Create(KGHOLE, "KGHOLE") ]
2010-11-07 21:57:24 +01:00
) // 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:
2010-12-01 17:02:06 +01:00
'sizeof'^ '('! unmanaged_type ')'!;
2010-11-07 21:57:24 +01:00
checked_expression:
2010-12-01 17:02:06 +01:00
'checked'^ '('! expression ')'! ;
2010-11-07 21:57:24 +01:00
unchecked_expression:
2010-12-01 17:02:06 +01:00
'unchecked'^ '('! expression ')'! ;
2010-11-07 21:57:24 +01:00
default_value_expression:
2010-12-01 17:02:06 +01:00
'default'^ '('! type ')'! ;
2010-11-07 21:57:24 +01:00
anonymous_method_expression:
2010-12-01 17:02:06 +01:00
'delegate'^ explicit_anonymous_function_signature? block;
2010-11-07 21:57:24 +01:00
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
2010-12-03 18:23:52 +01:00
( '(' argument_list? ')' o1=object_or_collection_initializer? -> ^(NEW[$type.start.Token, "NEW"] type argument_list? $o1?)
| o2=object_or_collection_initializer -> ^(NEW[$type.start.Token, "NEW"] type $o2))
2010-11-07 21:57:24 +01:00
;
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:
2010-12-01 17:02:06 +01:00
'typeof'^ '('! ((unbound_type_name) => unbound_type_name
2010-11-07 21:57:24 +01:00
| type
2010-12-01 17:02:06 +01:00
| 'void') ')'! ;
2010-11-07 21:57:24 +01:00
// 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]:
2010-12-03 18:23:52 +01:00
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); } )* ;
2010-11-07 21:57:24 +01:00
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
2010-12-03 18:23:52 +01:00
(qs=qid_start -> $qs) (qp=qid_part[$qid.tree] -> $qp)* { $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
2010-12-03 18:23:52 +01:00
qid_part[CommonTree lhs]:
access_identifier[ $lhs ] ;
2010-11-07 21:57:24 +01:00
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]:
2010-11-24 10:28:54 +01:00
((predefined_type | type_name) rank_specifiers) => (p1=predefined_type { $thetext = $p1.thetext; } | tn1=type_name { $thetext = $tn1.thetext; }) rs=rank_specifiers { $thetext += $rs.text; } (s1+='*' { $thetext += "*"; })* -> ^(TYPE $p1? $tn1? $rs $s1*)
| ((predefined_type | type_name) ('*'+ | '?')) => (p2=predefined_type { $thetext = $p2.thetext; } | tn2=type_name { $thetext = $tn2.thetext; }) ((s2+='*' { $thetext += "*"; })+ | o2='?' { $thetext += "?"; }) -> ^(TYPE $p2? $tn2? $s2* $o2?)
| (p3=predefined_type { $thetext = $p3.thetext; } | tn3=type_name { $thetext = $tn3.thetext; }) -> ^(TYPE $p3? $tn3?)
2010-12-01 17:02:06 +01:00
| v='void' { $thetext = "System.Void"; } (s+='*' { $thetext += "*"; })+ -> ^(TYPE[$v.token, "TYPE"] $v $s+)
2010-11-24 10:28:54 +01:00
;
2010-11-07 21:57:24 +01:00
non_nullable_type:
2010-12-01 17:02:06 +01:00
(p=predefined_type | t=type_name) rs=rank_specifiers? (s+='*')* -> ^(TYPE["TYPE"] $p? $t? $rs? $s*)
| v='void' (s+='*')+ -> ^(TYPE[$v.token,"TYPE"] $v $s+)
2010-11-24 10:28:54 +01:00
;
2010-11-07 21:57:24 +01:00
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
2010-12-01 17:02:06 +01:00
(cast_expression) => cast_expression
| primary_or_array_creation_expression -> primary_or_array_creation_expression
| p='+' unary_expression -> ^(MONOPLUS[$p.token,"MONOPLUS"] unary_expression)
| m='-' unary_expression -> ^(MONOMINUS[$m.token, "MONOMINUS"] unary_expression)
| n='!' unary_expression -> ^(MONONOT[$n.token, "MONONOT"] unary_expression)
| t='~' unary_expression -> ^(MONOTWIDDLE[$t.token, "TWIDDLE"] unary_expression)
| pre_increment_expression -> pre_increment_expression
| pre_decrement_expression -> pre_decrement_expression
| pointer_indirection_expression -> pointer_indirection_expression
| addressof_expression -> addressof_expression
2010-11-07 21:57:24 +01:00
;
cast_expression:
2010-12-01 17:02:06 +01:00
// //'(' type ')' unary_expression ;
l='(' type ')' unary_expression -> ^(CAST_EXPR[$l.token, "CAST"] type unary_expression);
2010-11-07 21:57:24 +01:00
assignment_operator:
'=' | '+=' | '-=' | '*=' | '/=' | '%=' | '&=' | '|=' | '^=' | '<<=' | '>' '>=' ;
pre_increment_expression:
2010-12-01 17:02:06 +01:00
s='++' unary_expression -> ^(PREINC[$s.token, "PRE++"] unary_expression) ;
2010-11-07 21:57:24 +01:00
pre_decrement_expression:
2010-12-01 17:02:06 +01:00
s='--' unary_expression -> ^(PREDEC[$s.token, "PRE--"] unary_expression);
2010-11-07 21:57:24 +01:00
pointer_indirection_expression:
2010-12-01 17:02:06 +01:00
s='*' unary_expression -> ^(MONOSTAR[$s.token, "STAR"] unary_expression);
2010-11-07 21:57:24 +01:00
addressof_expression:
2010-12-01 17:02:06 +01:00
a='&' unary_expression -> ^(ADDRESSOF[$a.token, "ADDRESSOF"] unary_expression);
2010-11-07 21:57:24 +01:00
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 17:13:39 +01:00
(a1=additive_expression -> $a1) ((so='<<' a3=additive_expression -> ^($so $shift_expression $a3))
| ('>' '>' a2=additive_expression -> ^(RIGHT_SHIFT $shift_expression $a2))
2010-11-24 07:52:54 +01:00
)* ;
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) } )
2010-11-24 11:29:30 +01:00
^(CAST_EXPR[$i1.Token, "(cast)"] { (CommonTree)adaptor.DupTree($t1.tree) } { (CommonTree)adaptor.DupTree($relational_expression.tree) })
^(CAST_EXPR[$i1.Token, "(cast)"] { (CommonTree)adaptor.DupTree($t1.tree) } 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-12-01 17:02:06 +01:00
(ne=null_coalescing_expression -> $ne) (q='?' te=expression ':' ee=expression -> ^(COND_EXPR[$q.token, "?:"] $conditional_expression $te $ee))? ;
// (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:
2010-12-03 18:23:52 +01:00
a1=positional_argument (',' an+=positional_argument)* -> ^(ARGS[$a1.start.Token,"ARGS"] $a1 $an*);
2010-11-07 21:57:24 +01:00
positional_argument:
attribute_argument_expression ;
named_argument_list:
2010-12-03 18:23:52 +01:00
a1=named_argument (',' an+=named_argument)* -> ^(ARGS[$a1.start.Token,"ARGS"] $a1 $an*);
2010-11-07 21:57:24 +01:00
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
2010-12-01 17:02:06 +01:00
| v='void' -> ^(TYPE[$v.token, "TYPE"] $v);
2010-11-07 21:57:24 +01:00
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:
2010-12-01 17:02:06 +01:00
invocation_start (((arguments[null] ('['|'.'|'->')) => arguments[ (CommonTree)adaptor.Create(KGHOLE, "KGHOLE") ] invocation_part)
| invocation_part)* arguments[ (CommonTree)adaptor.Create(KGHOLE, "KGHOLE") ] ;
2010-11-07 21:57:24 +01:00
invocation_start:
predefined_type
| (identifier generic_argument_list) => identifier generic_argument_list
| 'this'
| 'base'
| identifier ('::' identifier)?
| typeof_expression // typeof(Foo).Name
;
invocation_part:
2010-12-01 17:02:06 +01:00
access_identifier[ (CommonTree)adaptor.Create(KGHOLE, "KGHOLE") ]
| brackets[ (CommonTree)adaptor.Create(KGHOLE, "KGHOLE") ] ;
2010-11-07 21:57:24 +01:00
///////////////////////////////////////////////////////
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
2010-11-24 10:28:54 +01:00
// i='if' '(' boolean_expression ')' embedded_statement (('else') => else_statement)? -> ^(IF[$i.Token] boolean_expression embedded_statement else_statement?)
2010-11-07 21:57:24 +01:00
'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
///////////////////////////////////////////////////////
2010-12-03 20:17:40 +01:00
predefined_type returns [string thetext]
@after{
string newText;
if (predefined_type_map.TryGetValue($predefined_type.tree.Token.Text, out newText)) {
$predefined_type.tree.Token.Text = newText;
}
}:
'bool' { $thetext = "System.Boolean"; }
2010-11-07 21:57:24 +01:00
| '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
;