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 113 of file C4AulParse.cpp.

113  :
114  Fn(0), Host(a), pOrgScript(a), Engine(a->Engine),
115  SPos(a->Script.getData()), TokenSPos(SPos),
116  TokenType(ATT_INVALID),
117  ContextToExecIn(nullptr)
118 { }
#define a
C4AulParse::C4AulParse ( C4AulScriptFunc Fn,
C4AulScriptContext context,
C4AulScriptEngine Engine 
)

Definition at line 120 of file C4AulParse.cpp.

120  :
121  Fn(Fn), Host(nullptr), pOrgScript(nullptr), Engine(Engine),
122  SPos(Fn->Script), TokenSPos(SPos),
123  TokenType(ATT_INVALID),
124  ContextToExecIn(context)
125 { }
const char * Script
C4AulParse::~C4AulParse ( )

Definition at line 127 of file C4AulParse.cpp.

128 {
129  ClearToken();
130 }

Member Function Documentation

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

Definition at line 1203 of file C4AulParse.cpp.

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

Referenced by Parse_Expression().

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

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 1042 of file C4AulParse.cpp.

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

Referenced by Parse_Statement().

1043 {
1044  auto block = ::aul::ast::Block::New(TokenSPos);
1045  Match(ATT_BLOPEN);
1046  while (TokenType != ATT_BLCLOSE)
1047  {
1048  block->children.push_back(Parse_Statement());
1049  }
1050  Shift();
1051  return block;
1052 }
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:755

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 852 of file C4AulParse.cpp.

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

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

853 {
854  // get first token
855  Shift();
856  // Synthesize a wrapping function which we can call
857  std::unique_ptr<::aul::ast::FunctionDecl> func;
858  if (whole_function)
859  {
861  }
862  else
863  {
864  auto expr = Parse_Expression();
865  func = std::make_unique<::aul::ast::FunctionDecl>("$internal$eval");
866  func->body = std::make_unique<::aul::ast::Block>();
867  func->body->children.push_back(std::make_unique<::aul::ast::Return>(std::move(expr)));
868  }
869  Match(ATT_EOF);
870  return func;
871 }
std::unique_ptr<::aul::ast::FunctionDecl > Parse_ToplevelFunctionDecl()
Definition: C4AulParse.cpp:959
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
void Shift()
Definition: C4AulParse.cpp:755

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 1269 of file C4AulParse.cpp.

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

Referenced by Parse_Statement().

1270 {
1271  auto loop = ::aul::ast::DoLoop::New(TokenSPos);
1272  Shift();
1273  loop->body = Parse_Statement();
1274  // Execute condition
1275  if (TokenType != ATT_IDTF || !SEqual(Idtf, C4AUL_While))
1276  UnexpectedToken("'while'");
1277  Shift();
1278  Match(ATT_BOPEN);
1279  loop->cond = Parse_Expression();
1280  Match(ATT_BCLOSE);
1281  return loop;
1282 }
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
#define C4AUL_While
Definition: C4AulParse.cpp:57
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:755

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 1379 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().

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

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 1315 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().

1316 {
1317  auto loop = ::aul::ast::ForLoop::New(TokenSPos);
1318  Match(ATT_IDTF); Match(ATT_BOPEN);
1319  // Initialization
1320  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_VarNamed))
1321  {
1322  loop->init = Parse_Var();
1323  }
1324  else if (TokenType != ATT_SCOLON)
1325  {
1326  loop->init = Parse_Expression();
1327  }
1328  // Consume first semicolon
1329  Match(ATT_SCOLON);
1330  // Condition
1331  if (TokenType != ATT_SCOLON)
1332  {
1333  loop->cond = Parse_Expression();
1334  }
1335  // Consume second semicolon
1336  Match(ATT_SCOLON);
1337  // Incrementor
1338  if (TokenType != ATT_BCLOSE)
1339  {
1340  loop->incr = Parse_Expression();
1341  }
1342  // Consume closing bracket
1343  Match(ATT_BCLOSE);
1344  loop->body = Parse_Statement();
1345  return loop;
1346 }
#define C4AUL_VarNamed
Definition: C4AulParse.cpp:69
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
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 1348 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().

