mirror of
https://github.com/twiglet/cs2j.git
synced 2025-01-18 13:15:17 +01:00
Add parseString and IsJavaish so that we can parse arbitrary snippets of Java(ish) code and weave them into the output
This commit is contained in:
parent
71beb7eef6
commit
18fb3d4063
@ -129,6 +129,7 @@ namespace Twiglet.CS2J.Translator
|
|||||||
.Add ("translator-timestamp-files=", v => cfg.TranslatorAddTimeStamp = Boolean.Parse(v))
|
.Add ("translator-timestamp-files=", v => cfg.TranslatorAddTimeStamp = Boolean.Parse(v))
|
||||||
.Add ("translator-exception-is-throwable=", v => cfg.TranslatorExceptionIsThrowable = Boolean.Parse(v))
|
.Add ("translator-exception-is-throwable=", v => cfg.TranslatorExceptionIsThrowable = Boolean.Parse(v))
|
||||||
.Add ("experimental-transforms=", v => cfg.ExperimentalTransforms = Boolean.Parse(v))
|
.Add ("experimental-transforms=", v => cfg.ExperimentalTransforms = Boolean.Parse(v))
|
||||||
|
.Add ("internal-isjavaish", v => cfg.InternalIsJavaish = true)
|
||||||
;
|
;
|
||||||
|
|
||||||
//TODO: fix enum dump
|
//TODO: fix enum dump
|
||||||
@ -191,6 +192,7 @@ namespace Twiglet.CS2J.Translator
|
|||||||
w.Close();
|
w.Close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// load in T.stg template group, put in templates variable
|
// load in T.stg template group, put in templates variable
|
||||||
string templateLocation = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("templates", "java.stg"));
|
string templateLocation = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Path.Combine("templates", "java.stg"));
|
||||||
if (File.Exists(templateLocation)) {
|
if (File.Exists(templateLocation)) {
|
||||||
@ -279,6 +281,7 @@ namespace Twiglet.CS2J.Translator
|
|||||||
// }
|
// }
|
||||||
csParser p = new csParser(tokens);
|
csParser p = new csParser(tokens);
|
||||||
p.TraceDestination = Console.Error;
|
p.TraceDestination = Console.Error;
|
||||||
|
p.IsJavaish = cfg.InternalIsJavaish;
|
||||||
|
|
||||||
csParser.compilation_unit_return parser_rt = p.compilation_unit();
|
csParser.compilation_unit_return parser_rt = p.compilation_unit();
|
||||||
|
|
||||||
@ -439,6 +442,7 @@ namespace Twiglet.CS2J.Translator
|
|||||||
javaMaker.Cfg = cfg;
|
javaMaker.Cfg = cfg;
|
||||||
javaMaker.CUMap = new Dictionary<string, CUnit>();
|
javaMaker.CUMap = new Dictionary<string, CUnit>();
|
||||||
javaMaker.CUKeys = new List<string>();
|
javaMaker.CUKeys = new List<string>();
|
||||||
|
javaMaker.IsJavaish = cfg.InternalIsJavaish;
|
||||||
|
|
||||||
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Translating {0} to Java", fullName);
|
if (cfg.DebugLevel >= 1) Console.Out.WriteLine("Translating {0} to Java", fullName);
|
||||||
|
|
||||||
@ -514,6 +518,8 @@ namespace Twiglet.CS2J.Translator
|
|||||||
netMaker.AliasKeys = javaMaker.CUMap[typeName].NameSpaceAliasKeys;
|
netMaker.AliasKeys = javaMaker.CUMap[typeName].NameSpaceAliasKeys;
|
||||||
netMaker.AliasNamespaces = javaMaker.CUMap[typeName].NameSpaceAliasValues;
|
netMaker.AliasNamespaces = javaMaker.CUMap[typeName].NameSpaceAliasValues;
|
||||||
|
|
||||||
|
netMaker.IsJavaish = cfg.InternalIsJavaish;
|
||||||
|
|
||||||
if (cfg.DebugLevel > 5) Console.Out.WriteLine("Translating {0} Net Calls to Java", javaFName);
|
if (cfg.DebugLevel > 5) Console.Out.WriteLine("Translating {0} Net Calls to Java", javaFName);
|
||||||
NetMaker.compilation_unit_return javaCompilationUnit = netMaker.compilation_unit();
|
NetMaker.compilation_unit_return javaCompilationUnit = netMaker.compilation_unit();
|
||||||
|
|
||||||
|
@ -61,6 +61,11 @@ namespace Twiglet.CS2J.Translator
|
|||||||
get; set;
|
get; set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool InternalIsJavaish
|
||||||
|
{
|
||||||
|
get; set;
|
||||||
|
}
|
||||||
|
|
||||||
public CS2JSettings ()
|
public CS2JSettings ()
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -95,6 +100,8 @@ namespace Twiglet.CS2J.Translator
|
|||||||
TranslatorExceptionIsThrowable = false;
|
TranslatorExceptionIsThrowable = false;
|
||||||
|
|
||||||
ExperimentalTransforms = false;
|
ExperimentalTransforms = false;
|
||||||
|
|
||||||
|
InternalIsJavaish = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,13 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
using Antlr.Runtime.Tree;
|
using Antlr.Runtime.Tree;
|
||||||
using Antlr.Runtime;
|
using Antlr.Runtime;
|
||||||
|
|
||||||
|
using AntlrCSharp;
|
||||||
|
|
||||||
using Twiglet.CS2J.Translator.Utils;
|
using Twiglet.CS2J.Translator.Utils;
|
||||||
using Twiglet.CS2J.Translator.TypeRep;
|
using Twiglet.CS2J.Translator.TypeRep;
|
||||||
using Twiglet.CS2J.Translator;
|
using Twiglet.CS2J.Translator;
|
||||||
@ -119,6 +123,84 @@ namespace Twiglet.CS2J.Translator.Transform
|
|||||||
return (String.IsNullOrEmpty(ns) ? "" : ns + ".");
|
return (String.IsNullOrEmpty(ns) ? "" : ns + ".");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Routines to parse strings to ANTLR Trees on the fly, used to generate fragments needed by the transformation
|
||||||
|
public CommonTree parseString(string startRule, string inStr)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (Cfg.Verbosity > 5) Console.WriteLine("Parsing fragment ");
|
||||||
|
|
||||||
|
ICharStream input = new ANTLRStringStream(inStr);
|
||||||
|
|
||||||
|
PreProcessor lex = new PreProcessor();
|
||||||
|
lex.AddDefine(Cfg.MacroDefines);
|
||||||
|
lex.CharStream = input;
|
||||||
|
lex.TraceDestination = Console.Error;
|
||||||
|
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lex);
|
||||||
|
|
||||||
|
csParser p = new csParser(tokens);
|
||||||
|
p.TraceDestination = Console.Error;
|
||||||
|
p.IsJavaish = true;
|
||||||
|
|
||||||
|
// Try and call a rule like CSParser.namespace_body()
|
||||||
|
// Use reflection to find the rule to use.
|
||||||
|
MethodInfo mi = p.GetType().GetMethod(startRule);
|
||||||
|
|
||||||
|
if (mi == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Could not find start rule " + startRule + " in csParser");
|
||||||
|
}
|
||||||
|
|
||||||
|
ParserRuleReturnScope csRet = (ParserRuleReturnScope) mi.Invoke(p, new object[0]);
|
||||||
|
|
||||||
|
CommonTreeNodeStream csTreeStream = new CommonTreeNodeStream(csRet.Tree);
|
||||||
|
csTreeStream.TokenStream = tokens;
|
||||||
|
|
||||||
|
JavaMaker javaMaker = new JavaMaker(csTreeStream);
|
||||||
|
javaMaker.TraceDestination = Console.Error;
|
||||||
|
javaMaker.Cfg = Cfg;
|
||||||
|
javaMaker.IsJavaish = true;
|
||||||
|
|
||||||
|
// Try and call a rule like CSParser.namespace_body()
|
||||||
|
// Use reflection to find the rule to use.
|
||||||
|
mi = javaMaker.GetType().GetMethod(startRule);
|
||||||
|
|
||||||
|
if (mi == null)
|
||||||
|
{
|
||||||
|
throw new Exception("Could not find start rule " + startRule + " in javaMaker");
|
||||||
|
}
|
||||||
|
|
||||||
|
TreeRuleReturnScope javaSyntaxRet = (TreeRuleReturnScope) mi.Invoke(javaMaker, new object[0]);
|
||||||
|
|
||||||
|
CommonTree javaSyntaxAST = (CommonTree)javaSyntaxRet.Tree;
|
||||||
|
|
||||||
|
// CommonTreeNodeStream javaSyntaxNodes = new CommonTreeNodeStream(javaSyntaxAST);
|
||||||
|
//
|
||||||
|
// javaSyntaxNodes.TokenStream = csTree.TokenStream;
|
||||||
|
//
|
||||||
|
// NetMaker netMaker = new NetMaker(javaSyntaxNodes);
|
||||||
|
// netMaker.TraceDestination = Console.Error;
|
||||||
|
//
|
||||||
|
// netMaker.Cfg = Cfg;
|
||||||
|
// netMaker.AppEnv = AppEnv;
|
||||||
|
//
|
||||||
|
// CommonTree javaAST = (CommonTree)netMaker.class_member_declarations().Tree;
|
||||||
|
//
|
||||||
|
return javaSyntaxAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If true, then we are parsing some JavaIsh fragment
|
||||||
|
private bool isJavaish = false;
|
||||||
|
public bool IsJavaish
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return isJavaish;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
isJavaish = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wraps a compilation unit with its imports search path
|
// Wraps a compilation unit with its imports search path
|
||||||
|
@ -40,6 +40,7 @@ scope TypeContext {
|
|||||||
@header
|
@header
|
||||||
{
|
{
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,7 +708,17 @@ type_arguments returns [List<string> tyargs]
|
|||||||
$tyargs = new List<string>();
|
$tyargs = new List<string>();
|
||||||
}
|
}
|
||||||
:
|
:
|
||||||
t1=type { $tyargs.Add($t1.thetext); } (',' tn=type { $tyargs.Add($tn.thetext); })* ;
|
t1=type_argument { $tyargs.Add($t1.thetext); } (',' tn=type_argument { $tyargs.Add($tn.thetext); })* ;
|
||||||
|
|
||||||
|
public type_argument returns [string thetext]:
|
||||||
|
{this.IsJavaish}?=> javaish_type_argument {$thetext = $javaish_type_argument.thetext; }
|
||||||
|
| type {$thetext = $type.thetext; }
|
||||||
|
;
|
||||||
|
public javaish_type_argument returns [string thetext]:
|
||||||
|
('?' 'extends')=> '?' 'extends' type {$thetext = "? extends " + $type.thetext; }
|
||||||
|
| '?' {$thetext = "?"; }
|
||||||
|
| type {$thetext = $type.thetext; }
|
||||||
|
;
|
||||||
|
|
||||||
type returns [string 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 += "*"; })* -> ^(TYPE $p1? $tn1? $rs '*'*)
|
((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 += "*"; })* -> ^(TYPE $p1? $tn1? $rs '*'*)
|
||||||
@ -1029,11 +1040,14 @@ method_declaration [CommonTree atts, CommonTree mods, List<string> modList, Comm
|
|||||||
)?
|
)?
|
||||||
')'
|
')'
|
||||||
( type_parameter_constraints_clauses { isToString = false; isMain = false; })?
|
( type_parameter_constraints_clauses { isToString = false; isMain = false; })?
|
||||||
|
// Only have throw Exceptions if IsJavaish
|
||||||
|
throw_exceptions?
|
||||||
|
|
||||||
b=method_body[isToString]
|
b=method_body[isToString]
|
||||||
|
|
||||||
// build main method if required
|
// build main method if required
|
||||||
argParam=magicMainArgs[isMain && isMainHasArg, $member_name.tree.Token]
|
argParam=magicMainArgs[isMain && isMainHasArg, $member_name.tree.Token]
|
||||||
mainApply=magicMainApply[isMain, $member_name.tree.Token, $TypeContext::typeName, $argParam.tree]
|
mainApply=magicMainApply[isMain, $member_name.tree.Token, (isMain ? $TypeContext::typeName : null), $argParam.tree]
|
||||||
mainCall=magicMainExit[isMain, isInt, $member_name.tree.Token, $mainApply.tree]
|
mainCall=magicMainExit[isMain, isInt, $member_name.tree.Token, $mainApply.tree]
|
||||||
mainMethod=magicMainWrapper[isMain, $member_name.tree.Token, $mainCall.tree]
|
mainMethod=magicMainWrapper[isMain, $member_name.tree.Token, $mainCall.tree]
|
||||||
|
|
||||||
@ -1041,7 +1055,7 @@ method_declaration [CommonTree atts, CommonTree mods, List<string> modList, Comm
|
|||||||
{ if (isToString) {
|
{ if (isToString) {
|
||||||
$member_name.tree.Token.Text = "toString";
|
$member_name.tree.Token.Text = "toString";
|
||||||
}
|
}
|
||||||
exceptions = $b.exceptionList;
|
exceptions = IsJavaish ? $throw_exceptions.tree : $b.exceptionList;
|
||||||
}
|
}
|
||||||
-> $mainMethod?
|
-> $mainMethod?
|
||||||
^(METHOD { dupTree($atts) } { dupTree($mods) } { dupTree($type) }
|
^(METHOD { dupTree($atts) } { dupTree($mods) } { dupTree($type) }
|
||||||
@ -1053,8 +1067,16 @@ method_body [bool smotherExceptions] returns [CommonTree exceptionList]:
|
|||||||
| b=block el=magicThrowsException[true,$b.tree.Token] { $exceptionList=$el.tree; }
|
| b=block el=magicThrowsException[true,$b.tree.Token] { $exceptionList=$el.tree; }
|
||||||
-> $b
|
-> $b
|
||||||
;
|
;
|
||||||
member_name returns [string rawId]:
|
|
||||||
(type_or_generic '.')* i=identifier { $rawId = $i.text; }
|
throw_exceptions:
|
||||||
|
{IsJavaish}?=> 'throws'! t1=identifier { $t1.tree.Type = EXCEPTION; } (','! tn=identifier { $tn.tree.Type = EXCEPTION; } )*
|
||||||
|
;
|
||||||
|
member_name returns [string rawId, string full_name]
|
||||||
|
@init {
|
||||||
|
$full_name = "";
|
||||||
|
}:
|
||||||
|
(type_or_generic '.' {$full_name += mkTypeOrGenericString($type_or_generic.type, $type_or_generic.generic_arguments) + ".";})*
|
||||||
|
i=identifier { $rawId = $i.text; $full_name += $i.text; }
|
||||||
// keving [interface_type.identifier] | type_name '.' identifier
|
// keving [interface_type.identifier] | type_name '.' identifier
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -670,8 +670,13 @@ qid_part:
|
|||||||
generic_argument_list:
|
generic_argument_list:
|
||||||
'<' type_arguments '>' -> generic_args(args={ $type_arguments.st });
|
'<' type_arguments '>' -> generic_args(args={ $type_arguments.st });
|
||||||
type_arguments:
|
type_arguments:
|
||||||
ts+=type (',' ts+=type)* -> commalist(items = { $ts });
|
ts+=type_argument (',' ts+=type_argument)* -> commalist(items = { $ts });
|
||||||
|
|
||||||
|
public type_argument:
|
||||||
|
('?' 'extends')=> '?' 'extends' type -> op(pre={"?"},op={" extends "},post={$type.st})
|
||||||
|
| '?' -> string(payload={"?"})
|
||||||
|
| type -> { $type.st }
|
||||||
|
;
|
||||||
type
|
type
|
||||||
@init {
|
@init {
|
||||||
StringTemplate nm = null;
|
StringTemplate nm = null;
|
||||||
@ -1349,16 +1354,19 @@ predefined_type:
|
|||||||
| t='short' | t='string' | t='uint' | t='ulong' | t='ushort') { collectComments($t.TokenStartIndex); } -> string(payload={$t.text});
|
| t='short' | t='string' | t='uint' | t='ulong' | t='ushort') { collectComments($t.TokenStartIndex); } -> string(payload={$t.text});
|
||||||
|
|
||||||
identifier:
|
identifier:
|
||||||
i=IDENTIFIER { collectComments($i.TokenStartIndex); } -> string(payload= { $IDENTIFIER.text }) | also_keyword -> string(payload= { $also_keyword.text });
|
i=IDENTIFIER { collectComments($i.TokenStartIndex); } -> string(payload= { $IDENTIFIER.text }) | also_keyword -> { $also_keyword.st };
|
||||||
|
|
||||||
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' ;
|
'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:
|
also_keyword:
|
||||||
'add' | 'alias' | 'assembly' | 'module' | 'field' | 'method' | 'param' | 'property' | 'type' | 'yield'
|
(
|
||||||
| 'from' | 'into' | 'join' | 'on' | 'where' | 'orderby' | 'group' | 'by' | 'ascending' | 'descending'
|
t='add' | t='alias' | t='assembly' | t='module' | t='field' | t='method' | t='param' | t='property' | t='type' | t='yield'
|
||||||
| 'equals' | 'select' | 'pragma' | 'let' | 'remove' | 'get' | 'set' | 'var' | '__arglist' | 'dynamic' | 'elif'
|
| t='from' | t='into' | t='join' | t='on' | t='where' | t='orderby' | t='group' | t='by' | t='ascending' | t='descending'
|
||||||
| 'endif' | 'define' | 'undef';
|
| t='equals' | t='select' | t='pragma' | t='let' | t='remove' | t='get' | t='set' | t='var' | t='__arglist' | t='dynamic' | t='elif'
|
||||||
|
| t='endif' | t='define' | t='undef'
|
||||||
|
) -> string(payload={$t.text})
|
||||||
|
;
|
||||||
|
|
||||||
literal:
|
literal:
|
||||||
Real_literal -> string(payload={$Real_literal.text})
|
Real_literal -> string(payload={$Real_literal.text})
|
||||||
|
@ -15,7 +15,6 @@ tokens {
|
|||||||
INTERFACE;
|
INTERFACE;
|
||||||
FINAL; /* final modifier */
|
FINAL; /* final modifier */
|
||||||
ANNOTATION;
|
ANNOTATION;
|
||||||
IN;
|
|
||||||
OUT;
|
OUT;
|
||||||
CONST;
|
CONST;
|
||||||
EVENT;
|
EVENT;
|
||||||
@ -66,6 +65,9 @@ tokens {
|
|||||||
ELSE = 'else';
|
ELSE = 'else';
|
||||||
BREAK = 'break';
|
BREAK = 'break';
|
||||||
OBJECT = 'object';
|
OBJECT = 'object';
|
||||||
|
THIS = 'this';
|
||||||
|
FOREACH = 'foreach';
|
||||||
|
IN = 'in';
|
||||||
|
|
||||||
OPEN_BRACKET='[';
|
OPEN_BRACKET='[';
|
||||||
CLOSE_BRACKET=']';
|
CLOSE_BRACKET=']';
|
||||||
@ -176,6 +178,19 @@ tokens {
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We have a fragments library for strings that we want to splice in to the generated code.
|
||||||
|
// This is Java, so to parse it we need to set IsJavaish so that we are a bit more lenient ...
|
||||||
|
private bool isJavaish = false;
|
||||||
|
public bool IsJavaish
|
||||||
|
{
|
||||||
|
get {
|
||||||
|
return isJavaish;
|
||||||
|
}
|
||||||
|
set {
|
||||||
|
isJavaish = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public compilation_unit:
|
public compilation_unit:
|
||||||
@ -485,8 +500,16 @@ public qid_part:
|
|||||||
public generic_argument_list:
|
public generic_argument_list:
|
||||||
'<' type_arguments '>' ;
|
'<' type_arguments '>' ;
|
||||||
public type_arguments:
|
public type_arguments:
|
||||||
type (',' type)* ;
|
type_argument (',' type_argument)* ;
|
||||||
|
public type_argument:
|
||||||
|
{this.IsJavaish}?=> javaish_type_argument
|
||||||
|
| type
|
||||||
|
;
|
||||||
|
public javaish_type_argument:
|
||||||
|
('?' 'extends')=> '?' 'extends' type
|
||||||
|
| '?'
|
||||||
|
| type
|
||||||
|
;
|
||||||
public type:
|
public type:
|
||||||
((predefined_type | type_name) rank_specifiers) => (predefined_type | type_name) rank_specifiers '*'*
|
((predefined_type | type_name) rank_specifiers) => (predefined_type | type_name) rank_specifiers '*'*
|
||||||
| ((predefined_type | type_name) ('*'+ | '?')) => (predefined_type | type_name) ('*'+ | '?')
|
| ((predefined_type | type_name) ('*'+ | '?')) => (predefined_type | type_name) ('*'+ | '?')
|
||||||
@ -1127,7 +1150,10 @@ public for_iterator:
|
|||||||
public statement_expression_list:
|
public statement_expression_list:
|
||||||
statement_expression (',' statement_expression)* ;
|
statement_expression (',' statement_expression)* ;
|
||||||
public foreach_statement:
|
public foreach_statement:
|
||||||
'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement ;
|
'foreach' '(' local_variable_type identifier 'in' expression ')' embedded_statement
|
||||||
|
| {this.IsJavaish}? f='for' '(' local_variable_type identifier i=':' expression ')' embedded_statement
|
||||||
|
-> FOREACH[$f,"foreach"] '(' local_variable_type identifier IN[$i,"in"] expression ')' embedded_statement
|
||||||
|
;
|
||||||
public jump_statement:
|
public jump_statement:
|
||||||
break_statement
|
break_statement
|
||||||
| continue_statement
|
| continue_statement
|
||||||
|
Loading…
x
Reference in New Issue
Block a user