OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
C4AulParse Class Reference

#include <C4AulParse.h>

Public Member Functions

 C4AulParse (class C4ScriptHost *host)
 
 C4AulParse (C4AulScriptFunc *Fn, C4AulScriptContext *context, C4AulScriptEngine *Engine)
 
 ~C4AulParse ()
 
std::unique_ptr
<::aul::ast::FunctionDecl
Parse_DirectExec (const char *code, bool whole_function)
 
std::unique_ptr
<::aul::ast::Script
Parse_Script (C4ScriptHost *)
 

Protected Member Functions

std::unique_ptr
<::aul::ast::FunctionDecl
Parse_ToplevelFunctionDecl ()
 
std::unique_ptr<::aul::ast::StmtParse_Statement ()
 
std::unique_ptr<::aul::ast::BlockParse_Block ()
 
std::unique_ptr
<::aul::ast::ArrayLit
Parse_Array ()
 
std::unique_ptr
<::aul::ast::ProplistLit
Parse_PropList ()
 
std::unique_ptr
<::aul::ast::DoLoop
Parse_DoWhile ()
 
std::unique_ptr
<::aul::ast::WhileLoop
Parse_While ()
 
std::unique_ptr<::aul::ast::IfParse_If ()
 
std::unique_ptr
<::aul::ast::ForLoop
Parse_For ()
 
std::unique_ptr
<::aul::ast::RangeLoop
Parse_ForEach ()
 
std::unique_ptr<::aul::ast::ExprParse_Expression (int iParentPrio=-1)
 
std::unique_ptr
<::aul::ast::VarDecl
Parse_Var ()
 
void Shift ()
 

Friends

class C4AulParseError
 

Detailed Description

Definition at line 45 of file C4AulParse.h.

Constructor & Destructor Documentation

C4AulParse::C4AulParse ( class C4ScriptHost host)

Definition at line 104 of file C4AulParse.cpp.

104  :
105  Fn(nullptr), Host(a), pOrgScript(a), Engine(a->Engine),
106  SPos(a->Script.getData()), TokenSPos(SPos),
107  TokenType(ATT_INVALID),
108  ContextToExecIn(nullptr)
109 { }
#define a
C4AulParse::C4AulParse ( C4AulScriptFunc Fn,
C4AulScriptContext context,
C4AulScriptEngine Engine 
)

Definition at line 111 of file C4AulParse.cpp.

111  :
112  Fn(Fn), Host(nullptr), pOrgScript(nullptr), Engine(Engine),
113  SPos(Fn->Script), TokenSPos(SPos),
114  TokenType(ATT_INVALID),
115  ContextToExecIn(context)
116 { }
const char * Script
C4AulParse::~C4AulParse ( )

Definition at line 118 of file C4AulParse.cpp.

119 {
120  ClearToken();
121 }

Member Function Documentation

std::unique_ptr<::aul::ast::ArrayLit > C4AulParse::Parse_Array ( )
protected

Definition at line 1194 of file C4AulParse.cpp.

References ATT_BCLOSE2, ATT_BOPEN2, ATT_COMMA, Parse_Expression(), Shift(), and C4ScriptHost::Warn().

Referenced by Parse_Expression().

1195 {
1196  auto arr = ::aul::ast::ArrayLit::New(TokenSPos);
1197  // force "["
1198  Match(ATT_BOPEN2);
1199  // Create an array
1200  while (TokenType != ATT_BCLOSE2)
1201  {
1202  // got no parameter before a ","? then push nil
1203  if (TokenType == ATT_COMMA)
1204  {
1205  Warn(C4AulWarningId::empty_parameter_in_array, (unsigned)arr->values.size());
1206  arr->values.emplace_back(::aul::ast::NilLit::New(TokenSPos));
1207  }
1208  else
1209  arr->values.emplace_back(Parse_Expression());
1210  if (TokenType == ATT_BCLOSE2)
1211  break;
1212  Match(ATT_COMMA, "',' or ']'");
1213  // [] -> size 0, [*,] -> size 2, [*,*,] -> size 3
1214  if (TokenType == ATT_BCLOSE2)
1215  {
1216  Warn(C4AulWarningId::empty_parameter_in_array, (unsigned)arr->values.size());
1217  arr->values.emplace_back(::aul::ast::NilLit::New(TokenSPos));
1218  }
1219  }
1220  Shift();
1221  return arr;
1222 }
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::Block > C4AulParse::Parse_Block ( )
protected

Definition at line 1033 of file C4AulParse.cpp.

References ATT_BLCLOSE, ATT_BLOPEN, Parse_Statement(), and Shift().

Referenced by Parse_Statement().

1034 {
1035  auto block = ::aul::ast::Block::New(TokenSPos);
1036  Match(ATT_BLOPEN);
1037  while (TokenType != ATT_BLCLOSE)
1038  {
1039  block->children.push_back(Parse_Statement());
1040  }
1041  Shift();
1042  return block;
1043 }
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::FunctionDecl > C4AulParse::Parse_DirectExec ( const char *  code,
bool  whole_function 
)

Definition at line 843 of file C4AulParse.cpp.

References ATT_EOF, Parse_Expression(), Parse_ToplevelFunctionDecl(), and Shift().

Referenced by C4AulScriptFunc::ParseDirectExecFunc(), and C4AulScriptFunc::ParseDirectExecStatement().