1349 {
1350  auto loop = ::aul::ast::RangeLoop::New(TokenSPos);
1351  Match(ATT_IDTF); Match(ATT_BOPEN);
1352  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_VarNamed))
1353  {
1354  loop->scoped_var = true;
1355  Shift();
1356  }
1357  // get variable name
1358  Check(ATT_IDTF, "variable name");
1359  loop->var = Idtf;
1360  Shift();
1361  if (TokenType != ATT_IDTF || !SEqual(Idtf, C4AUL_In))
1362  UnexpectedToken("'in'");
1363  Shift();
1364  // get expression for array
1365  loop->cond = Parse_Expression();
1366  Match(ATT_BCLOSE);
1367  // loop body
1368  loop->body = Parse_Statement();
1369  return loop;
1370 }
#define C4AUL_VarNamed
Definition: C4AulParse.cpp:69
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
#define C4AUL_In
Definition: C4AulParse.cpp:59
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:755

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 1297 of file C4AulParse.cpp.

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

Referenced by Parse_Statement().

1298 {
1299  auto stmt = ::aul::ast::If::New(TokenSPos);
1300  Shift();
1301  Match(ATT_BOPEN);
1302  stmt->cond = Parse_Expression();
1303  Match(ATT_BCLOSE);
1304  // parse controlled statement
1305  stmt->iftrue = Parse_Statement();
1306  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_Else))
1307  {
1308  Shift();
1309  // expect a command now
1310  stmt->iffalse = Parse_Statement();
1311  }
1312  return stmt;
1313 }
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
#define C4AUL_Else
Definition: C4AulParse.cpp:55
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:755

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 1233 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().

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

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 873 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().

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

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

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 959 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().

960 {
961  const char *NodeStart = TokenSPos;
962  bool is_global = SEqual(Idtf, C4AUL_Global);
963  // skip access modifier
964  if (SEqual(Idtf, C4AUL_Private) ||
965  SEqual(Idtf, C4AUL_Protected) ||
966  SEqual(Idtf, C4AUL_Public) ||
967  SEqual(Idtf, C4AUL_Global))
968  {
969  Shift();
970  }
971 
972  // check for func declaration
973  if (!SEqual(Idtf, C4AUL_Func))
974  Error("Declaration expected, but found identifier: %s", Idtf);
975  Shift();
976  // get next token, must be func name
977  Check(ATT_IDTF, "function name");
978 
979  auto func = ::aul::ast::FunctionDecl::New(NodeStart, Idtf);
980  func->is_global = is_global;
981  Shift();
982  Parse_Function(func.get());
983  return func;
984 }
#define C4AUL_Public
Definition: C4AulParse.cpp:50
#define C4AUL_Func
Definition: C4AulParse.cpp:46
#define C4AUL_Private
Definition: C4AulParse.cpp:48
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:97
#define C4AUL_Global
Definition: C4AulParse.cpp:51
void Shift()
Definition: C4AulParse.cpp:755
#define C4AUL_Protected
Definition: C4AulParse.cpp:49

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 1644 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().

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

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 1284 of file C4AulParse.cpp.

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

Referenced by Parse_Statement().

1285 {
1286  auto loop = ::aul::ast::WhileLoop::New(TokenSPos);
1287  Shift();
1288  // Execute condition
1289  Match(ATT_BOPEN);
1290  loop->cond = Parse_Expression();
1291  Match(ATT_BCLOSE);
1292  // Execute body
1293  loop->body = Parse_Statement();
1294  return loop;
1295 }
std::unique_ptr<::aul::ast::Expr > Parse_Expression(int iParentPrio=-1)
std::unique_ptr<::aul::ast::Stmt > Parse_Statement()
void Shift()
Definition: C4AulParse.cpp:755

Here is the call graph for this function:

Here is the caller graph for this function:

void C4AulParse::Shift ( )
protected

Definition at line 755 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().

756 {
757  TokenType = GetNextToken();
758 }

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: