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

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

Referenced by Parse_Expression().

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

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

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

Referenced by Parse_Statement().

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

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

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

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

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

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

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

Referenced by Parse_Statement().

1274 {
1275  auto loop = ::aul::ast::DoLoop::New(TokenSPos);
1276  Shift();
1277  loop->body = Parse_Statement();
1278  // Execute condition
1279  if (TokenType != ATT_IDTF || !SEqual(Idtf, C4AUL_While))
1280  UnexpectedToken("'while'");
1281  Shift();
1282  Match(ATT_BOPEN);
1283  loop->cond = Parse_Expression();
1284  Match(ATT_BCLOSE);
1285  return loop;
1286 }
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:759

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

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

1320 {
1321  auto loop = ::aul::ast::ForLoop::New(TokenSPos);
1322  Match(ATT_IDTF); Match(ATT_BOPEN);
1323  // Initialization
1324  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_VarNamed))
1325  {
1326  loop->init = Parse_Var();
1327  }
1328  else if (TokenType != ATT_SCOLON)
1329  {
1330  loop->init = Parse_Expression();
1331  }
1332  // Consume first semicolon
1333  Match(ATT_SCOLON);
1334  // Condition
1335  if (TokenType != ATT_SCOLON)
1336  {
1337  loop->cond = Parse_Expression();
1338  }
1339  // Consume second semicolon
1340  Match(ATT_SCOLON);
1341  // Incrementor
1342  if (TokenType != ATT_BCLOSE)
1343  {
1344  loop->incr = Parse_Expression();
1345  }
1346  // Consume closing bracket
1347  Match(ATT_BCLOSE);
1348  loop->body = Parse_Statement();
1349  return loop;
1350 }
#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 1352 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().

1353 {
1354  auto loop = ::aul::ast::RangeLoop::New(TokenSPos);
1355  Match(ATT_IDTF); Match(ATT_BOPEN);
1356  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_VarNamed))
1357  {
1358  loop->scoped_var = true;
1359  Shift();
1360  }
1361  // get variable name
1362  Check(ATT_IDTF, "variable name");
1363  loop->var = Idtf;
1364  Shift();
1365  if (TokenType != ATT_IDTF || !SEqual(Idtf, C4AUL_In))
1366  UnexpectedToken("'in'");
1367  Shift();
1368  // get expression for array
1369  loop->cond = Parse_Expression();
1370  Match(ATT_BCLOSE);
1371  // loop body
1372  loop->body = Parse_Statement();
1373  return loop;
1374 }
#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:759

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

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

Referenced by Parse_Statement().

1302 {
1303  auto stmt = ::aul::ast::If::New(TokenSPos);
1304  Shift();
1305  Match(ATT_BOPEN);
1306  stmt->cond = Parse_Expression();
1307  Match(ATT_BCLOSE);
1308  // parse controlled statement
1309  stmt->iftrue = Parse_Statement();
1310  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_Else))
1311  {
1312  Shift();
1313  // expect a command now
1314  stmt->iffalse = Parse_Statement();
1315  }
1316  return stmt;
1317 }
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:759

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

1238 {
1239  auto proplist = ::aul::ast::ProplistLit::New(TokenSPos);
1240  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_New))
1241  {
1242  Shift();
1243  proplist->values.emplace_back(Strings.P[P_Prototype].GetCStr(), Parse_Expression());
1244  }
1245  Match(ATT_BLOPEN);
1246  while (TokenType != ATT_BLCLOSE)
1247  {
1248  std::string key;
1249  if (TokenType == ATT_IDTF)
1250  {
1251  key = Idtf;
1252  Shift();
1253  }
1254  else if (TokenType == ATT_STRING)
1255  {
1256  key = cStr->GetCStr();
1257  Shift();
1258  }
1259  else UnexpectedToken("string or identifier");
1260  if (TokenType != ATT_COLON && TokenType != ATT_SET)
1261  UnexpectedToken("':' or '='");
1262  Shift();
1263  proplist->values.emplace_back(key, Parse_Expression());
1264  if (TokenType == ATT_COMMA)
1265  Shift();
1266  else if (TokenType != ATT_BLCLOSE)
1267  UnexpectedToken("'}' or ','");
1268  }
1269  Shift();
1270  return proplist;
1271 }
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:759

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

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

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

964 {
965  const char *NodeStart = TokenSPos;
966  bool is_global = SEqual(Idtf, C4AUL_Global);
967  // skip access modifier
968  if (SEqual(Idtf, C4AUL_Private) ||
969  SEqual(Idtf, C4AUL_Protected) ||
970  SEqual(Idtf, C4AUL_Public) ||
971  SEqual(Idtf, C4AUL_Global))
972  {
973  Shift();
974  }
975 
976  // check for func declaration
977  if (!SEqual(Idtf, C4AUL_Func))
978  Error("Declaration expected, but found identifier: %s", Idtf);
979  Shift();
980  // get next token, must be func name
981  Check(ATT_IDTF, "function name");
982 
983  auto func = ::aul::ast::FunctionDecl::New(NodeStart, Idtf);
984  func->is_global = is_global;
985  Shift();
986  Parse_Function(func.get());
987  return func;
988 }
#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:759
#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 1648 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().

1649 {
1650  auto decl = ::aul::ast::VarDecl::New(TokenSPos);
1651  if (SEqual(Idtf, C4AUL_VarNamed))
1652  {
1653  decl->scope = ::aul::ast::VarDecl::Scope::Func;
1654  }
1655  else if (SEqual(Idtf, C4AUL_LocalNamed))
1656  {
1657  decl->scope = ::aul::ast::VarDecl::Scope::Object;
1658  }
1659  else if (SEqual(Idtf, C4AUL_GlobalNamed))
1660  {
1661  decl->scope = ::aul::ast::VarDecl::Scope::Global;
1662  }
1663  else
1664  {
1665  assert(0 && "C4AulParse::Parse_Var called with invalid parse state (current token should be scope of variable)");
1666  // Uh this shouldn't happen, ever
1667  Error("internal error: C4AulParse::Parse_Var called with invalid parse state (current token should be scope of variable, but is '%s')", Idtf);
1668  }
1669  Shift();
1670  if (TokenType == ATT_IDTF && SEqual(Idtf, C4AUL_Const))
1671  {
1672  decl->constant = true;
1673  Shift();
1674  }
1675  while (true)
1676  {
1677  // get desired variable name
1678  Check(ATT_IDTF, "variable name");
1679  std::string identifier = Idtf;
1680  Shift();
1681  ::aul::ast::ExprPtr init;
1682  if (TokenType == ATT_SET)
1683  {
1684  Shift();
1685  init = Parse_Expression();
1686  }
1687  decl->decls.push_back({ identifier, std::move(init) });
1688  if (TokenType == ATT_SCOLON)
1689  return decl;
1690  Match(ATT_COMMA, "',' or ';'");
1691  }
1692 }
#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:759

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

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

Referenced by Parse_Statement().

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

Here is the call graph for this function:

Here is the caller graph for this function:

void C4AulParse::Shift ( )
protected

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

760 {
761  TokenType = GetNextToken();
762 }

Here is the caller graph for this function:

Friends And Related Function Documentation

friend class C4AulParseError
friend

Definition at line 102 of file C4AulParse.h.

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


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