844 {
845  // get first token
846  Shift();
847  // Synthesize a wrapping function which we can call
848  std::unique_ptr<::aul::ast::FunctionDecl> func;
849  if (whole_function)
850  {
852  }
853  else
854  {
855  auto expr = Parse_Expression();
856  func = std::make_unique<::aul::ast::FunctionDecl>("$internal$eval");
857  func->body = std::make_unique<::aul::ast::Block>();
858  func->body->children.push_back(std::make_unique<::aul::ast::Return>(std::move(expr)));
859  }
860  Match(ATT_EOF);
861  return func;
862 }
std::unique_ptr<::aul::ast::FunctionDecl > Parse_ToplevelFunctionDecl()
Definition: C4AulParse.cpp:950
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::DoLoop > C4AulParse::Parse_DoWhile ( )
protected

Definition at line 1260 of file C4AulParse.cpp.

References ATT_BCLOSE, ATT_BOPEN, ATT_IDTF, C4AUL_While, Parse_Expression(), Parse_Statement(), SEqual(), and Shift().

Referenced by Parse_Statement().

1261 {
1262  auto loop = ::aul::ast::DoLoop::New(TokenSPos);
1263  Shift();
1264  loop->body = Parse_Statement();
1265  // Execute condition
1266  if (TokenType != ATT_IDTF || !SEqual(Idtf, C4AUL_While))
1267  UnexpectedToken("'while'");
1268  Shift();
1269  Match(ATT_BOPEN);
1270  loop->cond = Parse_Expression();
1271  Match(ATT_BCLOSE);
1272  return loop;
1273 }
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
#define C4AUL_While
Definition: C4AulParse.cpp:48
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::Expr > C4AulParse::Parse_Expression ( int  iParentPrio = -1)
protected

Definition at line 1370 of file C4AulParse.cpp.

References ATT_BCLOSE, ATT_BCLOSE2, ATT_BLOPEN, ATT_BOPEN, ATT_BOPEN2, ATT_CALL, ATT_CALLFS, ATT_COLON, ATT_DOT, ATT_IDTF, ATT_INT, ATT_OPERATOR, ATT_SET, ATT_STRING, C4AUL_Do, C4AUL_Else, C4AUL_False, C4AUL_For, C4AUL_Func, C4AUL_If, C4AUL_New, C4AUL_Nil, C4AUL_Par, C4AUL_Return, C4AUL_this, C4AUL_True, C4AUL_While, C4AulParseError, aul::ast::CallExpr::callee, C4ScriptOpDef::Changer, aul::ast::CallExpr::context, C4String::GetCStr(), C4ScriptOpDef::Identifier, C4ScriptOpDef::NoSecondStatement, Parse_Array(), Parse_PropList(), C4ScriptOpDef::Postfix, C4ScriptOpDef::Priority, aul::ast::CallExpr::safe_call, SEqual(), and Shift().

Referenced by Parse_Array(), Parse_DirectExec(), Parse_DoWhile(), Parse_For(), Parse_ForEach(), Parse_If(), Parse_PropList(), Parse_Statement(), Parse_Var(), and Parse_While().

