Navigation Menu

Skip to content

Commit

Permalink
adding code to have classes
Browse files Browse the repository at this point in the history
  • Loading branch information
SuperFola committed Mar 28, 2019
1 parent d3f5a29 commit 92d59ca
Show file tree
Hide file tree
Showing 6 changed files with 203 additions and 25 deletions.
2 changes: 1 addition & 1 deletion README.md
Expand Up @@ -11,7 +11,7 @@ This language is aiming video games, and was created to replace Lua, which lacks
```
cls Player
// constructor, must be unique
Player(x: int, y: int, name: string)
new Player(x: int, y: int, name: string)
m_x = x
m_y = y
m_name = name
Expand Down
6 changes: 3 additions & 3 deletions documentation/lang/main.md
Expand Up @@ -53,7 +53,7 @@ A class can must only one constructor.

```
cls Name
Name(x: int) // ok
new Name(x: int) // ok
stuff...
end
Expand All @@ -63,11 +63,11 @@ cls Name
end
cls Test
Test()
new Test()
stuff...
end
Test(x: int) // won't work, ParseError
new Test(x: int) // won't work, ParseError
stuff...
end
end
Expand Down
15 changes: 12 additions & 3 deletions kafe/include/kafe/internal/node.hpp
Expand Up @@ -97,12 +97,11 @@ namespace kafe

struct Class : public Node
{
Class(const std::string& name, NodePtr constructor, NodePtrList methods, NodePtrList attributes);
Class(const std::string& name, NodePtr constructor, NodePtrList body);

const std::string name;
NodePtr constructor; // should be a function
NodePtrList methods; // should be a vector of function
NodePtrList attributes; // should be a vector of definition/declaration
NodePtrList body; // should be a vector of functions/definitions/declarations

virtual void toString(std::ostream& os, std::size_t indent);
};
Expand Down Expand Up @@ -234,6 +233,16 @@ namespace kafe
virtual void toString(std::ostream& os, std::size_t indent);
};

struct ClsConstructor : public Node
{
ClsConstructor(const std::string& name, NodePtrList body);

const std::string name;
NodePtrList body;

virtual void toString(std::ostream& os, std::size_t indent);
};

struct End : public Node
{
End();
Expand Down
1 change: 1 addition & 0 deletions kafe/include/kafe/parser.hpp
Expand Up @@ -65,6 +65,7 @@ namespace kafe
MaybeNodePtr parseEnd();
MaybeNodePtr parseFunction();
MaybeNodePtr parseClass();
MaybeNodePtr parseConstructor();
};
}

Expand Down
47 changes: 44 additions & 3 deletions kafe/source/internal/node.cpp
Expand Up @@ -119,14 +119,29 @@ void Function::toString(std::ostream& os, std::size_t indent)

// ---------------------------

Class::Class(const std::string& name, NodePtr constructor, NodePtrList methods, NodePtrList attributes) :
name(name), constructor(std::move(constructor)), methods(std::move(methods)), attributes(std::move(attributes))
Class::Class(const std::string& name, NodePtr constructor, NodePtrList body) :
name(name), constructor(std::move(constructor)), body(std::move(body))
, Node("class")
{}

void Class::toString(std::ostream& os, std::size_t indent)
{
printIndent(os, indent); os << "(Class)";
printIndent(os, indent); os << "(Class\n";
printIndent(os, indent + 1); os << "(Name " << name << ")\n";
constructor->toString(os, indent + 1);
printIndent(os, indent + 1); os << "(Body";
for (auto& node: body)
{
os << "\n";
node->toString(os, indent + 2);
}
if (body.size() > 0)
{
os << "\n";
printIndent(os, indent + 1);
}
os << ")\n";
printIndent(os, indent); os << ")";
}

// ---------------------------
Expand Down Expand Up @@ -300,6 +315,32 @@ void MethodCall::toString(std::ostream& os, std::size_t indent)

// ---------------------------

ClsConstructor::ClsConstructor(const std::string& name, NodePtrList body) :
name(name), body(std::move(body))
, Node("class constructor")
{}

