Skip to content

Commit

Permalink
v1.05
Browse files Browse the repository at this point in the history
- Fixed conditions without then
- Fixed do while/whilenot issue with new lines
- Fixed string concatenation was not detected in some cases
- Added full support of vJASS (vjass blocks, arrays, ifs and loops, function definition)
- Fixed more bugs
  • Loading branch information
Geogriy committed Nov 20, 2019
1 parent 4f272aa commit c04ec44
Show file tree
Hide file tree
Showing 11 changed files with 402 additions and 92 deletions.
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
# cJass2Lua
## Useful converter from cJass to Lua for Warcraft III scripts
## Useful converter from cJass/JASS to Lua for Warcraft III scripts

## Description
Warcraft III Reforged brought us lua scripting, but still a lot of map makers for WC3 are using cJass. Just because C-style syntax rules. Unfortunately cJass extension is unsupported for Reforged and who knows how it will be. Lua is more efficient, useful and simple for game development. But a lot of projects are still on cJass and no way to convert them to Lua. Editor without cJass extension does not perceive this code. Re-writing code manually to Lua could take a lot of time, nobody wants to waste time on it. This tool comes to solve this problem. cjass2lua tool can easily convert cJass to readable Lua code, it will help you to upgrade your map by modern map development patterns.
Warcraft III Reforged brought us Lua scripting, but still a lot of map makers for WC3 are using JASS and cJass. JASS is because it's a standard and cJass just because C-style syntax rules. Unfortunately cJass extension is unsupported for Reforged and who knows how it will be. And JASS becomes deprecated. Lua is more efficient, useful and simple for game development. But a lot of projects are still on cJass/JASS and no way to convert them to Lua. Editor without cJass extension does not perceive this code. Re-writing code manually to Lua could take a lot of time, nobody wants to waste time on it. This tool comes to solve this problem. cjass2lua tool can easily convert cJass and JASS to readable Lua code, it will help you to upgrade your map by modern map development patterns.

### Features
- Analyzing and syntax checking cJass code
- Producing .lua file with converted code of your cJass code
- Full support of JASS/cJASS
- Producing .lua file with converted code of your cJass/JASS code
- Single file conversion
- Smart string decection (constants, locals, globals, declared functions) and smart replacing string concatenation operator
- Supports some JASS syntax as condition expressions without `()`, `if ... then`. Keywords `local`, `set`, `call`, `array` can be used normally or not used at all. Loops supported: `while`, `do ... while`, `whilenot`, `do ... whilenot`, `loop / exitwhen`
- Supports mixed code of cJass/JASS. It is fully recognizable.
- Lambdas
- Define macroses with expressions
- Massive folder-to-folder conversion
Expand All @@ -23,21 +24,20 @@ Warcraft III Reforged brought us lua scripting, but still a lot of map makers fo

### Unsupported features
- Analyzing classes/structures and converting them to Lua meta table implementation (Planned to be implemented soon)
- JASS/vJASS Syntax
- vJASS features as scopes, modules, etc. are unsupported (and have no sense in Lua)
- Pre-processor directives
- Macroses. Only constants, function and variable shorters. Macroses are translated into global variables.
- Macroses. Only constants and expression defines, function and variable shorters. Macroses are translated into global variables.

### Pay attention to this before translating your code
- Your code is 100% correct
- Array indexes in Lua started from 1 in some cases. Just note that.
- You have no objects or classes/structures
- You have no JASS syntax function and block declaration. Use only C style definition as `unit Function(integer arg)` and C style block definition with `{ ... }`, do not use such words as `endfunction`, `endloop` etc.
- String concatecation operator `+` in JASS normally should be replaced with `..` but string globals or functions defined beyond current file are unknown. And in this some cases with unknown in current context string globals or functions operator `+` will be not replaced.
- Pre-increments or post-increments are supported and can be used in expressions, but for example `a = i++` will be converted into `a = (i + 1)` and `i` will not be incremented. In this cases you need to increment it manually.
- Read logs if something goes wrong, this application leaves cjass2lua.log file with all it's actions and possible problems. Everything should be fine if you have no warnings.