1371 {
1372  const char *NodeStart = TokenSPos;
1373  std::unique_ptr<::aul::ast::Expr> expr;
1374  const C4ScriptOpDef * op;
1375  C4AulFunc *FoundFn = nullptr;
1376  C4Value val;
1377  switch (TokenType)
1378  {
1379  case ATT_IDTF:
1380  // XXX: Resolving literals here means that you can't create a variable
1381  // with the names "true", "false", "nil" or "this" anymore. I don't
1382  // consider this too much of a problem, because there is never a reason
1383  // to do this and it makes my job a lot easier
1384  if (SEqual(Idtf, C4AUL_True))
1385  {
1386  Shift();
1387  expr = ::aul::ast::BoolLit::New(NodeStart, true);
1388  }
1389  else if (SEqual(Idtf, C4AUL_False))
1390  {
1391  Shift();
1392  expr = ::aul::ast::BoolLit::New(NodeStart, false);
1393  }
1394  else if (SEqual(Idtf, C4AUL_Nil))
1395  {
1396  Shift();
1397  expr = ::aul::ast::NilLit::New(NodeStart);
1398  }
1399  else if (SEqual(Idtf, C4AUL_this))
1400  {
1401  Shift();
1402  if (TokenType == ATT_BOPEN)
1403  {
1404  Shift();
1405  Match(ATT_BCLOSE);
1406  // TODO: maybe warn about "this" with parentheses?
1407  }
1408  expr = ::aul::ast::ThisLit::New(NodeStart);
1409  }
1410  // XXX: Other things that people aren't allowed to do anymore: name their variables or functions any of:
1411  // "if", "else", "for", "while", "do", "return", or "Par".
1412  // We could allow variables with these names and disambiguate based on the syntax, but no.
1413  else if (SEqual(Idtf, C4AUL_If) || SEqual(Idtf, C4AUL_Else) || SEqual(Idtf, C4AUL_For) || SEqual(Idtf, C4AUL_While) || SEqual(Idtf, C4AUL_Do) || SEqual(Idtf, C4AUL_Return))
1414  {
1415  Error("reserved identifier not allowed in expressions: %s", Idtf);
1416  }
1417  else if (SEqual(Idtf, C4AUL_Par))
1418  {
1419  Shift();
1420  // "Par" is special in that it isn't a function and thus doesn't accept an arbitrary number of parameters
1421  Match(ATT_BOPEN);
1422  expr = ::aul::ast::ParExpr::New(NodeStart, Parse_Expression());
1423  Match(ATT_BCLOSE);
1424  }
1425  else if (SEqual(Idtf, C4AUL_New))
1426  {
1427  // Because people might call a variables or functions "new", we need to look ahead and guess whether it's a proplist constructor.
1428  PushParsePos();
1429  Shift();
1430  if (TokenType == ATT_IDTF)
1431  {
1432  // this must be a proplist because two identifiers can't immediately follow each other
1433  PopParsePos();
1434  expr = Parse_PropList();
1435  }
1436  else
1437  {
1438  // Some non-identifier means this is either a variable, a function, or a syntax error. Which one exactly is something we'll figure out later.
1439  PopParsePos();
1440  }
1441  }
1442  else if (SEqual(Idtf, C4AUL_Func))
1443  {
1444  PushParsePos();
1445  Shift();
1446  if (TokenType == ATT_BOPEN)
1447  {
1448  auto func = ::aul::ast::FunctionExpr::New(NodeStart);
1449  Parse_Function(func.get());
1450  expr = std::move(func);
1451  DiscardParsePos();
1452  }
1453  else
1454  {
1455  PopParsePos();
1456  }
1457  }
1458  if (!expr)
1459  {
1460  // If we end up here, it must be a proper identifier (or a reserved word that's used as an identifier).
1461  // Time to look ahead and see whether it's a function call.
1462  std::string identifier = Idtf;
1463  Shift();
1464  if (TokenType == ATT_BOPEN)
1465  {
1466  // Well, it looks like one, at least
1467  auto func = ::aul::ast::CallExpr::New(NodeStart);
1468  func->callee = identifier;
1469  Parse_CallParams(func.get());
1470  expr = std::move(func);
1471  }
1472  else
1473  {
1474  // It's most certainly not a function call.
1475  expr = ::aul::ast::VarExpr::New(NodeStart, identifier);
1476  }
1477  }
1478  break;
1479  case ATT_INT: // constant in cInt
1480  expr = ::aul::ast::IntLit::New(NodeStart, cInt);
1481  Shift();
1482  break;
1483  case ATT_STRING: // reference in cStr
1484  expr = ::aul::ast::StringLit::New(NodeStart, cStr->GetCStr());
1485  Shift();
1486  break;
1487  case ATT_OPERATOR:
1488  // -> must be a prefix operator
1489  op = &C4ScriptOpMap[cInt];
1490  // postfix?
1491  if (op->Postfix)
1492  // oops. that's wrong
1493  throw C4AulParseError(this, "postfix operator without first expression");
1494  Shift();
1495  // generate code for the following expression
1496  expr = Parse_Expression(op->Priority);
1497  if (SEqual(op->Identifier, "+"))
1498  {
1499  // This is a no-op.
1500  }
1501  else
1502  {
1503  expr = ::aul::ast::UnOpExpr::New(NodeStart, op - C4ScriptOpMap, std::move(expr));
1504  }
1505  break;
1506  case ATT_BOPEN:
1507  Shift();
1508  expr = Parse_Expression();
1509  Match(ATT_BCLOSE);
1510  break;
1511  case ATT_BOPEN2:
1512  expr = Parse_Array();
1513  break;
1514  case ATT_BLOPEN:
1515  expr = Parse_PropList();
1516  break;
1517  default:
1518  UnexpectedToken("expression");
1519  }
1520 
1521  assert(expr);
1522 
1523  while (true)
1524  {
1525  NodeStart = TokenSPos;
1526  switch (TokenType)
1527  {
1528  case ATT_SET:
1529  {
1530  // back out of any kind of parent operator
1531  // (except other setters, as those are right-associative)
1532  if (iParentPrio > 1)
1533  return expr;
1534  Shift();
1535  expr = ::aul::ast::AssignmentExpr::New(NodeStart, std::move(expr), Parse_Expression(1));
1536  break;
1537  }
1538  case ATT_OPERATOR:
1539  {
1540  // expect postfix operator
1541  const C4ScriptOpDef * op = &C4ScriptOpMap[cInt];
1542  if (!op->Postfix)
1543  {
1544  // does an operator with the same name exist?
1545  // when it's a postfix-operator, it can be used instead.
1546  const C4ScriptOpDef * postfixop;
1547  for (postfixop = op + 1; postfixop->Identifier; ++postfixop)
1548  if (SEqual(op->Identifier, postfixop->Identifier))
1549  if (postfixop->Postfix)
1550  break;
1551  // not found?
1552  if (!postfixop->Identifier)
1553  {
1554  Error("unexpected prefix operator: %s", op->Identifier);
1555  }
1556  // otherwise use the new-found correct postfix operator
1557  op = postfixop;
1558  }
1559 
1560  if (iParentPrio + !op->Changer > op->Priority)
1561  return expr;
1562 
1563  Shift();
1564  if (op->NoSecondStatement)
1565  {
1566  // Postfix unary op
1567  expr = ::aul::ast::UnOpExpr::New(NodeStart, op - C4ScriptOpMap, std::move(expr));
1568  }
1569  else
1570  {
1571  expr = ::aul::ast::BinOpExpr::New(NodeStart, op - C4ScriptOpMap, std::move(expr), Parse_Expression(op->Priority));
1572  }
1573  break;
1574  }
1575  case ATT_BOPEN2:
1576  {
1577  // parse either [index], or [start:end] in which case either index is optional
1578  Shift();
1579  ::aul::ast::ExprPtr start;
1580  if (TokenType == ATT_COLON)
1581  start = ::aul::ast::IntLit::New(TokenSPos, 0); // slice with first index missing -> implicit start index zero
1582  else
1583  start = Parse_Expression();
1584 
1585  if (TokenType == ATT_BCLOSE2)
1586  {
1587  expr = ::aul::ast::SubscriptExpr::New(NodeStart, std::move(expr), std::move(start));
1588  }
1589  else if (TokenType == ATT_COLON)
1590  {
1591  Shift();
1592  ::aul::ast::ExprPtr end;
1593  if (TokenType == ATT_BCLOSE2)
1594  {
1595  end = ::aul::ast::IntLit::New(TokenSPos, std::numeric_limits<int32_t>::max());
1596  }
1597  else
1598  {
1599  end = Parse_Expression();
1600  }
1601  expr = ::aul::ast::SliceExpr::New(NodeStart, std::move(expr), std::move(start), std::move(end));
1602  }
1603  else
1604  {
1605  UnexpectedToken("']' or ':'");
1606  }
1607  Match(ATT_BCLOSE2);
1608  break;
1609  }
1610  case ATT_DOT:
1611  Shift();
1612  Check(ATT_IDTF, "property name");
1613  expr = ::aul::ast::SubscriptExpr::New(NodeStart, std::move(expr), ::aul::ast::StringLit::New(TokenSPos, Idtf));
1614  Shift();
1615  break;
1616  case ATT_CALL: case ATT_CALLFS:
1617  {
1618  auto call = ::aul::ast::CallExpr::New(NodeStart);
1619  call->context = std::move(expr);
1620  call->safe_call = TokenType == ATT_CALLFS;
1621  Shift();
1622  Check(ATT_IDTF, "function name after '->'");
1623  call->callee = Idtf;
1624  Shift();
1625  Parse_CallParams(call.get());
1626  expr = std::move(call);
1627  break;
1628  }
1629  default:
1630  return expr;
1631  }
1632  }
1633 }
#define C4AUL_For
Definition: C4AulParse.cpp:49
const C4ScriptOpDef C4ScriptOpMap[]
Definition: C4AulParse.cpp:261
bool NoSecondStatement
Definition: C4AulParse.h:37
#define C4AUL_Func
Definition: C4AulParse.cpp:37
const char * GetCStr() const
Definition: C4StringTable.h:49
#define C4AUL_Return
Definition: C4AulParse.cpp:51
#define C4AUL_If
Definition: C4AulParse.cpp:45
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
#define C4AUL_Do
Definition: C4AulParse.cpp:47
std::unique_ptr<::aul::ast::ArrayLit > Parse_Array()
std::unique_ptr< Expr > ExprPtr
Definition: C4AulAST.h:147
#define C4AUL_this
Definition: C4AulParse.cpp:56
#define C4AUL_New
Definition: C4AulParse.cpp:76
friend class C4AulParseError
Definition: C4AulParse.h:101
#define C4AUL_False
Definition: C4AulParse.cpp:74
unsigned short Priority
Definition: C4AulParse.h:32
#define C4AUL_Else
Definition: C4AulParse.cpp:46
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
#define C4AUL_While
Definition: C4AulParse.cpp:48
#define C4AUL_Par
Definition: C4AulParse.cpp:53
const char * Identifier
Definition: C4AulParse.h:33
#define C4AUL_Nil
Definition: C4AulParse.cpp:75
void Shift()
Definition: C4AulParse.cpp:746
std::unique_ptr<::aul::ast::ProplistLit > Parse_PropList()
#define C4AUL_True
Definition: C4AulParse.cpp:73

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::ForLoop > C4AulParse::Parse_For ( )
protected