void ClsConstructor::toString(std::ostream& os, std::size_t indent)
{
printIndent(os, indent); os << "(ClassConstructor\n";
printIndent(os, indent + 1); os << "(Name " << name << ")\n";
printIndent(os, indent + 1); os << "(Body";
for (auto& node: body)
{
os << "\n";
node->toString(os, indent + 2);
}
if (body.size() > 0)
{
os << "\n";
printIndent(os, indent + 1);
}
os << ")\n";
printIndent(os, indent); os << ")";
}

// ---------------------------

End::End() :
Node("end")
{}
Expand Down
157 changes: 142 additions & 15 deletions kafe/source/parser.cpp
Expand Up @@ -78,14 +78,8 @@ MaybeNodePtr Parser::parseInstruction()


// function/method calls as expression, not as instruction!
// FunctionCall and MethodCall should be the last ones of the list
if (auto inst = parseFunctionCall())
error("Function calls as instructions are forbidden", "");
else
back(getCount() - current + 1);

if (auto inst = parseMethodCall())
error("Method calls as instructions are forbidden", "");
if (auto inst = parseExp())
error("Expressions as instructions are forbidden", "");
else
back(getCount() - current + 1);

Expand Down Expand Up @@ -214,8 +208,8 @@ MaybeNodePtr Parser::parseOperation()
{
/*
Trying to parse operations such as
(1 + 2)
(1 / (2 + 3))
1 + 2
1 / (2 + 3)
Get current token: it must be a '('
If it's not => quit
Expand All @@ -231,8 +225,6 @@ MaybeNodePtr Parser::parseOperation()
TODO This parser should also do a "shunting yard"
*/

space();

// parse expressions
NodePtrList operations;
Expand Down Expand Up @@ -642,9 +634,9 @@ MaybeNodePtr Parser::parseClass()
/*
Trying to parse class definition:
class Name
cls Name
// only one constructor!
Name(arg: type, ...)
new Name(arg: type, ...)
... // no ret here!
end
Expand All @@ -658,5 +650,140 @@ MaybeNodePtr Parser::parseClass()
end
*/

return {};
space();

std::string keyword = "";
if (!name(&keyword))
return {};
if (keyword != "cls")
return {};

space();

std::string clsname = "";
if (!name(&clsname))
error("Expected class name", clsname);

space();

bool hadconstructor = false;
NodePtrList body;
NodePtr constructor;
while (true)
{
// first, try to get a valid instruction
if (auto inst = parseInt())
body.push_back(inst);
else
{
// otherwise, it's probably the constructor
if (!hadconstructor)
{
if (auto inst = parseConstructor())
constructor = inst;
else
error("Unexpected instruction, a valid constructor is needed", clsname);

hadconstructor = true;
}
else
error("The constructor of a class must be unique", clsname);
}
}

if (!hadconstructor)
error("Class definition must include a constructor", clsname);

return std::make_shared<Class>(clsname, constructor, body);
}

MaybeNodePtr Parser::parseConstructor()
{
/*
Trying to parse constructor definitions such as:
new Name(arg: type, ...)
stuff...
end
*/

space();

// checking for 'new'
std::string keyword = "";
if (!name(&keyword))
return {};
if (keyword != "new")
return {};

space();

// getting name
std::string constructorname = "";
if (!name(&constructorname))
error("Expected constructor name", constructorname);

space();

// getting arguments (enclosed in ())
NodePtrList arguments;
if (except(IsChar('(')))
{
while (true)
{
// eat the trailing white space
space();

// check if end of arguments
if (accept(IsChar(')')))
break;

std::string varname = "";
if (!name(&varname))
break; // we don't have arguments

space();
// : after varname and before type is mandatory
if (!except(IsChar(':')))
error("Expected ':' after argument name and before type name", "");
space();

std::string type = "";
if (!name(&type))
error("Expected type name for argument in function definition", type);

space();

// register argument
arguments.push_back(
std::make_shared<Declaration>(varname, type)
);

// check for ',' -> other arguments
if (accept(IsChar(',')))
continue;
}
}

space();

// getting the body
NodePtrList body;
while (true)
{
MaybeNodePtr inst = parseInstruction();

// after getting the instruction, check if it's valid
if (inst)
{
// if we found a 'end' token, stop
if (inst.value()->nodename == "end")
break;
body.push_back(inst.value());
}
else
error("Expected valid instruction for body of constructor definition", "");
}

return std::make_shared<ClsConstructor>(funcname, arguments, type, body);
}

0 comments on commit 92d59ca

Please sign in to comment.