diff --git a/README.md b/README.md
index 5fffedd..1093a3d 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,6 @@
# SWG-ScriptConverter
-Some tool I made in 2015 to convert the original Star Wars Galaxies server scripts to Java.
+In 2015 someone asked me to make a tool to convert the original Star Wars Galaxies server scripts to Java. I believe it resulted in [this project](https://github.com/SWG-Source) as they have the scripts in Java form over there. That seems to be a fork though so it's probably in other places too.
+
+The source they have on [their repo](https://github.com/SWG-Source/dsrc/tree/master/sku.0/sys.server/compiled/game/script) is missing all the fun comments that were in the original scripts. I didn't bother preserving them in the output from this tool.
+
+Also I only got this to the point where you could compile the resulting Java source into class files. There is almost certainly a version out there that has additional fixes to this code.
diff --git a/ScriptConverter.sln b/ScriptConverter.sln
new file mode 100644
index 0000000..17c8f3e
--- /dev/null
+++ b/ScriptConverter.sln
@@ -0,0 +1,22 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 2013
+VisualStudioVersion = 12.0.31101.0
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ScriptConverter", "ScriptConverter\ScriptConverter.csproj", "{3F560E64-ACCE-4520-B3E7-EA6502E20F49}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {3F560E64-ACCE-4520-B3E7-EA6502E20F49}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {3F560E64-ACCE-4520-B3E7-EA6502E20F49}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {3F560E64-ACCE-4520-B3E7-EA6502E20F49}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {3F560E64-ACCE-4520-B3E7-EA6502E20F49}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/ScriptConverter/App.config b/ScriptConverter/App.config
new file mode 100644
index 0000000..8e15646
--- /dev/null
+++ b/ScriptConverter/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ScriptConverter/Ast/Declarations/Declaration.cs b/ScriptConverter/Ast/Declarations/Declaration.cs
new file mode 100644
index 0000000..d168297
--- /dev/null
+++ b/ScriptConverter/Ast/Declarations/Declaration.cs
@@ -0,0 +1,24 @@
+using System;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Declarations
+{
+ abstract class Declaration
+ {
+ public readonly ScriptToken Start;
+ public readonly ScriptToken End;
+
+ protected Declaration(ScriptToken start, ScriptToken end = null)
+ {
+ if (start == null)
+ throw new ArgumentNullException("start");
+
+ Start = start;
+ End = end ?? start;
+ }
+
+ public abstract TDecl Accept(IAstVisitor visitor);
+
+ public abstract void SetParent();
+ }
+}
diff --git a/ScriptConverter/Ast/Declarations/FieldDeclaration.cs b/ScriptConverter/Ast/Declarations/FieldDeclaration.cs
new file mode 100644
index 0000000..b097355
--- /dev/null
+++ b/ScriptConverter/Ast/Declarations/FieldDeclaration.cs
@@ -0,0 +1,34 @@
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Declarations
+{
+ class FieldDeclaration : Declaration
+ {
+ public ScriptType Type { get; private set; }
+ public string Name { get; private set; }
+ public Expression Value { get; private set; }
+ public bool IsConstant { get; private set; }
+ public bool IsPublic { get; private set; }
+
+ public FieldDeclaration(ScriptToken start, ScriptToken end, ScriptType type, string name, Expression value, bool isConst, bool isPublic)
+ : base(start, end)
+ {
+ Type = type;
+ Name = name;
+ Value = value;
+ IsConstant = isConst;
+ IsPublic = isPublic;
+ }
+
+ public override TDecl Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent()
+ {
+ Value.SetParent(null);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Declarations/IncludeDeclaration.cs b/ScriptConverter/Ast/Declarations/IncludeDeclaration.cs
new file mode 100644
index 0000000..6b53a30
--- /dev/null
+++ b/ScriptConverter/Ast/Declarations/IncludeDeclaration.cs
@@ -0,0 +1,25 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Declarations
+{
+ class IncludeDeclaration : Declaration
+ {
+ public string Name { get; private set; }
+
+ public IncludeDeclaration(ScriptToken start, ScriptToken end, string name)
+ : base(start, end)
+ {
+ Name = name;
+ }
+
+ public override TDecl Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent()
+ {
+
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Declarations/InheritsDeclaration.cs b/ScriptConverter/Ast/Declarations/InheritsDeclaration.cs
new file mode 100644
index 0000000..61c87c9
--- /dev/null
+++ b/ScriptConverter/Ast/Declarations/InheritsDeclaration.cs
@@ -0,0 +1,25 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Declarations
+{
+ class InheritsDeclaration : Declaration
+ {
+ public string Name { get; private set; }
+
+ public InheritsDeclaration(ScriptToken start, ScriptToken end, string name)
+ : base(start, end)
+ {
+ Name = name;
+ }
+
+ public override TDecl Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent()
+ {
+
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Declarations/MethodDeclaration.cs b/ScriptConverter/Ast/Declarations/MethodDeclaration.cs
new file mode 100644
index 0000000..d2246f5
--- /dev/null
+++ b/ScriptConverter/Ast/Declarations/MethodDeclaration.cs
@@ -0,0 +1,46 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Ast.Statements;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Declarations
+{
+ class MethodDeclaration : Declaration
+ {
+ public class Parameter
+ {
+ public ScriptType Type { get; private set; }
+ public string Name { get; private set; }
+
+ public Parameter(ScriptType type, string name)
+ {
+ Type = type;
+ Name = name;
+ }
+ }
+
+ public ScriptType ReturnType { get; private set; }
+ public string Name { get; private set; }
+ public ReadOnlyCollection Parameters { get; private set; }
+ public BlockStatement Block { get; private set; }
+
+ public MethodDeclaration(ScriptToken start, ScriptToken end, ScriptType returnType, string name, List parameters, BlockStatement block)
+ : base(start, end)
+ {
+ ReturnType = returnType;
+ Name = name;
+ Parameters = parameters.AsReadOnly();
+ Block = block;
+ }
+
+ public override TDecl Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent()
+ {
+ Block.SetParent(null);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Document.cs b/ScriptConverter/Ast/Document.cs
new file mode 100644
index 0000000..12ec918
--- /dev/null
+++ b/ScriptConverter/Ast/Document.cs
@@ -0,0 +1,19 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Linq;
+using ScriptConverter.Ast.Declarations;
+
+namespace ScriptConverter.Ast
+{
+ class Document
+ {
+ public ReadOnlyCollection Declarations { get; private set; }
+
+ public Document(IEnumerable declarations)
+ {
+ Declarations = declarations
+ .ToList()
+ .AsReadOnly();
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/ArrayInitializerExpression.cs b/ScriptConverter/Ast/Expressions/ArrayInitializerExpression.cs
new file mode 100644
index 0000000..d994bc4
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/ArrayInitializerExpression.cs
@@ -0,0 +1,32 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class ArrayInitializerExpression : Expression
+ {
+ public ReadOnlyCollection Values { get; private set; }
+
+ public ArrayInitializerExpression(ScriptToken start, ScriptToken end, List values)
+ : base(start, end)
+ {
+ Values = values.AsReadOnly();
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ foreach (var expression in Values)
+ {
+ expression.SetParent(this);
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/BinaryOperatorExpression.cs b/ScriptConverter/Ast/Expressions/BinaryOperatorExpression.cs
new file mode 100644
index 0000000..3eeb23a
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/BinaryOperatorExpression.cs
@@ -0,0 +1,32 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class BinaryOperatorExpression : Expression
+ {
+ public ScriptTokenType Operation { get; private set; }
+ public Expression Left { get; private set; }
+ public Expression Right { get; private set; }
+
+ public BinaryOperatorExpression(ScriptTokenType op, Expression left, Expression right)
+ : base(left.Start, right.End)
+ {
+ Operation = op;
+ Left = left;
+ Right = right;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Left.SetParent(this);
+ Right.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/BoolExpression.cs b/ScriptConverter/Ast/Expressions/BoolExpression.cs
new file mode 100644
index 0000000..d78373c
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/BoolExpression.cs
@@ -0,0 +1,25 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class BoolExpression : Expression
+ {
+ public bool Value { get; private set; }
+
+ public BoolExpression(ScriptToken token, bool value)
+ : base(token)
+ {
+ Value = value;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/CallExpression.cs b/ScriptConverter/Ast/Expressions/CallExpression.cs
new file mode 100644
index 0000000..d8205ef
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/CallExpression.cs
@@ -0,0 +1,36 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class CallExpression : Expression
+ {
+ public Expression Left { get; private set; }
+ public ReadOnlyCollection Parameters { get; private set; }
+
+ public CallExpression(ScriptToken end, Expression left, List parameters)
+ : base(left.Start, end)
+ {
+ Left = left;
+ Parameters = parameters.AsReadOnly();
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Left.SetParent(this);
+
+ foreach (var expression in Parameters)
+ {
+ expression.SetParent(this);
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/CastExpression.cs b/ScriptConverter/Ast/Expressions/CastExpression.cs
new file mode 100644
index 0000000..8cc86fb
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/CastExpression.cs
@@ -0,0 +1,29 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class CastExpression : Expression
+ {
+ public ScriptType Type { get; private set; }
+ public Expression Value { get; private set; }
+
+ public CastExpression(ScriptToken start, ScriptType type, Expression value)
+ : base(start, value.End)
+ {
+ Type = type;
+ Value = value;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Value.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/Expression.cs b/ScriptConverter/Ast/Expressions/Expression.cs
new file mode 100644
index 0000000..7e3a97e
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/Expression.cs
@@ -0,0 +1,25 @@
+using System;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ abstract class Expression
+ {
+ public readonly ScriptToken Start;
+ public readonly ScriptToken End;
+ public Expression Parent { get; protected set; }
+
+ protected Expression(ScriptToken start, ScriptToken end = null)
+ {
+ if (start == null)
+ throw new ArgumentNullException("start");
+
+ Start = start;
+ End = end ?? start;
+ }
+
+ public abstract TExpr Accept(IAstVisitor visitor);
+
+ public abstract void SetParent(Expression parent);
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/FieldExpression.cs b/ScriptConverter/Ast/Expressions/FieldExpression.cs
new file mode 100644
index 0000000..46b7087
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/FieldExpression.cs
@@ -0,0 +1,29 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class FieldExpression : Expression
+ {
+ public Expression Left { get; private set; }
+ public string Name { get; private set; }
+
+ public FieldExpression(Expression left, ScriptToken name)
+ : base(left.Start, name)
+ {
+ Left = left;
+ Name = name.Contents;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Left.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/IdentifierExpression.cs b/ScriptConverter/Ast/Expressions/IdentifierExpression.cs
new file mode 100644
index 0000000..71c1196
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/IdentifierExpression.cs
@@ -0,0 +1,25 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class IdentifierExpression : Expression
+ {
+ public string Name { get; private set; }
+
+ public IdentifierExpression(ScriptToken token)
+ : base(token)
+ {
+ Name = token.Contents;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/IndexerExpression.cs b/ScriptConverter/Ast/Expressions/IndexerExpression.cs
new file mode 100644
index 0000000..afb1865
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/IndexerExpression.cs
@@ -0,0 +1,30 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class IndexerExpression : Expression
+ {
+ public Expression Left { get; private set; }
+ public Expression Index { get; private set; }
+
+ public IndexerExpression(ScriptToken end, Expression left, Expression index)
+ : base(left.Start, end)
+ {
+ Left = left;
+ Index = index;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Left.SetParent(this);
+ Index.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/InstanceOfExpression.cs b/ScriptConverter/Ast/Expressions/InstanceOfExpression.cs
new file mode 100644
index 0000000..499ae0b
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/InstanceOfExpression.cs
@@ -0,0 +1,29 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class InstanceOfExpression : Expression
+ {
+ public Expression Left { get; private set; }
+ public ScriptType Type { get; private set; }
+
+ public InstanceOfExpression(ScriptToken end, Expression left, ScriptType type)
+ : base(left.Start, end)
+ {
+ Left = left;
+ Type = type;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Left.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/NewExpression.cs b/ScriptConverter/Ast/Expressions/NewExpression.cs
new file mode 100644
index 0000000..8ed62cd
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/NewExpression.cs
@@ -0,0 +1,47 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class NewExpression : Expression
+ {
+ public string Type { get; private set; }
+ public bool IsArray { get { return ArrayDimensions > 0; } }
+ public int ArrayDimensions { get; private set; }
+ public ReadOnlyCollection Parameters { get; private set; }
+ public ReadOnlyCollection Initializer { get; private set; }
+
+ public NewExpression(ScriptToken start, ScriptToken end, string type, int arrayDimensions, List parameters, List initializer = null)
+ : base(start, end)
+ {
+ Type = type;
+ ArrayDimensions = arrayDimensions;
+ Parameters = parameters.AsReadOnly();
+ Initializer = initializer != null ? initializer.AsReadOnly() : null;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ foreach (var expression in Parameters)
+ {
+ expression.SetParent(this);
+ }
+
+ if (Initializer != null)
+ {
+ foreach (var expression in Initializer)
+ {
+ expression.SetParent(this);
+ }
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/NullExpression.cs b/ScriptConverter/Ast/Expressions/NullExpression.cs
new file mode 100644
index 0000000..984ef0b
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/NullExpression.cs
@@ -0,0 +1,23 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class NullExpression : Expression
+ {
+ public NullExpression(ScriptToken token)
+ : base(token)
+ {
+
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/NumberExpression.cs b/ScriptConverter/Ast/Expressions/NumberExpression.cs
new file mode 100644
index 0000000..3a4ae22
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/NumberExpression.cs
@@ -0,0 +1,25 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class NumberExpression : Expression
+ {
+ public string Value { get; private set; }
+
+ public NumberExpression(ScriptToken token)
+ : base(token)
+ {
+ Value = token.Contents;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/PostfixOperatorExpression.cs b/ScriptConverter/Ast/Expressions/PostfixOperatorExpression.cs
new file mode 100644
index 0000000..ea3d9c1
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/PostfixOperatorExpression.cs
@@ -0,0 +1,29 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class PostfixOperatorExpression : Expression
+ {
+ public ScriptTokenType Operation { get; private set; }
+ public Expression Left { get; private set; }
+
+ public PostfixOperatorExpression(ScriptToken end, Expression left)
+ : base(left.Start, end)
+ {
+ Operation = end.Type;
+ Left = left;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Left.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/PrefixOperatorExpression.cs b/ScriptConverter/Ast/Expressions/PrefixOperatorExpression.cs
new file mode 100644
index 0000000..cb25108
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/PrefixOperatorExpression.cs
@@ -0,0 +1,29 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class PrefixOperatorExpression : Expression
+ {
+ public ScriptTokenType Operation { get; private set; }
+ public Expression Right { get; private set; }
+
+ public PrefixOperatorExpression(ScriptToken start, Expression right)
+ : base(start, right.End)
+ {
+ Operation = start.Type;
+ Right = right;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Right.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/StringExpression.cs b/ScriptConverter/Ast/Expressions/StringExpression.cs
new file mode 100644
index 0000000..346fc5e
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/StringExpression.cs
@@ -0,0 +1,27 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Expressions
+{
+ class StringExpression : Expression
+ {
+ public string Value { get; private set; }
+ public bool IsSingleQuote { get; private set; }
+
+ public StringExpression(ScriptToken token, bool singleQuote)
+ : base(token)
+ {
+ Value = token.Contents;
+ IsSingleQuote = singleQuote;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Expressions/TernaryExpression.cs b/ScriptConverter/Ast/Expressions/TernaryExpression.cs
new file mode 100644
index 0000000..2c83f96
--- /dev/null
+++ b/ScriptConverter/Ast/Expressions/TernaryExpression.cs
@@ -0,0 +1,31 @@
+namespace ScriptConverter.Ast.Expressions
+{
+ class TernaryExpression : Expression
+ {
+ public Expression Condition { get; private set; }
+ public Expression TrueExpression { get; private set; }
+ public Expression FalseExpression { get; private set; }
+
+ public TernaryExpression(Expression condition, Expression trueExpression, Expression falseExpression)
+ : base(condition.Start, falseExpression.End)
+ {
+ Condition = condition;
+ TrueExpression = trueExpression;
+ FalseExpression = falseExpression;
+ }
+
+ public override TExpr Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Expression parent)
+ {
+ Parent = parent;
+
+ Condition.SetParent(this);
+ TrueExpression.SetParent(this);
+ FalseExpression.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/IAstVisitor.cs b/ScriptConverter/Ast/IAstVisitor.cs
new file mode 100644
index 0000000..68c2666
--- /dev/null
+++ b/ScriptConverter/Ast/IAstVisitor.cs
@@ -0,0 +1,48 @@
+using ScriptConverter.Ast.Declarations;
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Ast.Statements;
+
+namespace ScriptConverter.Ast
+{
+ interface IAstVisitor
+ {
+ TDoc Visit(Document document);
+
+ TDecl Visit(FieldDeclaration declaration);
+ TDecl Visit(IncludeDeclaration declaration);
+ TDecl Visit(InheritsDeclaration declaration);
+ TDecl Visit(MethodDeclaration declaration);
+
+ TStmt Visit(BlockStatement statement);
+ TStmt Visit(BreakStatement statement);
+ TStmt Visit(ContinueStatement statement);
+ TStmt Visit(DoStatement statement);
+ TStmt Visit(EmptyStatement statement);
+ TStmt Visit(ForStatement statement);
+ TStmt Visit(IfStatement statement);
+ TStmt Visit(NakedStatement statement);
+ TStmt Visit(ReturnStatement statement);
+ TStmt Visit(SwitchStatement statement);
+ TStmt Visit(ThrowStatement statement);
+ TStmt Visit(TryStatement statement);
+ TStmt Visit(VariableStatement statement);
+ TStmt Visit(WhileStatement statement);
+
+ TExpr Visit(ArrayInitializerExpression expression);
+ TExpr Visit(BinaryOperatorExpression expression);
+ TExpr Visit(BoolExpression expression);
+ TExpr Visit(CallExpression expression);
+ TExpr Visit(CastExpression expression);
+ TExpr Visit(FieldExpression expression);
+ TExpr Visit(IdentifierExpression expression);
+ TExpr Visit(IndexerExpression expression);
+ TExpr Visit(InstanceOfExpression expression);
+ TExpr Visit(NewExpression expression);
+ TExpr Visit(NullExpression expression);
+ TExpr Visit(NumberExpression expression);
+ TExpr Visit(PostfixOperatorExpression expression);
+ TExpr Visit(PrefixOperatorExpression expression);
+ TExpr Visit(StringExpression expression);
+ TExpr Visit(TernaryExpression expression);
+ }
+}
diff --git a/ScriptConverter/Ast/ScriptType.cs b/ScriptConverter/Ast/ScriptType.cs
new file mode 100644
index 0000000..11c7231
--- /dev/null
+++ b/ScriptConverter/Ast/ScriptType.cs
@@ -0,0 +1,48 @@
+using System.Linq;
+
+namespace ScriptConverter.Ast
+{
+ class ScriptType
+ {
+ public string Name { get; private set; }
+ public bool IsArray { get { return ArrayDimensions > 0; } }
+ public bool IsResizable { get; private set; }
+ public int ArrayDimensions { get; private set; }
+
+ public ScriptType(string name, int arrayDimensions = 0, bool isResizable = false)
+ {
+ if (name == "unknown")
+ name = "Object";
+
+ if (name == "string")
+ name = "String";
+
+ if (name == "modifyable_int")
+ name = "modifiable_int";
+
+ if (name == "modifyable _float")
+ name = "modifiable_float";
+
+ if (name == "modifyable_string_id")
+ name = "modifiable_string_id";
+
+ if (isResizable)
+ arrayDimensions = 1;
+
+ Name = name;
+ IsResizable = isResizable;
+ ArrayDimensions = arrayDimensions;
+ }
+
+ public override string ToString()
+ {
+ if (IsResizable)
+ return "Vector";
+
+ if (!IsArray)
+ return Name;
+
+ return Name + string.Join("", Enumerable.Repeat("[]", ArrayDimensions));
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/BlockStatement.cs b/ScriptConverter/Ast/Statements/BlockStatement.cs
new file mode 100644
index 0000000..80d89f2
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/BlockStatement.cs
@@ -0,0 +1,38 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class BlockStatement : Statement
+ {
+ public ReadOnlyCollection Statements { get; private set; }
+ public bool IsSwitch { get; private set; }
+
+ public BlockStatement(ScriptToken start, ScriptToken end, List statements, bool isSwitch = false)
+ : base(start, end)
+ {
+ if (statements == null)
+ throw new ArgumentNullException("statements");
+
+ Statements = statements.AsReadOnly();
+ IsSwitch = isSwitch;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ foreach (var statement in Statements)
+ {
+ statement.SetParent(this);
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/BreakStatement.cs b/ScriptConverter/Ast/Statements/BreakStatement.cs
new file mode 100644
index 0000000..20ff15b
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/BreakStatement.cs
@@ -0,0 +1,23 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class BreakStatement : Statement
+ {
+ public BreakStatement(ScriptToken token)
+ : base(token)
+ {
+
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/ContinueStatement.cs b/ScriptConverter/Ast/Statements/ContinueStatement.cs
new file mode 100644
index 0000000..ceb0106
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/ContinueStatement.cs
@@ -0,0 +1,23 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class ContinueStatement : Statement
+ {
+ public ContinueStatement(ScriptToken token)
+ : base(token)
+ {
+
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/DoStatement.cs b/ScriptConverter/Ast/Statements/DoStatement.cs
new file mode 100644
index 0000000..a93c61f
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/DoStatement.cs
@@ -0,0 +1,31 @@
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class DoStatement : Statement
+ {
+ public Expression Condition { get; private set; }
+ public BlockStatement Block { get; private set; }
+
+ public DoStatement(ScriptToken start, ScriptToken end, Expression condition, BlockStatement block)
+ : base(start, end)
+ {
+ Condition = condition;
+ Block = block;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ Condition.SetParent(null);
+ Block.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/EmptyStatement.cs b/ScriptConverter/Ast/Statements/EmptyStatement.cs
new file mode 100644
index 0000000..6022e6c
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/EmptyStatement.cs
@@ -0,0 +1,23 @@
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class EmptyStatement : Statement
+ {
+ public EmptyStatement(ScriptToken token)
+ : base(token)
+ {
+
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/ForStatement.cs b/ScriptConverter/Ast/Statements/ForStatement.cs
new file mode 100644
index 0000000..ea3b1d0
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/ForStatement.cs
@@ -0,0 +1,55 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class ForStatement : Statement
+ {
+ public ReadOnlyCollection Initializers { get; private set; }
+ public Expression Condition { get; private set; }
+ public ReadOnlyCollection Increment { get; private set; }
+ public BlockStatement Block { get; private set; }
+
+ public ForStatement(ScriptToken start, ScriptToken end, List initializers, Expression condition, List increment, BlockStatement block)
+ : base(start, end)
+ {
+ Initializers = initializers != null ? initializers.AsReadOnly() : null;
+ Condition = condition;
+ Increment = increment != null ? increment.AsReadOnly() : null;
+ Block = block;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ if (Initializers != null)
+ {
+ foreach (var statement in Initializers)
+ {
+ statement.SetParent(this);
+ }
+ }
+
+ if (Condition != null)
+ Condition.SetParent(null);
+
+ if (Increment != null)
+ {
+ foreach (var expression in Increment)
+ {
+ expression.SetParent(null);
+ }
+ }
+
+ Block.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/IfStatement.cs b/ScriptConverter/Ast/Statements/IfStatement.cs
new file mode 100644
index 0000000..572c646
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/IfStatement.cs
@@ -0,0 +1,53 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class IfStatement : Statement
+ {
+ public class Branch
+ {
+ public Expression Condition { get; private set; }
+ public BlockStatement Block { get; private set; }
+
+ public Branch(Expression condition, BlockStatement block)
+ {
+ Condition = condition;
+ Block = block;
+ }
+ }
+
+ public ReadOnlyCollection Branches { get; private set; }
+ public Branch DefaultBranch { get; private set; }
+
+ public IfStatement(ScriptToken start, ScriptToken end, List branches, Branch defaultBranch)
+ : base(start, end)
+ {
+ Branches = branches.AsReadOnly();
+ DefaultBranch = defaultBranch;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ foreach (var branch in Branches)
+ {
+ branch.Condition.SetParent(null);
+ branch.Block.SetParent(this);
+ }
+
+ if (DefaultBranch != null)
+ {
+ DefaultBranch.Block.SetParent(this);
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/NakedStatement.cs b/ScriptConverter/Ast/Statements/NakedStatement.cs
new file mode 100644
index 0000000..c451288
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/NakedStatement.cs
@@ -0,0 +1,27 @@
+using ScriptConverter.Ast.Expressions;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class NakedStatement : Statement
+ {
+ public Expression Expression { get; private set; }
+
+ public NakedStatement(Expression expression)
+ : base(expression.Start, expression.End)
+ {
+ Expression = expression;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ Expression.SetParent(null);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/ReturnStatement.cs b/ScriptConverter/Ast/Statements/ReturnStatement.cs
new file mode 100644
index 0000000..6c80980
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/ReturnStatement.cs
@@ -0,0 +1,29 @@
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class ReturnStatement : Statement
+ {
+ public Expression Value { get; private set; }
+
+ public ReturnStatement(ScriptToken start, ScriptToken end, Expression value)
+ : base(start, end)
+ {
+ Value = value;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ if (Value != null)
+ Value.SetParent(null);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/Statement.cs b/ScriptConverter/Ast/Statements/Statement.cs
new file mode 100644
index 0000000..036af75
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/Statement.cs
@@ -0,0 +1,25 @@
+using System;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ abstract class Statement
+ {
+ public readonly ScriptToken Start;
+ public readonly ScriptToken End;
+ public Statement Parent { get; protected set; }
+
+ protected Statement(ScriptToken start, ScriptToken end = null)
+ {
+ if (start == null)
+ throw new ArgumentNullException("start");
+
+ Start = start;
+ End = end ?? start;
+ }
+
+ public abstract TStmt Accept(IAstVisitor visitor);
+
+ public abstract void SetParent(Statement parent);
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/SwitchStatement.cs b/ScriptConverter/Ast/Statements/SwitchStatement.cs
new file mode 100644
index 0000000..f14316f
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/SwitchStatement.cs
@@ -0,0 +1,55 @@
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class SwitchStatement : Statement
+ {
+ public class Branch
+ {
+ public ReadOnlyCollection Conditions { get; private set; }
+ public BlockStatement Block { get; private set; }
+
+ public Branch(List conditions, BlockStatement block)
+ {
+ Conditions = conditions.AsReadOnly();
+ Block = block;
+ }
+ }
+
+ public Expression Expression { get; private set; }
+ public ReadOnlyCollection Branches { get; private set; }
+
+ public SwitchStatement(ScriptToken start, ScriptToken end, Expression expression, List branches)
+ : base(start, end)
+ {
+ Expression = expression;
+ Branches = branches.AsReadOnly();
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ Expression.SetParent(null);
+
+ foreach (var branch in Branches)
+ {
+ foreach (var expression in branch.Conditions)
+ {
+ if (expression != null)
+ expression.SetParent(null);
+ }
+
+ branch.Block.SetParent(this);
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/ThrowStatement.cs b/ScriptConverter/Ast/Statements/ThrowStatement.cs
new file mode 100644
index 0000000..d97149a
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/ThrowStatement.cs
@@ -0,0 +1,28 @@
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class ThrowStatement : Statement
+ {
+ public Expression Value { get; private set; }
+
+ public ThrowStatement(ScriptToken start, Expression value)
+ : base(start, value.End)
+ {
+ Value = value;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ Value.SetParent(null);
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/TryStatement.cs b/ScriptConverter/Ast/Statements/TryStatement.cs
new file mode 100644
index 0000000..e90b1b9
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/TryStatement.cs
@@ -0,0 +1,53 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class TryStatement : Statement
+ {
+ public class Branch
+ {
+ public ScriptType Type { get; private set; }
+ public string Name { get; private set; }
+ public BlockStatement Block { get; private set; }
+
+ public Branch(ScriptType type, string name, BlockStatement block)
+ {
+ Type = type;
+ Name = name;
+ Block = block;
+ }
+ }
+
+ public BlockStatement Block { get; private set; }
+ public ReadOnlyCollection Branches { get; private set; }
+
+ public TryStatement(ScriptToken start, ScriptToken end, BlockStatement block, List branches) : base(start, end)
+ {
+ if (branches.Count < 1)
+ throw new ArgumentException("need at least 1 branch", "branches");
+
+ Block = block;
+ Branches = branches.AsReadOnly();
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ Block.SetParent(this);
+
+ foreach (var branch in Branches)
+ {
+ branch.Block.SetParent(this);
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/VariableStatement.cs b/ScriptConverter/Ast/Statements/VariableStatement.cs
new file mode 100644
index 0000000..874eaad
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/VariableStatement.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class VariableStatement : Statement
+ {
+ public class Definition
+ {
+ public ScriptType Type { get; private set; }
+ public string Name { get; private set; }
+ public Expression Value { get; private set; }
+
+ public Definition(ScriptType type, string name, Expression value)
+ {
+ Type = type;
+ Name = name;
+ Value = value;
+ }
+ }
+
+ public ScriptType BaseType { get; private set; }
+ public bool Final { get; private set; }
+ public ReadOnlyCollection Definitions { get; private set; }
+
+ public VariableStatement(ScriptToken start, ScriptToken end, ScriptType baseType, bool final, List definitions)
+ : base(start, end)
+ {
+ if (definitions.Count < 1)
+ throw new ArgumentException("need at least 1 definition", "definitions");
+
+ BaseType = baseType;
+ Final = final;
+ Definitions = definitions.AsReadOnly();
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ foreach (var definition in Definitions)
+ {
+ if (definition.Value != null)
+ definition.Value.SetParent(null);
+ }
+ }
+ }
+}
diff --git a/ScriptConverter/Ast/Statements/WhileStatement.cs b/ScriptConverter/Ast/Statements/WhileStatement.cs
new file mode 100644
index 0000000..59f8bf4
--- /dev/null
+++ b/ScriptConverter/Ast/Statements/WhileStatement.cs
@@ -0,0 +1,31 @@
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter.Ast.Statements
+{
+ class WhileStatement : Statement
+ {
+ public Expression Condition { get; private set; }
+ public BlockStatement Block { get; private set; }
+
+ public WhileStatement(ScriptToken start, ScriptToken end, Expression condition, BlockStatement block)
+ : base(start, end)
+ {
+ Condition = condition;
+ Block = block;
+ }
+
+ public override TStmt Accept(IAstVisitor visitor)
+ {
+ return visitor.Visit(this);
+ }
+
+ public override void SetParent(Statement parent)
+ {
+ Parent = parent;
+
+ Condition.SetParent(null);
+ Block.SetParent(this);
+ }
+ }
+}
diff --git a/ScriptConverter/AstPrinter.cs b/ScriptConverter/AstPrinter.cs
new file mode 100644
index 0000000..609874c
--- /dev/null
+++ b/ScriptConverter/AstPrinter.cs
@@ -0,0 +1,1136 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using ScriptConverter.Ast;
+using ScriptConverter.Ast.Declarations;
+using ScriptConverter.Ast.Expressions;
+using ScriptConverter.Ast.Statements;
+using ScriptConverter.Parser;
+
+namespace ScriptConverter
+{
+ // TODO: make == to .equals() conversion use type info
+
+ class AstPrinter : IAstVisitor
+ {
+ private IndentTextWriter _writer;
+ private readonly string _package;
+ private readonly string _name;
+ private readonly bool _isLib;
+
+ public AstPrinter(string package, string name, bool isLib)
+ : this(Console.Out, package, name, isLib)
+ {
+
+ }
+
+ public AstPrinter(TextWriter writer, string package, string name, bool isLib)
+ {
+ _writer = new IndentTextWriter(writer, " ");
+ _package = package;
+ _name = name;
+ _isLib = isLib;
+
+ _scopeStack = new Stack>();
+ }
+
+ public int Visit(Document document)
+ {
+ _writer.Write("package ");
+ _writer.Write(_package);
+ _writer.WriteLine(";");
+ _writer.WriteLine();
+
+ _writer.WriteLine("import script.*;");
+ _writer.WriteLine("import script.base_class.*;");
+ _writer.WriteLine("import script.combat_engine.*;");
+ _writer.WriteLine("import java.util.Arrays;");
+ _writer.WriteLine("import java.util.Hashtable;");
+ _writer.WriteLine("import java.util.Vector;");
+ _writer.WriteLine("import script.base_script;");
+ _writer.WriteLine();
+
+ foreach (var include in document.Declarations.OfType())
+ {
+ include.Accept(this);
+ }
+
+ _writer.WriteLine();
+
+ var inherits = document.Declarations.OfType().SingleOrDefault();
+
+ _writer.Write("public class ");
+ _writer.Write(_name);
+
+ if (_name == "base_script")
+ {
+ _writer.Write(" extends script.base_class");
+ }
+ else
+ {
+ _writer.Write(" extends script.");
+ _writer.Write(inherits != null ? inherits.Name : "base_script");
+ }
+
+ _writer.WriteLine();
+ _writer.WriteLine("{");
+ _writer.Indent++;
+
+ _writer.Write("public ");
+ _writer.Write(_name);
+ _writer.WriteLine("() { }");
+ _writer.WriteLine();
+
+ PushScope();
+
+ foreach (var constant in document.Declarations.OfType())
+ {
+ constant.SetParent();
+ constant.Accept(this);
+ }
+
+ _writer.WriteLine();
+
+ foreach (var method in document.Declarations.OfType())
+ {
+ method.SetParent();
+ method.Accept(this);
+ _writer.WriteLine();
+ }
+
+ PopScope();
+
+ _writer.Indent--;
+ _writer.WriteLine("}");
+
+ _writer.WriteLine();
+ return 0;
+ }
+
+ #region Declarations
+
+ public int Visit(FieldDeclaration declaration)
+ {
+ Declare(declaration.Name, declaration.Type);
+
+ if (declaration.IsPublic)
+ _writer.Write("public ");
+
+ if (declaration.IsConstant)
+ _writer.Write("static final ");
+
+ _writer.Write(declaration.Type);
+ _writer.Write(" ");
+ _writer.Write(declaration.Name);
+ _writer.Write(" = ");
+ declaration.Value.Accept(this);
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ public int Visit(IncludeDeclaration declaration)
+ {
+ _writer.Write("import ");
+
+ if (!declaration.Name.StartsWith("java."))
+ _writer.Write("script.");
+
+ _writer.Write(declaration.Name);
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ public int Visit(InheritsDeclaration declaration)
+ {
+ throw new NotSupportedException();
+ }
+
+ public int Visit(MethodDeclaration declaration)
+ {
+ List extraParameters;
+ var isEventHandler = EventHandlers.TryGetValue(declaration.ReturnType.ToString(), out extraParameters);
+
+ var extras = isEventHandler ? extraParameters : Enumerable.Empty();
+ var parameters = extras.Concat(declaration.Parameters).ToList();
+
+ _methodReturnType = declaration.ReturnType;
+ _methodParameters = parameters.ToDictionary(p => p.Name, p => p.Type);
+
+ _writer.Write("public ");
+
+ if (_isLib)
+ _writer.Write("static ");
+
+ _writer.Write(isEventHandler ? "int" : declaration.ReturnType.ToString());
+ _writer.Write(" ");
+ _writer.Write(declaration.Name);
+ _writer.Write("(");
+
+ var first = true;
+ foreach (var parameter in parameters)
+ {
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+
+ _writer.Write(parameter.Type);
+ _writer.Write(" ");
+ _writer.Write(parameter.Name);
+ }
+
+ _writer.WriteLine(") throws InterruptedException");
+
+ declaration.Block.Accept(this);
+
+ return 0;
+ }
+
+ #endregion
+
+ #region Statements
+
+ public int Visit(BlockStatement statement)
+ {
+ if (!statement.IsSwitch)
+ {
+ _writer.WriteLine("{");
+ PushScope();
+ }
+
+ _writer.Indent++;
+
+ foreach (var subStatement in statement.Statements)
+ {
+ var nakedStmt = subStatement as NakedStatement;
+ if (nakedStmt != null)
+ nakedStmt.Expression.SetParent(null);
+
+ subStatement.Accept(this);
+ }
+
+ _writer.Indent--;
+
+ if (!statement.IsSwitch)
+ {
+ PopScope();
+ _writer.WriteLine("}");
+ }
+
+ return 0;
+ }
+
+ public int Visit(BreakStatement statement)
+ {
+ _writer.WriteLine("break;");
+ return 0;
+ }
+
+ public int Visit(ContinueStatement statement)
+ {
+ _writer.WriteLine("continue;");
+ return 0;
+ }
+
+ public int Visit(DoStatement statement)
+ {
+ _writer.WriteLine("do");
+ statement.Block.Accept(this);
+ _writer.Write("while (");
+ statement.Condition.Accept(this);
+ _writer.WriteLine(");");
+ return 0;
+ }
+
+ public int Visit(EmptyStatement statement)
+ {
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ public int Visit(ForStatement statement)
+ {
+ _writer.Write("for (");
+
+ if (statement.Initializers != null)
+ {
+ var first = true;
+ foreach (var initializer in statement.Initializers)
+ {
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+
+ var initVariable = initializer as VariableStatement;
+ if (initVariable != null)
+ {
+ if (initVariable.Final)
+ throw new Exception("why");
+
+ _writer.Write(initVariable.BaseType);
+ _writer.Write(" ");
+
+ var firstVar = true;
+ foreach (var definition in initVariable.Definitions)
+ {
+ if (!firstVar)
+ _writer.Write(", ");
+
+ firstVar = false;
+
+ _writer.Write(definition.Name);
+
+ var i = initVariable.BaseType.ArrayDimensions;
+ while (definition.Type.ArrayDimensions > i++)
+ {
+ _writer.Write("[]");
+ }
+
+ if (definition.Value != null)
+ {
+ _writer.Write(" = ");
+ definition.Value.Accept(this);
+ }
+ }
+ }
+
+ var initExpr = initializer as NakedStatement;
+ if (initExpr != null)
+ {
+ initExpr.Expression.Accept(this);
+ }
+ }
+ }
+
+ _writer.Write("; ");
+
+ if (statement.Condition != null)
+ statement.Condition.Accept(this);
+
+ _writer.Write("; ");
+
+ if (statement.Increment != null)
+ {
+ var first = true;
+ foreach (var increment in statement.Increment)
+ {
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+ increment.Accept(this);
+ }
+ }
+
+ _writer.WriteLine(")");
+ statement.Block.Accept(this);
+ return 0;
+ }
+
+ public int Visit(IfStatement statement)
+ {
+ for (var i = 0; i < statement.Branches.Count; i++)
+ {
+ var branch = statement.Branches[i];
+
+ _writer.Write(i == 0 ? "if" : "else if");
+
+ _writer.Write(" (");
+ branch.Condition.Accept(this);
+ _writer.WriteLine(")");
+
+ branch.Block.Accept(this);
+ }
+
+ if (statement.DefaultBranch != null)
+ {
+ _writer.WriteLine("else ");
+ statement.DefaultBranch.Block.Accept(this);
+ }
+
+ return 0;
+ }
+
+ public int Visit(NakedStatement statement)
+ {
+ statement.Expression.Accept(this);
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ public int Visit(ReturnStatement statement)
+ {
+ if (statement.Value != null)
+ {
+ var valueIdentifier = statement.Value as IdentifierExpression;
+ if (valueIdentifier != null)
+ {
+ var type = GetType(valueIdentifier.Name);
+ if (type != null && type.IsResizable)
+ {
+ if (_methodReturnType != null && _methodReturnType.IsArray && !_methodReturnType.IsResizable)
+ {
+ var result = ResizableToArray(valueIdentifier.Name, _methodReturnType);
+ _writer.WriteLine("return {0};", result);
+ return 0;
+ }
+ }
+ }
+
+ _writer.Write("return ");
+ statement.Value.Accept(this);
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ _writer.WriteLine("return;");
+ return 0;
+ }
+
+ public int Visit(SwitchStatement statement)
+ {
+ _writer.Write("switch (");
+ statement.Expression.Accept(this);
+ _writer.WriteLine(")");
+
+ _writer.WriteLine("{");
+ _writer.Indent++;
+
+ for (var i = 0; i < statement.Branches.Count; i++)
+ {
+ var branch = statement.Branches[i];
+
+ foreach (var condition in branch.Conditions)
+ {
+ if (condition == null)
+ {
+ _writer.WriteLine("default:");
+ continue;
+ }
+
+ _writer.Write("case ");
+ condition.Accept(this);
+ _writer.WriteLine(":");
+ }
+
+ branch.Block.Accept(this);
+
+ if (i < statement.Branches.Count - 1)
+ _writer.WriteLine();
+ }
+
+ _writer.WriteLine();
+
+ _writer.Indent--;
+ _writer.WriteLine("}");
+ return 0;
+ }
+
+ public int Visit(ThrowStatement statement)
+ {
+ _writer.Write("throw ");
+ statement.Value.Accept(this);
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ public int Visit(TryStatement statement)
+ {
+ _writer.WriteLine("try");
+ statement.Block.Accept(this);
+
+ foreach (var branch in statement.Branches)
+ {
+ _writer.Write("catch (");
+ _writer.Write(branch.Type);
+ _writer.Write(" ");
+ _writer.Write(branch.Name);
+ _writer.WriteLine(")");
+ branch.Block.Accept(this);
+ }
+
+ return 0;
+ }
+
+ public int Visit(VariableStatement statement)
+ {
+ if (statement.Definitions.Count == 1)
+ {
+ var def = statement.Definitions[0];
+
+ var targetType = def.Type;
+
+ var valueIdent = def.Value as IdentifierExpression;
+ if (valueIdent != null)
+ {
+ var valueType = GetType(valueIdent.Name);
+ if (valueType != null)
+ {
+ if (targetType.IsResizable && (valueType.IsArray && !valueType.IsResizable))
+ {
+ Declare(def.Name, def.Type);
+ // Vector def = arrayIdent;
+
+ var result = ArrayToResizable(valueIdent.Name);
+ _writer.WriteLine("Vector {0} = {1};", def.Name, result);
+
+ return 0;
+ }
+
+ if ((targetType.IsArray && !targetType.IsResizable) && valueType.IsResizable)
+ {
+ Declare(def.Name, def.Type);
+ // arrayType[] def = vectorIdent;
+
+ var result = ResizableToArray(valueIdent.Name, def.Type);
+ _writer.WriteLine("{0} {1} = {2};", targetType, def.Name, result);
+
+ return 0;
+ }
+ }
+ }
+
+ var valueCast = def.Value as CastExpression;
+ if (valueCast != null && targetType.IsResizable)
+ {
+ var valueType = valueCast.Type;
+
+ if (valueType.IsResizable && targetType.Name == valueType.Name)
+ {
+ valueType = new ScriptType(valueType.Name, valueType.ArrayDimensions);
+
+ Declare(def.Name, def.Type);
+ // resizable arrayType[] def = (resizable arrayType[])arrayExpr;
+
+ var result = ArrayToResizable(valueType, valueCast.Value);
+ _writer.WriteLine("Vector {0} = {1};", def.Name, result);
+
+ return 0;
+ }
+ }
+ }
+
+ if (statement.Final)
+ _writer.Write("final ");
+
+ if (statement.BaseType.IsResizable)
+ {
+ var def = statement.Definitions.Single();
+
+ Declare(def.Name, def.Type);
+
+ _writer.Write("Vector ");
+ _writer.Write(def.Name);
+
+ if (def.Value == null)
+ {
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ _writer.Write(" = ");
+
+ if (def.Value is NewExpression)
+ {
+ _writer.WriteLine("new Vector();");
+ }
+ else
+ {
+ def.Value.Accept(this);
+ _writer.WriteLine(";");
+ }
+
+ return 0;
+ }
+
+ _writer.Write(statement.BaseType);
+ _writer.Write(" ");
+
+ var first = true;
+ foreach (var definition in statement.Definitions)
+ {
+ Declare(definition.Name, definition.Type);
+
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+
+ _writer.Write(definition.Name);
+
+ var i = statement.BaseType.ArrayDimensions;
+ while (definition.Type.ArrayDimensions > i++)
+ {
+ _writer.Write("[]");
+ }
+
+ if (definition.Value != null)
+ {
+ _writer.Write(" = ");
+ definition.Value.Accept(this);
+ }
+ }
+
+ _writer.WriteLine(";");
+ return 0;
+ }
+
+ public int Visit(WhileStatement statement)
+ {
+ _writer.Write("while (");
+ statement.Condition.Accept(this);
+ _writer.WriteLine(")");
+ statement.Block.Accept(this);
+ return 0;
+ }
+
+ #endregion
+
+ #region Expressions
+
+ public int Visit(ArrayInitializerExpression expression)
+ {
+ _writer.Write("{ ");
+
+ var first = true;
+ foreach (var value in expression.Values)
+ {
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+ value.Accept(this);
+ }
+
+ _writer.Write(" }");
+ return 0;
+ }
+
+ public int Visit(BinaryOperatorExpression expression)
+ {
+ if (expression.Operation == ScriptTokenType.EqualTo ||
+ expression.Operation == ScriptTokenType.NotEqualTo)
+ {
+ var leftString = expression.Left as StringExpression;
+ var rightString = expression.Right as StringExpression;
+
+ if ((leftString != null && !leftString.IsSingleQuote) || (rightString != null && !rightString.IsSingleQuote))
+ {
+ if (expression.Operation == ScriptTokenType.NotEqualTo)
+ _writer.Write("!");
+
+ expression.Left.Accept(this);
+ _writer.Write(".equals(");
+ expression.Right.Accept(this);
+ _writer.Write(")");
+
+ return 0;
+ }
+ }
+
+ if (expression.Operation == ScriptTokenType.Assign)
+ {
+ var leftIndexer = expression.Left as IndexerExpression;
+ if (leftIndexer != null)
+ {
+ var leftIdentifier = leftIndexer.Left as IdentifierExpression;
+ if (leftIdentifier != null)
+ {
+ var type = GetType(leftIdentifier.Name);
+ if (type != null && type.IsResizable)
+ {
+ _writer.Write(leftIdentifier.Name);
+ _writer.Write(".set(");
+ leftIndexer.Index.Accept(this);
+ _writer.Write(", ");
+ expression.Right.Accept(this);
+ _writer.Write(")");
+
+ return 0;
+ }
+ }
+ }
+
+ var leftIdent = expression.Left as IdentifierExpression;
+ var rightIdent = expression.Right as IdentifierExpression;
+ if (expression.Parent == null && leftIdent != null && rightIdent != null)
+ {
+ var leftType = GetType(leftIdent.Name);
+ var rightType = GetType(rightIdent.Name);
+ if (leftType != null && rightType != null)
+ {
+ if (leftType.IsResizable && (rightType.IsArray && !rightType.IsResizable))
+ {
+ // =
+
+ var result = ArrayToResizable(rightIdent.Name);
+ _writer.Write("{0} = {1}", leftIdent.Name, result);
+
+ return 0;
+ }
+
+ if ((leftType.IsArray && !leftType.IsResizable) && rightType.IsResizable)
+ {
+ // =
+
+ var result = ResizableToArray(rightIdent.Name, leftType);
+ _writer.Write("{0} = {1}", leftIdent.Name, result);
+
+ return 0;
+ }
+ }
+ }
+ }
+
+ var needParens = expression.Parent != null;
+
+ if (needParens)
+ _writer.Write("(");
+
+ expression.Left.Accept(this);
+ _writer.Write(" ");
+ _writer.Write(BinaryOperatorMap[expression.Operation]);
+ _writer.Write(" ");
+ expression.Right.Accept(this);
+
+ if (needParens)
+ _writer.Write(")");
+
+ return 0;
+ }
+
+ public int Visit(BoolExpression expression)
+ {
+ _writer.Write(expression.Value ? "true" : "false");
+ return 0;
+ }
+
+ public int Visit(CallExpression expression)
+ {
+ expression.Left.Accept(this);
+ _writer.Write("(");
+
+ var first = true;
+ foreach (var parameter in expression.Parameters)
+ {
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+ parameter.Accept(this);
+ }
+
+ _writer.Write(")");
+ return 0;
+ }
+
+ public int Visit(CastExpression expression)
+ {
+ _writer.Write("(");
+ _writer.Write("(");
+ _writer.Write(expression.Type);
+ _writer.Write(")");
+ expression.Value.Accept(this);
+ _writer.Write(")");
+ return 0;
+ }
+
+ public int Visit(FieldExpression expression)
+ {
+ if (expression.Name == "length")
+ {
+ var leftIdentifier = expression.Left as IdentifierExpression;
+ if (leftIdentifier != null)
+ {
+ var type = GetType(leftIdentifier.Name);
+ if (type != null && type.IsResizable)
+ {
+ _writer.Write(leftIdentifier.Name);
+ _writer.Write(".size()");
+ return 0;
+ }
+ }
+ }
+ expression.Left.Accept(this);
+ _writer.Write(".");
+ _writer.Write(expression.Name);
+ return 0;
+ }
+
+ public int Visit(IdentifierExpression expression)
+ {
+ _writer.Write(expression.Name);
+ return 0;
+ }
+
+ public int Visit(IndexerExpression expression)
+ {
+ var leftIdentifier = expression.Left as IdentifierExpression;
+ if (leftIdentifier != null)
+ {
+ var type = GetType(leftIdentifier.Name);
+ if (type != null && type.IsResizable)
+ {
+ _writer.Write("((");
+ _writer.Write(type.Name);
+ _writer.Write(")");
+ _writer.Write(leftIdentifier.Name);
+ _writer.Write(".get(");
+ expression.Index.Accept(this);
+ _writer.Write("))");
+
+ return 0;
+ }
+ }
+
+ expression.Left.Accept(this);
+ _writer.Write("[");
+ expression.Index.Accept(this);
+ _writer.Write("]");
+ return 0;
+ }
+
+ public int Visit(InstanceOfExpression expression)
+ {
+ _writer.Write("(");
+ expression.Left.Accept(this);
+ _writer.Write(" instanceof ");
+
+ var typeName = expression.Type.ToString();
+
+ switch (typeName)
+ {
+ case "int":
+ typeName = "Integer";
+ break;
+ case "float":
+ typeName = "Float";
+ break;
+ case "boolean":
+ typeName = "Boolean";
+ break;
+ }
+
+ _writer.Write(typeName);
+ _writer.Write(")");
+ return 0;
+ }
+
+ public int Visit(NewExpression expression)
+ {
+ _writer.Write("new ");
+ _writer.Write(expression.Type);
+ _writer.Write(expression.IsArray ? "[" : "(");
+
+ {
+ var first = true;
+ foreach (var parameter in expression.Parameters)
+ {
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+ parameter.Accept(this);
+ }
+ }
+
+ _writer.Write(expression.IsArray ? "]" : ")");
+
+ if (expression.IsArray)
+ {
+ for (var i = 1; i < expression.ArrayDimensions; i++)
+ {
+ _writer.Write("[]");
+ }
+ }
+
+ if (expression.Initializer != null)
+ {
+ _writer.Write("{ ");
+
+ var first = true;
+ foreach (var value in expression.Initializer)
+ {
+ if (!first)
+ _writer.Write(", ");
+
+ first = false;
+ value.Accept(this);
+ }
+
+ _writer.Write(" }");
+ }
+
+ return 0;
+ }
+
+ public int Visit(NullExpression expression)
+ {
+ _writer.Write("null");
+ return 0;
+ }
+
+ public int Visit(NumberExpression expression)
+ {
+ _writer.Write(expression.Value);
+ return 0;
+ }
+
+ public int Visit(PostfixOperatorExpression expression)
+ {
+ expression.Left.Accept(this);
+ _writer.Write(PostfixOperatorMap[expression.Operation]);
+ return 0;
+ }
+
+ public int Visit(PrefixOperatorExpression expression)
+ {
+ _writer.Write(PrefixOperatorMap[expression.Operation]);
+ expression.Right.Accept(this);
+ return 0;
+ }
+
+ public int Visit(StringExpression expression)
+ {
+ _writer.Write(expression.IsSingleQuote ? "\'" : "\"");
+ _writer.Write(expression.Value);
+ _writer.Write(expression.IsSingleQuote ? "\'" : "\"");
+ return 0;
+ }
+
+ public int Visit(TernaryExpression expression)
+ {
+ _writer.Write("(");
+ expression.Condition.Accept(this);
+ _writer.Write(" ? ");
+ expression.TrueExpression.Accept(this);
+ _writer.Write(" : ");
+ expression.FalseExpression.Accept(this);
+ _writer.Write(")");
+ return 0;
+ }
+
+ #endregion
+
+ #region Resizable Conversions
+
+ private static int _resizableIndex;
+
+ private string ResizableToArray(ScriptType inputType, Expression inputExpression, ScriptType arrayType)
+ {
+ var temp = "__" + _resizableIndex++ + "_expr";
+
+ _writer.Write("{0} {1} = ", inputType, temp);
+ inputExpression.Accept(this);
+ _writer.WriteLine(";");
+
+ return ResizableToArray(temp, arrayType);
+ }
+
+ private string ArrayToResizable(ScriptType inputType, Expression inputExpression)
+ {
+ var temp = "__" + _resizableIndex++ + "_expr";
+
+ _writer.Write("{0} {1} = ", inputType, temp);
+ inputExpression.Accept(this);
+ _writer.WriteLine(";");
+
+ return ArrayToResizable(temp);
+ }
+
+ private string ResizableToArray(string inputIdentifier, ScriptType arrayType)
+ {
+ /*
+ arrayType[] __array = new arrayType[0];
+ if (input != null)
+ {
+ __array = new arrayType[input.size()];
+ for (int __i = 0; __i < input.size(); ++__i)
+ {
+ __array[__i] = (arrayType)input.get(__i);
+ }
+ }
+ */
+
+ var prefix = "__" + (_resizableIndex++) + "_";
+ var arrayTemp = prefix + "array";
+ var loopTemp = prefix + "i";
+
+ _writer.WriteLine("{1}[] {0} = new {1}[0];", arrayTemp, arrayType.Name);
+ _writer.WriteLine("if ({0} != null)", inputIdentifier);
+ _writer.WriteLine("{");
+ _writer.Indent++;
+ _writer.WriteLine("{0} = new {1}[{2}.size()];", arrayTemp, arrayType.Name, inputIdentifier);
+ _writer.WriteLine("for (int {0} = 0; {0} < {1}.size(); ++{0})", loopTemp, inputIdentifier);
+ _writer.WriteLine("{");
+ _writer.Indent++;
+ _writer.WriteLine("{0}[{1}] = ({2}){3}.get({1});", arrayTemp, loopTemp, arrayType.Name, inputIdentifier);
+ _writer.Indent--;
+ _writer.WriteLine("}");
+ _writer.Indent--;
+ _writer.WriteLine("}");
+
+ return arrayTemp;
+ }
+
+ private string ArrayToResizable(string inputIdentifier)
+ {
+ /*
+ Vector __array = new Vector();
+ if (input != null)
+ {
+ __array.setSize(input.length);
+ for (int __i = 0; __i < input.length; ++__i)
+ {
+ __array.set(__i, input[__i]);
+ }
+ }
+ */
+
+ var prefix = "__" + (_resizableIndex++) + "_";
+ var vectorTemp = prefix + "vector";
+ var loopTemp = prefix + "i";
+
+ _writer.WriteLine("Vector {0} = new Vector();", vectorTemp);
+ _writer.WriteLine("if ({0} != null)", inputIdentifier);
+ _writer.WriteLine("{");
+ _writer.Indent++;
+ _writer.WriteLine("{0}.setSize({1}.length);", vectorTemp, inputIdentifier);
+ _writer.WriteLine("for (int {0} = 0; {0} < {1}.length; ++{0})", loopTemp, inputIdentifier);
+ _writer.WriteLine("{");
+ _writer.Indent++;
+ _writer.WriteLine("{0}.set({1}, {2}[{1}]);", vectorTemp, loopTemp, inputIdentifier);
+ _writer.Indent--;
+ _writer.WriteLine("}");
+ _writer.Indent--;
+ _writer.WriteLine("}");
+
+ return vectorTemp;
+ }
+
+ #endregion
+
+ #region Scope
+
+ private ScriptType _methodReturnType;
+ private Dictionary _methodParameters;
+ private Stack> _scopeStack;
+
+ private ScriptType GetType(string name)
+ {
+ ScriptType type = null;
+
+ if (_methodParameters != null && _methodParameters.TryGetValue(name, out type))
+ return type;
+
+ if (_scopeStack.Any(scope => scope.TryGetValue(name, out type)))
+ return type;
+
+ // TODO: hopefully nothing inherits a resizable type...
+ return null;
+ throw new Exception("undefined variable: " + name);
+ }
+
+ private void Declare(string name, ScriptType type)
+ {
+ _scopeStack.Peek().Add(name, type);
+ }
+
+ private void PushScope()
+ {
+ _scopeStack.Push(new Dictionary());
+ }
+
+ private void PopScope()
+ {
+ _scopeStack.Pop();
+ }
+
+ #endregion
+
+ #region Operator Maps
+
+ private static readonly Dictionary BinaryOperatorMap = new Dictionary
+ {
+ { ScriptTokenType.Add, "+" },
+ { ScriptTokenType.Subtract, "-" },
+ { ScriptTokenType.Multiply, "*" },
+ { ScriptTokenType.Divide, "/" },
+ { ScriptTokenType.Remainder, "%" },
+ { ScriptTokenType.BitwiseShiftLeft, "<<" },
+ { ScriptTokenType.BitwiseShiftRight, ">>" },
+ { ScriptTokenType.BitwiseAnd, "&" },
+ { ScriptTokenType.BitwiseOr, "|" },
+ { ScriptTokenType.BitwiseXor, "^" },
+ { ScriptTokenType.LogicalAnd, "&&" },
+ { ScriptTokenType.LogicalOr, "||" },
+ { ScriptTokenType.EqualTo, "==" },
+ { ScriptTokenType.NotEqualTo, "!=" },
+ { ScriptTokenType.GreaterThan, ">" },
+ { ScriptTokenType.GreaterThanOrEqual, ">=" },
+ { ScriptTokenType.LessThan, "<" },
+ { ScriptTokenType.LessThanOrEqual, "<=" },
+ { ScriptTokenType.Assign, "=" },
+ { ScriptTokenType.AddAssign, "+=" },
+ { ScriptTokenType.SubtractAssign, "-=" },
+ { ScriptTokenType.MultiplyAssign, "*=" },
+ { ScriptTokenType.DivideAssign, "/=" },
+ { ScriptTokenType.RemainderAssign, "%=" },
+ { ScriptTokenType.BitwiseShiftLeftAssign, "<<=" },
+ { ScriptTokenType.BitwiseShiftRightAssign, ">>=" },
+ { ScriptTokenType.BitwiseAndAssign, "&=" },
+ { ScriptTokenType.BitwiseOrAssign, "|=" },
+ { ScriptTokenType.BitwiseXorAssign, "^=" },
+ };
+
+ private static readonly Dictionary PostfixOperatorMap = new Dictionary
+ {
+ { ScriptTokenType.Increment, "++" },
+ { ScriptTokenType.Decrement, "--" },
+ };
+
+ private static readonly Dictionary PrefixOperatorMap = new Dictionary
+ {
+ { ScriptTokenType.Add, "+" },
+ { ScriptTokenType.Subtract, "-" },
+ { ScriptTokenType.BitwiseNot, "~" },
+ { ScriptTokenType.LogicalNot, "!" },
+ { ScriptTokenType.Increment, "++" },
+ { ScriptTokenType.Decrement, "--" },
+ };
+
+ #endregion
+
+ #region Event Handlers
+
+ private static readonly Dictionary> EventHandlers = new Dictionary>
+ {
+ {
+ "messageHandler", new List
+ {
+ new MethodDeclaration.Parameter(new ScriptType("obj_id"), "self"),
+ new MethodDeclaration.Parameter(new ScriptType("dictionary"), "params"),
+ }
+ },
+ {
+ "commandHandler", new List
+ {
+ new MethodDeclaration.Parameter(new ScriptType("obj_id"), "self"),
+ new MethodDeclaration.Parameter(new ScriptType("obj_id"), "target"),
+ new MethodDeclaration.Parameter(new ScriptType("String"), "params"),
+ new MethodDeclaration.Parameter(new ScriptType("float"), "defaultTime"),
+ }
+ },
+ {
+ "trigger", new List
+ {
+ new MethodDeclaration.Parameter(new ScriptType("obj_id"), "self"),
+ }
+ },
+ };
+
+ #endregion
+ }
+}
diff --git a/ScriptConverter/CoreAnnotations.cs b/ScriptConverter/CoreAnnotations.cs
new file mode 100644
index 0000000..1e0fb02
--- /dev/null
+++ b/ScriptConverter/CoreAnnotations.cs
@@ -0,0 +1,406 @@
+/*
+ * Copyright 2007-2011 JetBrains s.r.o.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Collections.Generic;
+
+namespace JetBrains.Annotations
+{
+ ///
+ /// Indicates that marked element should be localized or not.
+ ///
+ [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
+ public sealed class LocalizationRequiredAttribute : Attribute
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// true if a element should be localized; otherwise, false.
+ public LocalizationRequiredAttribute(bool required)
+ {
+ Required = required;
+ }
+
+ ///
+ /// Gets a value indicating whether a element should be localized.
+ /// true if a element should be localized; otherwise, false.
+ ///
+ public bool Required { get; set; }
+
+ ///
+ /// Returns whether the value of the given object is equal to the current .
+ ///
+ /// The object to test the value equality of.
+ ///
+ /// true if the value of the given object is equal to that of the current; otherwise, false.
+ ///
+ public override bool Equals(object obj)
+ {
+ var attribute = obj as LocalizationRequiredAttribute;
+ return attribute != null && attribute.Required == Required;
+ }
+
+ ///
+ /// Returns the hash code for this instance.
+ ///
+ /// A hash code for the current .
+ public override int GetHashCode()
+ {
+ return base.GetHashCode();
+ }
+ }
+
+ ///
+ /// Indicates that marked method builds string by format pattern and (optional) arguments.
+ /// Parameter, which contains format string, should be given in constructor.
+ /// The format string should be in -like form
+ ///
+ [AttributeUsage(AttributeTargets.Constructor | AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
+ public sealed class StringFormatMethodAttribute : Attribute
+ {
+ private readonly string myFormatParameterName;
+
+ ///
+ /// Initializes new instance of StringFormatMethodAttribute
+ ///
+ /// Specifies which parameter of an annotated method should be treated as format-string
+ public StringFormatMethodAttribute(string formatParameterName)
+ {
+ myFormatParameterName = formatParameterName;
+ }
+
+ ///
+ /// Gets format parameter name
+ ///
+ public string FormatParameterName
+ {
+ get { return myFormatParameterName; }
+ }
+ }
+
+ ///
+ /// Indicates that the function argument should be string literal and match one of the parameters of the caller function.
+ /// For example, has such parameter.
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public sealed class InvokerParameterNameAttribute : Attribute
+ {
+ }
+
+ ///
+ /// Indicates that the marked method is assertion method, i.e. it halts control flow if one of the conditions is satisfied.
+ /// To set the condition, mark one of the parameters with attribute
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
+ public sealed class AssertionMethodAttribute : Attribute
+ {
+ }
+
+ ///
+ /// Indicates the condition parameter of the assertion method.
+ /// The method itself should be marked by attribute.
+ /// The mandatory argument of the attribute is the assertion type.
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = true)]
+ public sealed class AssertionConditionAttribute : Attribute
+ {
+ private readonly AssertionConditionType myConditionType;
+
+ ///
+ /// Initializes new instance of AssertionConditionAttribute
+ ///
+ /// Specifies condition type
+ public AssertionConditionAttribute(AssertionConditionType conditionType)
+ {
+ myConditionType = conditionType;
+ }
+
+ ///
+ /// Gets condition type
+ ///
+ public AssertionConditionType ConditionType
+ {
+ get { return myConditionType; }
+ }
+ }
+
+ ///
+ /// Specifies assertion type. If the assertion method argument satisifes the condition, then the execution continues.
+ /// Otherwise, execution is assumed to be halted
+ ///
+ public enum AssertionConditionType
+ {
+ ///
+ /// Indicates that the marked parameter should be evaluated to true
+ ///
+ IS_TRUE = 0,
+
+ ///
+ /// Indicates that the marked parameter should be evaluated to false
+ ///
+ IS_FALSE = 1,
+
+ ///
+ /// Indicates that the marked parameter should be evaluated to null value
+ ///
+ IS_NULL = 2,
+
+ ///
+ /// Indicates that the marked parameter should be evaluated to not null value
+ ///
+ IS_NOT_NULL = 3,
+ }
+
+ ///
+ /// Indicates that the marked method unconditionally terminates control flow execution.
+ /// For example, it could unconditionally throw exception
+ ///
+ [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
+ public sealed class TerminatesProgramAttribute : Attribute
+ {
+ }
+
+ ///
+ /// Indicates that the value of marked element could be null sometimes, so the check for null is necessary before its usage
+ ///
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
+ public sealed class CanBeNullAttribute : Attribute
+ {
+ }
+
+ ///
+ /// Indicates that the value of marked element could never be null
+ ///
+ [AttributeUsage(AttributeTargets.Method | AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.Delegate | AttributeTargets.Field, AllowMultiple = false, Inherited = true)]
+ public sealed class NotNullAttribute : Attribute
+ {
+ }
+
+ ///
+ /// Indicates that the value of marked type (or its derivatives) cannot be compared using '==' or '!=' operators.
+ /// There is only exception to compare with null, it is permitted
+ ///
+ [AttributeUsage(AttributeTargets.Interface | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = true)]
+ public sealed class CannotApplyEqualityOperatorAttribute : Attribute
+ {
+ }
+
+ ///
+ /// When applied to target attribute, specifies a requirement for any type which is marked with
+ /// target attribute to implement or inherit specific type or types
+ ///
+ ///
+ ///
+ /// [BaseTypeRequired(typeof(IComponent)] // Specify requirement
+ /// public class ComponentAttribute : Attribute
+ /// {}
+ ///
+ /// [Component] // ComponentAttribute requires implementing IComponent interface
+ /// public class MyComponent : IComponent
+ /// {}
+ ///
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true)]
+ [BaseTypeRequired(typeof(Attribute))]
+ public sealed class BaseTypeRequiredAttribute : Attribute
+ {
+ private readonly Type[] myBaseTypes;
+
+ ///
+ /// Initializes new instance of BaseTypeRequiredAttribute
+ ///
+ /// Specifies which types are required
+ public BaseTypeRequiredAttribute(Type baseType)
+ {
+ myBaseTypes = new[] { baseType };
+ }
+
+ ///
+ /// Gets enumerations of specified base types
+ ///
+ public IEnumerable BaseTypes
+ {
+ get { return myBaseTypes; }
+ }
+ }
+
+ ///
+ /// Indicates that the marked symbol is used implicitly (e.g. via reflection, in external library),
+ /// so this symbol will not be marked as unused (as well as by other usage inspections)
+ ///
+ [AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = true)]
+ public sealed class UsedImplicitlyAttribute : Attribute
+ {
+ [UsedImplicitly]
+ public UsedImplicitlyAttribute()
+ : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default)
+ {
+ }
+
+ [UsedImplicitly]
+ public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
+ {
+ UseKindFlags = useKindFlags;
+ TargetFlags = targetFlags;
+ }
+
+ [UsedImplicitly]
+ public UsedImplicitlyAttribute(ImplicitUseKindFlags useKindFlags)
+ : this(useKindFlags, ImplicitUseTargetFlags.Default)
+ {
+ }
+
+ [UsedImplicitly]
+ public UsedImplicitlyAttribute(ImplicitUseTargetFlags targetFlags)
+ : this(ImplicitUseKindFlags.Default, targetFlags)
+ {
+ }
+
+ [UsedImplicitly]
+ public ImplicitUseKindFlags UseKindFlags { get; private set; }
+
+ ///
+ /// Gets value indicating what is meant to be used
+ ///
+ [UsedImplicitly]
+ public ImplicitUseTargetFlags TargetFlags { get; private set; }
+ }
+
+ ///
+ /// Should be used on attributes and causes ReSharper to not mark symbols marked with such attributes as unused (as well as by other usage inspections)
+ ///
+ [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
+ public sealed class MeansImplicitUseAttribute : Attribute
+ {
+ [UsedImplicitly]
+ public MeansImplicitUseAttribute()
+ : this(ImplicitUseKindFlags.Default, ImplicitUseTargetFlags.Default)
+ {
+ }
+
+ [UsedImplicitly]
+ public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags, ImplicitUseTargetFlags targetFlags)
+ {
+ UseKindFlags = useKindFlags;
+ TargetFlags = targetFlags;
+ }
+
+ [UsedImplicitly]
+ public MeansImplicitUseAttribute(ImplicitUseKindFlags useKindFlags)
+ : this(useKindFlags, ImplicitUseTargetFlags.Default)
+ {
+ }
+
+ [UsedImplicitly]
+ public MeansImplicitUseAttribute(ImplicitUseTargetFlags targetFlags)
+ : this(ImplicitUseKindFlags.Default, targetFlags)
+ {
+ }
+
+ [UsedImplicitly]
+ public ImplicitUseKindFlags UseKindFlags { get; private set; }
+
+ ///
+ /// Gets value indicating what is meant to be used
+ ///
+ [UsedImplicitly]
+ public ImplicitUseTargetFlags TargetFlags { get; private set; }
+ }
+
+ [Flags]
+ public enum ImplicitUseKindFlags
+ {
+ Default = Access | Assign | InstantiatedWithFixedConstructorSignature,
+
+ ///
+ /// Only entity marked with attribute considered used
+ ///
+ Access = 1,
+
+ ///
+ /// Indicates implicit assignment to a member
+ ///
+ Assign = 2,
+
+ ///
+ /// Indicates implicit instantiation of a type with fixed constructor signature.
+ /// That means any unused constructor parameters won't be reported as such.
+ ///
+ InstantiatedWithFixedConstructorSignature = 4,
+
+ ///
+ /// Indicates implicit instantiation of a type
+ ///
+ InstantiatedNoFixedConstructorSignature = 8,
+ }
+
+ ///
+ /// Specify what is considered used implicitly when marked with or
+ ///
+ [Flags]
+ public enum ImplicitUseTargetFlags
+ {
+ Default = Itself,
+
+ Itself = 1,
+
+ ///
+ /// Members of entity marked with attribute are considered used
+ ///
+ Members = 2,
+
+ ///
+ /// Entity marked with attribute and all its members considered used
+ ///
+ WithMembers = Itself | Members
+ }
+
+ ///
+ /// This attribute is intended to mark publicly available API which should not be removed and so is treated as used.
+ ///
+ [MeansImplicitUse]
+ public sealed class PublicAPIAttribute : Attribute
+ {
+ public PublicAPIAttribute()
+ {
+ }
+
+ // ReSharper disable UnusedParameter.Local
+ public PublicAPIAttribute(string comment)
+ // ReSharper restore UnusedParameter.Local
+ {
+ }
+ }
+
+ ///
+ /// Tells code analysis engine if the parameter is completely handled when the invoked method is on stack.
+ /// If the parameter is delegate, indicates that delegate is executed while the method is executed.
+ /// If the parameter is enumerable, indicates that it is enumerated while the method is executed.
+ ///
+ [AttributeUsage(AttributeTargets.Parameter, Inherited = true)]
+ public sealed class InstantHandleAttribute : Attribute
+ {
+ }
+
+ ///
+ /// Indicates that method doesn't contain observable side effects.
+ /// The same as
+ ///
+ [AttributeUsage(AttributeTargets.Method, Inherited = true)]
+ public sealed class PureAttribute : Attribute { }
+}
diff --git a/ScriptConverter/GenericComparer.cs b/ScriptConverter/GenericComparer.cs
new file mode 100644
index 0000000..e80bc90
--- /dev/null
+++ b/ScriptConverter/GenericComparer.cs
@@ -0,0 +1,20 @@
+using System;
+using System.Collections.Generic;
+
+namespace ScriptConverter
+{
+ public class GenericComparer : IComparer
+ {
+ private Func _comparer;
+
+ public GenericComparer(Func comparer)
+ {
+ _comparer = comparer;
+ }
+
+ public int Compare(T x, T y)
+ {
+ return _comparer(x, y);
+ }
+ }
+}
diff --git a/ScriptConverter/IndentTextWriter.cs b/ScriptConverter/IndentTextWriter.cs
new file mode 100644
index 0000000..2ed4ee1
--- /dev/null
+++ b/ScriptConverter/IndentTextWriter.cs
@@ -0,0 +1,63 @@
+using System;
+using System.Globalization;
+using System.IO;
+using System.Text;
+
+namespace ScriptConverter
+{
+ public class IndentTextWriter : TextWriter
+ {
+ private readonly TextWriter _writer;
+ private readonly string _indentStr;
+ private bool _shouldIndent;
+
+ public int Indent { get; set; }
+
+ public IndentTextWriter(TextWriter writer, string indentStr = " ")
+ {
+ _writer = writer;
+ _indentStr = indentStr;
+ _shouldIndent = false;
+ }
+
+ public override Encoding Encoding
+ {
+ get { return Encoding.Unicode; }
+ }
+
+ public override IFormatProvider FormatProvider
+ {
+ get { return CultureInfo.InvariantCulture; }
+ }
+
+ public override void Write(char value)
+ {
+ if (_shouldIndent)
+ {
+ _shouldIndent = false; // shouldIndent must be cleared first
+ WriteIndent();
+ }
+
+ _writer.Write(value);
+ }
+
+ public override void WriteLine()
+ {
+ base.WriteLine();
+
+ _shouldIndent = true; // defer indenting until the next Write
+ }
+
+ public override void WriteLine(string value)
+ {
+ Write(value);
+ WriteLine();
+ }
+
+ public void WriteIndent()
+ {
+ for (var i = 0; i < Indent; i++)
+ Write(_indentStr);
+ }
+ }
+}
diff --git a/ScriptConverter/Parser/CompilerError.cs b/ScriptConverter/Parser/CompilerError.cs
new file mode 100644
index 0000000..ab0b65c
--- /dev/null
+++ b/ScriptConverter/Parser/CompilerError.cs
@@ -0,0 +1,13 @@
+namespace ScriptConverter.Parser
+{
+ static class CompilerError
+ {
+ public const string UnterminatedString = "Unterminated string";
+ public const string UnexpectedEofString = "Unexpected end of file (bad escape sequence)";
+ public const string InvalidEscapeSequence = "Invalid escape sequence '{0}'";
+ public const string CharLiteralLength = "Character literals must be one byte long";
+ public const string InvalidNumber = "Invalid {0} number '{1}'";
+
+ public const string ExpectedButFound = "Expected {0} but found {1}";
+ }
+}
diff --git a/ScriptConverter/Parser/CompilerException.cs b/ScriptConverter/Parser/CompilerException.cs
new file mode 100644
index 0000000..ca38ab9
--- /dev/null
+++ b/ScriptConverter/Parser/CompilerException.cs
@@ -0,0 +1,21 @@
+using System;
+using JetBrains.Annotations;
+
+namespace ScriptConverter.Parser
+{
+ public class CompilerException : Exception
+ {
+ protected CompilerException(string message)
+ : base(message)
+ {
+
+ }
+
+ [StringFormatMethod("format")]
+ internal CompilerException(ScriptToken token, string format, params object[] args)
+ : base(string.Format("{0}({1}): {2}", token.FileName ?? "null", token.RangeString, string.Format(format, args)))
+ {
+
+ }
+ }
+}
diff --git a/ScriptConverter/Parser/Lexer.Static.cs b/ScriptConverter/Parser/Lexer.Static.cs
new file mode 100644
index 0000000..8bfae9f
--- /dev/null
+++ b/ScriptConverter/Parser/Lexer.Static.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+
+namespace ScriptConverter.Parser
+{
+ abstract partial class Lexer
+ {
+ protected static TToken EofToken;
+
+ static Lexer()
+ {
+ EofToken = null;
+ }
+
+ protected class OperatorDictionary : IEnumerable