Definition at line 1306 of file C4AulParse.cpp.

References ATT_BCLOSE, ATT_BOPEN, ATT_IDTF, ATT_SCOLON, C4AUL_VarNamed, Parse_Expression(), Parse_Statement(), Parse_Var(), and SEqual().

Referenced by Parse_Statement().

1307 {
1308  auto loop = ::aul::ast::ForLoop::New(TokenSPos);
1309  Match(ATT_IDTF); Match(ATT_BOPEN);
1310  // Initialization
1311  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_VarNamed))
1312  {
1313  loop->init = Parse_Var();
1314  }
1315  else if (TokenType != ATT_SCOLON)
1316  {
1317  loop->init = Parse_Expression();
1318  }
1319  // Consume first semicolon
1320  Match(ATT_SCOLON);
1321  // Condition
1322  if (TokenType != ATT_SCOLON)
1323  {
1324  loop->cond = Parse_Expression();
1325  }
1326  // Consume second semicolon
1327  Match(ATT_SCOLON);
1328  // Incrementor
1329  if (TokenType != ATT_BCLOSE)
1330  {
1331  loop->incr = Parse_Expression();
1332  }
1333  // Consume closing bracket
1334  Match(ATT_BCLOSE);
1335  loop->body = Parse_Statement();
1336  return loop;
1337 }
#define C4AUL_VarNamed
Definition: C4AulParse.cpp:60
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
std::unique_ptr<::aul::ast::VarDecl > Parse_Var()
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::RangeLoop > C4AulParse::Parse_ForEach ( )
protected

Definition at line 1339 of file C4AulParse.cpp.