### Latest release
- [v1.04](https://github.com/fullmetal-a/cjass2lua/releases/tag/v1.04)
- [v1.05](https://github.com/fullmetal-a/cjass2lua/releases/tag/v1.05)

### Manual
#### GUI
Expand Down
4 changes: 4 additions & 0 deletions cJass2Lua/Logger.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ namespace _____LOGGER
};

#ifdef _LOGGER_MAIN_CPP
#ifndef _DEBUG
Logger ___Logger(OutputInterface::Type::File, __logFileName);
#else
Logger ___Logger(OutputInterface::Type::Console, __logFileName);
#endif
#else
extern Logger ___Logger;
#endif
Expand Down
4 changes: 4 additions & 0 deletions cJass2Lua/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ namespace Utils
{
if (op == "&&")
return " and ";
else if (op == "." || op == ":")
return op;
else if (op == "+" && prevType == cJass::OperationObject::ConstType::String)
return " .. ";
else if (op == "||")
Expand All @@ -277,6 +279,8 @@ namespace Utils
{
if (op == "&&")
return " and ";
else if (op == "." || op == ":")
return op;
else if (op == "+" && isString)
return " .. ";
else if (op == "||")
Expand Down
115 changes: 94 additions & 21 deletions cJass2Lua/cJassNodes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,24 @@ namespace cJass
res += "Logic";
break;

case OperationObject::OpType::WhileNot:
res += "WhileNot";
break;

case OperationObject::OpType::Do:
res += "Do";
break;

case OperationObject::OpType::DoStatement:
res += "DoStatement";
break;

case OperationObject::OpType::ExitWhen:
res += "ExitWhen";
break;

default:
return "Unknown";
res += "Unknown";
}
res += ")";
return res;
Expand Down Expand Up @@ -158,9 +174,6 @@ namespace cJass
{
if (node->_depthIndex == 0)
node->_depthIndex = _depthIndex + 1;

if (_isString)
node->_isString = true;

_subnodes.push_back(node);
ResetIterator();
Expand Down Expand Up @@ -360,7 +373,7 @@ namespace cJass
else
_out << "-- " << tmp;

if (Top() == nullptr)
if (Top()->Top() == nullptr)
{
_out << OutputInterface::nl;
}
Expand Down Expand Up @@ -632,14 +645,13 @@ namespace cJass
break;

case OpType::DoStatement:
_out << "until(";
_out << "until ";
if (_extra == "not")
_out << "not(";
_out << "not( ";
for (auto& node : _subnodes)
node->ToLua();
if (_extra == "not")
_out << ")";
_out << ")";
_out << " )";
break;

case OpType::ExitWhen:
Expand Down Expand Up @@ -792,15 +804,15 @@ namespace cJass
case OpType::WhileNot:
_out << OutputInterface::nl;
PrintTabs(1);
_out << "while not (";
_out << "while not ( ";
if (CountSubnodes() == 0)
appLog(Warning) << "'whilenot' without statement!";
for (size_t i = 0; i < CountSubnodes(); i++)
{
auto node = AtNode(i);
node->ToLua();
if (i == 0)
_out << ") do";
_out << " ) do";
}
_out << OutputInterface::nl;
PrintTabs(1);
Expand Down Expand Up @@ -993,35 +1005,96 @@ namespace cJass
bool OperationObject::HasNeighbourStrings()
{
Node* top = _top;
size_t this_index = std::string::npos;
size_t this_index = 9999999;

if (top->IsString())
return true;

std::vector<std::string> neighbours;
for (size_t i = 0; i < top->CountSubnodes(); i++)
{
auto node = top->AtNode(i);

if (node->Ptr() == dynamic_cast<Node*>(this))
if (i > this_index + 1)
break;

if (node->Ptr() == dynamic_cast<Node*>(this) && this_index == 9999999)
{
this_index = i;
if (i > 0)
i--;
}

if (i == this_index - 1)
{
node = top->AtNode(i);
if (node->Ptr<OperationObject>()->GetOpType() == OperationObject::OpType::Index)
{
for (int j = int(i); j >= 0; j--)
{
node = top->AtNode(j);
if (node->Ptr<OperationObject>()->GetOpType() != OperationObject::OpType::Index)
{
neighbours.push_back(node->Ptr<OperationObject>()->_opText);
continue;
}
}
}
else
neighbours.push_back(node->Ptr<OperationObject>()->_opText);
}

if (i == this_index + 1)
{
node = top->AtNode(i);
neighbours.push_back(node->Ptr<OperationObject>()->_opText);
}
}

Function* fnode = nullptr;
GlobalSpace* gspace = nullptr;

top = this;
while (top != nullptr)
{
if (top->GetType() == Node::Type::Function)
{
fnode = top->Ptr<Function>();
break;
}
top = top->Top();
}

top = _top;
while (top != nullptr)
{
if (top->Top() == nullptr)
{
gspace = top->Ptr<GlobalSpace>();
break;
}
top = top->Top();
}

if (this_index != std::string::npos)
if (fnode != nullptr)
{
for (size_t i = 0; i < top->CountSubnodes(); i++)
for (auto n : neighbours)
{
auto node = top->AtNode(i);
if (n != "" && fnode->HasStringId(n))
return true;
}
}

if (i == this_index - 1 || i == this_index + 1)
{
if (node->IsString())
return true;
}
if (gspace != nullptr)
{
for (auto n : neighbours)
{
if (n != "" && gspace->HasStringId(n))
return true;
}
}
else
appLog(Critical) << "OperationObject::HasNeighbourStrings: Root node not found.";

return false;
}
Expand Down
6 changes: 3 additions & 3 deletions cJass2Lua/cJassNodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,12 +129,12 @@ namespace cJass
Constant,
Operator,
UnaryOperator,
Return,
NewLine,

//Expressions
ExitWhen,
DoStatement,

//Expressions
Return,
Expression, //General expression in () brackets or without them
Call, //Function call
Index, //Array index expression [] (not definition)
Expand Down
Loading

0 comments on commit c04ec44

Please sign in to comment.