References ATT_BCLOSE, ATT_BOPEN, ATT_IDTF, C4AUL_In, C4AUL_VarNamed, Parse_Expression(), Parse_Statement(), SEqual(), and Shift().

Referenced by Parse_Statement().

1340 {
1341  auto loop = ::aul::ast::RangeLoop::New(TokenSPos);
1342  Match(ATT_IDTF); Match(ATT_BOPEN);
1343  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_VarNamed))
1344  {
1345  loop->scoped_var = true;
1346  Shift();
1347  }
1348  // get variable name
1349  Check(ATT_IDTF, "variable name");
1350  loop->var = Idtf;
1351  Shift();
1352  if (TokenType != ATT_IDTF || !SEqual(Idtf, C4AUL_In))
1353  UnexpectedToken("'in'");
1354  Shift();
1355  // get expression for array
1356  loop->cond = Parse_Expression();
1357  Match(ATT_BCLOSE);
1358  // loop body
1359  loop->body = Parse_Statement();
1360  return loop;
1361 }
#define C4AUL_VarNamed
Definition: C4AulParse.cpp:60
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
#define C4AUL_In
Definition: C4AulParse.cpp:50
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::If > C4AulParse::Parse_If ( )
protected

Definition at line 1288 of file C4AulParse.cpp.

References ATT_BCLOSE, ATT_BOPEN, ATT_IDTF, C4AUL_Else, Parse_Expression(), Parse_Statement(), SEqual(), and Shift().

Referenced by Parse_Statement().

1289 {
1290  auto stmt = ::aul::ast::If::New(TokenSPos);
1291  Shift();
1292  Match(ATT_BOPEN);
1293  stmt->cond = Parse_Expression();
1294  Match(ATT_BCLOSE);
1295  // parse controlled statement
1296  stmt->iftrue = Parse_Statement();
1297  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_Else))
1298  {
1299  Shift();
1300  // expect a command now
1301  stmt->iffalse = Parse_Statement();
1302  }
1303  return stmt;
1304 }
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
#define C4AUL_Else
Definition: C4AulParse.cpp:46
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::ProplistLit > C4AulParse::Parse_PropList ( )
protected

Definition at line 1224 of file C4AulParse.cpp.

References ATT_BLCLOSE, ATT_BLOPEN, ATT_COLON, ATT_COMMA, ATT_IDTF, ATT_SET, ATT_STRING, C4AUL_New, C4String::GetCStr(), C4StringTable::P, P_Prototype, Parse_Expression(), SEqual(), Shift(), and Strings.

Referenced by Parse_Expression().

1225 {
1226  auto proplist = ::aul::ast::ProplistLit::New(TokenSPos);
1227  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_New))
1228  {
1229  Shift();
1230  proplist->values.emplace_back(Strings.P[P_Prototype].GetCStr(), Parse_Expression());
1231  }
1232  Match(ATT_BLOPEN);
1233  while (TokenType != ATT_BLCLOSE)
1234  {
1235  std::string key;
1236  if (TokenType == ATT_IDTF)
1237  {
1238  key = Idtf;
1239  Shift();
1240  }
1241  else if (TokenType == ATT_STRING)
1242  {
1243  key = cStr->GetCStr();
1244  Shift();
1245  }
1246  else UnexpectedToken("string or identifier");
1247  if (TokenType != ATT_COLON && TokenType != ATT_SET)
1248  UnexpectedToken("':' or '='");
1249  Shift();
1250  proplist->values.emplace_back(key, Parse_Expression());
1251  if (TokenType == ATT_COMMA)
1252  Shift();
1253  else if (TokenType != ATT_BLCLOSE)
1254  UnexpectedToken("'}' or ','");
1255  }
1256  Shift();
1257  return proplist;
1258 }
C4String P[P_LAST]
const char * GetCStr() const
Definition: C4StringTable.h:49
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
C4StringTable Strings
Definition: C4Globals.cpp:42
#define C4AUL_New
Definition: C4AulParse.cpp:76
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::Script > C4AulParse::Parse_Script ( C4ScriptHost scripthost)

Definition at line 864 of file C4AulParse.cpp.

References ATT_DIR, ATT_EOF, ATT_IDTF, ATT_OPERATOR, ATT_SCOLON, C4AUL_Append, C4AUL_GlobalNamed, C4AUL_Include, C4AUL_LocalNamed, C4AulParseError, C4ScriptHost::Engine, C4AulScriptEngine::errCnt, C4AulScriptEngine::ErrorHandler, StdStrBuf::getData(), C4PropList::GetDef(), C4ScriptHost::GetPropList(), C4AulErrorHandler::OnError(), Parse_ToplevelFunctionDecl(), Parse_Var(), C4ScriptHost::Script, ScriptEngine, SEqual(), Shift(), and C4AulError::what().

Referenced by C4ScriptHost::Preparse().

865 {
866  pOrgScript = scripthost;
867  SPos = pOrgScript->Script.getData();
868  const char * SPos0 = SPos;
869  bool first_error = true;
870  auto script = ::aul::ast::Script::New(SPos0);
871  while (true) try
872  {
873  // Go to the next token if the current token could not be processed or no token has yet been parsed
874  if (SPos == SPos0)
875  {
876  Shift();
877  }
878  SPos0 = SPos;
879  switch (TokenType)
880  {
881  case ATT_DIR:
882  // check for include statement
883  if (SEqual(Idtf, C4AUL_Include))
884  {
885  Shift();
886  // get id of script to include
887  Check(ATT_IDTF, "script name");
888  script->declarations.push_back(::aul::ast::IncludePragma::New(TokenSPos, Idtf));
889  Shift();
890  }
891  else if (SEqual(Idtf, C4AUL_Append))
892  {
893  if (pOrgScript->GetPropList()->GetDef())
894  throw C4AulParseError(this, "#appendto in a Definition");
895  Shift();
896  // get id of script to include/append
897  switch (TokenType)
898  {
899  case ATT_IDTF:
900  script->declarations.push_back(::aul::ast::AppendtoPragma::New(TokenSPos, Idtf));
901  break;
902  case ATT_OPERATOR:
903  if (SEqual(C4ScriptOpMap[cInt].Identifier, "*"))
904  {
905  script->declarations.push_back(::aul::ast::AppendtoPragma::New(TokenSPos));
906  break;
907  }
908  //fallthrough
909  default:
910  // -> ID expected
911  UnexpectedToken("identifier or '*'");
912  }
913  Shift();
914  }
915  else
916  // -> unknown directive
917  Error("unknown directive: %s", Idtf);
918  break;
919  case ATT_IDTF:
920  // need a keyword here to avoid parsing random function contents
921  // after a syntax error in a function
922  // check for object-local variable definition (local)
923  if (SEqual(Idtf, C4AUL_LocalNamed) || SEqual(Idtf, C4AUL_GlobalNamed))
924  {
925  script->declarations.push_back(Parse_Var());
926  Match(ATT_SCOLON);
927  }
928  // check for variable definition (static)
929  else
930  script->declarations.push_back(Parse_ToplevelFunctionDecl());
931  break;
932  case ATT_EOF:
933  return script;
934  default:
935  UnexpectedToken("declaration");
936  }
937  first_error = true;
938  }
939  catch (C4AulError &err)
940  {
941  if (first_error)
942  {
943  ++Engine->errCnt;
945  }
946  first_error = false;
947  }
948 }
const char * getData() const
Definition: StdBuf.h:442
const C4ScriptOpDef C4ScriptOpMap[]
Definition: C4AulParse.cpp:261
C4AulScriptEngine ScriptEngine
Definition: C4Globals.cpp:43
#define C4AUL_Append
Definition: C4AulParse.cpp:31
virtual C4PropListStatic * GetPropList()
Definition: C4ScriptHost.h:50
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
std::unique_ptr<::aul::ast::FunctionDecl > Parse_ToplevelFunctionDecl()
Definition: C4AulParse.cpp:950
virtual C4Def const * GetDef() const
Definition: C4PropList.cpp:685
std::unique_ptr<::aul::ast::VarDecl > Parse_Var()
const char * what() const noexceptoverride
#define C4AUL_Include
Definition: C4AulParse.cpp:30
#define C4AUL_GlobalNamed
Definition: C4AulParse.cpp:58
friend class C4AulParseError
Definition: C4AulParse.h:101
virtual void OnError(const char *msg)=0
#define C4AUL_LocalNamed
Definition: C4AulParse.cpp:59
C4AulErrorHandler * ErrorHandler
Definition: C4Aul.h:128
void Shift()
Definition: C4AulParse.cpp:746
StdStrBuf Script
Definition: C4ScriptHost.h:90

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::Stmt > C4AulParse::Parse_Statement ( )
protected

Definition at line 1045 of file C4AulParse.cpp.

References ATT_BLOPEN, ATT_BOPEN, ATT_BOPEN2, ATT_IDTF, ATT_INT, ATT_OPERATOR, ATT_SCOLON, ATT_SET, ATT_STRING, C4AUL_Break, C4AUL_Continue, C4AUL_Do, C4AUL_Else, C4AUL_For, C4AUL_Func, C4AUL_Global, C4AUL_GlobalNamed, C4AUL_If, C4AUL_In, C4AUL_LocalNamed, C4AUL_Private, C4AUL_Protected, C4AUL_Public, C4AUL_Return, C4AUL_VarNamed, C4AUL_While, C4AulParseError, Parse_Block(), Parse_DoWhile(), Parse_Expression(), Parse_For(), Parse_ForEach(), Parse_If(), Parse_Var(), Parse_While(), SEqual(), and Shift().

Referenced by Parse_Block(), Parse_DoWhile(), Parse_For(), Parse_ForEach(), Parse_If(), and Parse_While().

1046 {
1047  const char *NodeStart = TokenSPos;
1048  std::unique_ptr<::aul::ast::Stmt> stmt;
1049  switch (TokenType)
1050  {
1051  // do we have a block start?
1052  case ATT_BLOPEN:
1053  return Parse_Block();
1054  case ATT_BOPEN:
1055  case ATT_BOPEN2:
1056  case ATT_SET:
1057  case ATT_OPERATOR:
1058  case ATT_INT:
1059  case ATT_STRING:
1060  {
1061  stmt = Parse_Expression();
1062  Match(ATT_SCOLON);
1063  return stmt;
1064  }
1065  // additional function separator
1066  case ATT_SCOLON:
1067  Shift();
1068  return ::aul::ast::Noop::New(NodeStart);
1069  case ATT_IDTF:
1070  // check for variable definition
1071  if (SEqual(Idtf, C4AUL_VarNamed) || SEqual(Idtf, C4AUL_LocalNamed) || SEqual(Idtf, C4AUL_GlobalNamed))
1072  stmt = Parse_Var();
1073  // check new-form func begin
1074  else if (SEqual(Idtf, C4AUL_Func) ||
1075  SEqual(Idtf, C4AUL_Private) ||
1076  SEqual(Idtf, C4AUL_Protected) ||
1077  SEqual(Idtf, C4AUL_Public) ||
1078  SEqual(Idtf, C4AUL_Global))
1079  {
1080  throw C4AulParseError(this, "unexpected end of function");
1081  }
1082  // get function by identifier: first check special functions
1083  else if (SEqual(Idtf, C4AUL_If)) // if
1084  {
1085  return Parse_If();
1086  }
1087  else if (SEqual(Idtf, C4AUL_Else)) // else
1088  {
1089  throw C4AulParseError(this, "misplaced 'else'");
1090  }
1091  else if (SEqual(Idtf, C4AUL_Do)) // while
1092  {
1093  stmt = Parse_DoWhile();
1094  }
1095  else if (SEqual(Idtf, C4AUL_While)) // while
1096  {
1097  return Parse_While();
1098  }
1099  else if (SEqual(Idtf, C4AUL_For)) // for
1100  {
1101  PushParsePos();
1102  Shift();
1103  // Look if it's the for([var] foo in array)-form
1104  // must be followed by a bracket
1105  Match(ATT_BOPEN);
1106  // optional var
1107  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_VarNamed))
1108  Shift();
1109  // variable and "in"
1110  if (TokenType == ATT_IDTF
1111  && GetNextToken() == ATT_IDTF
1112  && SEqual(Idtf, C4AUL_In))
1113  {
1114  // reparse the stuff in the brackets like normal statements
1115  PopParsePos();
1116  return Parse_ForEach();
1117  }
1118  else
1119  {
1120  // reparse the stuff in the brackets like normal statements
1121  PopParsePos();
1122  return Parse_For();
1123  }
1124  }
1125  else if (SEqual(Idtf, C4AUL_Return)) // return
1126  {
1127  Shift();
1128  if (TokenType == ATT_SCOLON)
1129  {
1130  // allow return; without return value (implies nil)
1131  stmt = ::aul::ast::Return::New(NodeStart, ::aul::ast::NilLit::New(NodeStart));
1132  }
1133  else
1134  {
1135  // return retval;
1136  stmt = ::aul::ast::Return::New(NodeStart, Parse_Expression());
1137  }
1138  }
1139  else if (SEqual(Idtf, C4AUL_Break)) // break
1140  {
1141  Shift();
1142  stmt = ::aul::ast::Break::New(NodeStart);
1143  }
1144  else if (SEqual(Idtf, C4AUL_Continue)) // continue
1145  {
1146  Shift();
1147  stmt = ::aul::ast::Continue::New(NodeStart);
1148  }
1149  else
1150  {
1151  stmt = Parse_Expression();
1152  }
1153  Match(ATT_SCOLON);
1154  assert(stmt);
1155  return stmt;
1156  default:
1157  UnexpectedToken("statement");
1158  }
1159 }
#define C4AUL_For
Definition: C4AulParse.cpp:49
#define C4AUL_Public
Definition: C4AulParse.cpp:41
#define C4AUL_Continue
Definition: C4AulParse.cpp:55
#define C4AUL_Func
Definition: C4AulParse.cpp:37
#define C4AUL_Return
Definition: C4AulParse.cpp:51
#define C4AUL_Private
Definition: C4AulParse.cpp:39
#define C4AUL_VarNamed
Definition: C4AulParse.cpp:60
#define C4AUL_If
Definition: C4AulParse.cpp:45
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
#define C4AUL_Global
Definition: C4AulParse.cpp:42
#define C4AUL_Do
Definition: C4AulParse.cpp:47
#define C4AUL_In
Definition: C4AulParse.cpp:50
#define C4AUL_Break
Definition: C4AulParse.cpp:54
std::unique_ptr<::aul::ast::ForLoop > Parse_For()
std::unique_ptr<::aul::ast::VarDecl > Parse_Var()
std::unique_ptr<::aul::ast::WhileLoop > Parse_While()
std::unique_ptr<::aul::ast::Block > Parse_Block()
std::unique_ptr<::aul::ast::If > Parse_If()
#define C4AUL_GlobalNamed
Definition: C4AulParse.cpp:58
friend class C4AulParseError
Definition: C4AulParse.h:101
std::unique_ptr<::aul::ast::DoLoop > Parse_DoWhile()
std::unique_ptr<::aul::ast::RangeLoop > Parse_ForEach()
#define C4AUL_Else
Definition: C4AulParse.cpp:46
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
#define C4AUL_While
Definition: C4AulParse.cpp:48
#define C4AUL_LocalNamed
Definition: C4AulParse.cpp:59
void Shift()
Definition: C4AulParse.cpp:746
#define C4AUL_Protected
Definition: C4AulParse.cpp:40

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::FunctionDecl > C4AulParse::Parse_ToplevelFunctionDecl ( )
protected

Definition at line 950 of file C4AulParse.cpp.

References ATT_IDTF, C4AUL_Func, C4AUL_Global, C4AUL_Private, C4AUL_Protected, C4AUL_Public, SEqual(), and Shift().

Referenced by Parse_DirectExec(), and Parse_Script().

951 {
952  const char *NodeStart = TokenSPos;
953  bool is_global = SEqual(Idtf, C4AUL_Global);
954  // skip access modifier
955  if (SEqual(Idtf, C4AUL_Private) ||
956  SEqual(Idtf, C4AUL_Protected) ||
957  SEqual(Idtf, C4AUL_Public) ||
958  SEqual(Idtf, C4AUL_Global))
959  {
960  Shift();
961  }
962 
963  // check for func declaration
964  if (!SEqual(Idtf, C4AUL_Func))
965  Error("Declaration expected, but found identifier: %s", Idtf);
966  Shift();
967  // get next token, must be func name
968  Check(ATT_IDTF, "function name");
969 
970  auto func = ::aul::ast::FunctionDecl::New(NodeStart, Idtf);
971  func->is_global = is_global;
972  Shift();
973  Parse_Function(func.get());
974  return func;
975 }
#define C4AUL_Public
Definition: C4AulParse.cpp:41
#define C4AUL_Func
Definition: C4AulParse.cpp:37
#define C4AUL_Private
Definition: C4AulParse.cpp:39
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
#define C4AUL_Global
Definition: C4AulParse.cpp:42
void Shift()
Definition: C4AulParse.cpp:746
#define C4AUL_Protected
Definition: C4AulParse.cpp:40

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::VarDecl > C4AulParse::Parse_Var ( )
protected

Definition at line 1635 of file C4AulParse.cpp.

References ATT_COMMA, ATT_IDTF, ATT_SCOLON, ATT_SET, C4AUL_Const, C4AUL_GlobalNamed, C4AUL_LocalNamed, C4AUL_VarNamed, aul::ast::VarDecl::Func, aul::ast::VarDecl::Global, aul::ast::VarDecl::Object, Parse_Expression(), SEqual(), and Shift().

Referenced by Parse_For(), Parse_Script(), and Parse_Statement().

1636 {
1637  auto decl = ::aul::ast::VarDecl::New(TokenSPos);
1638  if (SEqual(Idtf, C4AUL_VarNamed))
1639  {
1640  decl->scope = ::aul::ast::VarDecl::Scope::Func;
1641  }
1642  else if (SEqual(Idtf, C4AUL_LocalNamed))
1643  {
1644  decl->scope = ::aul::ast::VarDecl::Scope::Object;
1645  }
1646  else if (SEqual(Idtf, C4AUL_GlobalNamed))
1647  {
1648  decl->scope = ::aul::ast::VarDecl::Scope::Global;
1649  }
1650  else
1651  {
1652  assert(0 && "C4AulParse::Parse_Var called with invalid parse state (current token should be scope of variable)");
1653  // Uh this shouldn't happen, ever
1654  Error("internal error: C4AulParse::Parse_Var called with invalid parse state (current token should be scope of variable, but is '%s')", Idtf);
1655  }
1656  Shift();
1657  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_Const))
1658  {
1659  decl->constant = true;
1660  Shift();
1661  }
1662  while (true)
1663  {
1664  // get desired variable name
1665  Check(ATT_IDTF, "variable name");
1666  std::string identifier = Idtf;
1667  Shift();
1668  ::aul::ast::ExprPtr init;
1669  if (TokenType == ATT_SET)
1670  {
1671  Shift();
1672  init = Parse_Expression();
1673  }
1674  decl->decls.push_back({ identifier, std::move(init) });
1675  if (TokenType == ATT_SCOLON)
1676  return decl;
1677  Match(ATT_COMMA, "',' or ';'");
1678  }
1679 }
#define C4AUL_Const
Definition: C4AulParse.cpp:43
#define C4AUL_VarNamed
Definition: C4AulParse.cpp:60
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
std::unique_ptr< Expr > ExprPtr
Definition: C4AulAST.h:147
#define C4AUL_GlobalNamed
Definition: C4AulParse.cpp:58
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
#define C4AUL_LocalNamed
Definition: C4AulParse.cpp:59
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

std::unique_ptr<::aul::ast::WhileLoop > C4AulParse::Parse_While ( )
protected

Definition at line 1275 of file C4AulParse.cpp.

References ATT_BCLOSE, ATT_BOPEN, Parse_Expression(), Parse_Statement(), and Shift().

Referenced by Parse_Statement().

1276 {
1277  auto loop = ::aul::ast::WhileLoop::New(TokenSPos);
1278  Shift();
1279  // Execute condition
1280  Match(ATT_BOPEN);
1281  loop->cond = Parse_Expression();
1282  Match(ATT_BCLOSE);
1283  // Execute body
1284  loop->body = Parse_Statement();
1285  return loop;
1286 }
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:746

Here is the call graph for this function:

Here is the caller graph for this function:

void C4AulParse::Shift ( )
protected

Definition at line 746 of file C4AulParse.cpp.

Referenced by Parse_Array(), Parse_Block(), Parse_DirectExec(), Parse_DoWhile(), Parse_Expression(), Parse_ForEach(), Parse_If(), Parse_PropList(), Parse_Script(), Parse_Statement(), Parse_ToplevelFunctionDecl(), Parse_Var(), and Parse_While().

747 {
748  TokenType = GetNextToken();
749 }

Here is the caller graph for this function:

Friends And Related Function Documentation

friend class C4AulParseError
friend

Definition at line 101 of file C4AulParse.h.

Referenced by Parse_Expression(), Parse_Script(), and Parse_Statement().


The documentation for this class was generated from the following files: