871 skipWhitespaceAndComments();
872 location.location = p;
873 currentType = matchNextToken();
876 void match (TokenType expected)
878 if (currentType != expected)
879 location.throwError (
"Found " + getTokenName (currentType) +
" when expecting " + getTokenName (expected));
884 bool matchIf (TokenType expected) {
if (currentType == expected) { skip();
return true; }
return false; }
885 bool matchesAny (TokenType t1, TokenType t2)
const {
return currentType == t1 || currentType == t2; }
886 bool matchesAny (TokenType t1, TokenType t2, TokenType t3)
const {
return matchesAny (t1, t2) || currentType == t3; }
889 TokenType currentType;
895 static bool isIdentifierStart (
juce_wchar c)
noexcept {
return CharacterFunctions::isLetter (c) || c ==
'_'; }
896 static bool isIdentifierBody (
juce_wchar c)
noexcept {
return CharacterFunctions::isLetterOrDigit (c) || c ==
'_'; }
898 TokenType matchNextToken()
900 if (isIdentifierStart (*p))
903 while (isIdentifierBody (*++end)) {}
905 auto len = (
size_t) (end - p);
906 #define JUCE_JS_COMPARE_KEYWORD(name, str) if (len == sizeof (str) - 1 && matchToken (TokenTypes::name, len)) return TokenTypes::name;
907 JUCE_JS_KEYWORDS (JUCE_JS_COMPARE_KEYWORD)
909 currentValue =
String (p, end); p = end;
910 return TokenTypes::identifier;
915 if (parseHexLiteral() || parseFloatLiteral() || parseOctalLiteral() || parseDecimalLiteral())
916 return TokenTypes::literal;
918 location.throwError (
"Syntax error in numeric constant");
921 if (parseStringLiteral (*p) || (*p ==
'.' && parseFloatLiteral()))
922 return TokenTypes::literal;
924 #define JUCE_JS_COMPARE_OPERATOR(name, str) if (matchToken (TokenTypes::name, sizeof (str) - 1)) return TokenTypes::name;
925 JUCE_JS_OPERATORS (JUCE_JS_COMPARE_OPERATOR)
928 location.throwError (
"Unexpected character '" + String::charToString (*p) +
"' in source");
930 return TokenTypes::eof;
933 bool matchToken (TokenType name,
size_t len)
noexcept
936 p += (
int) len;
return true;
939 void skipWhitespaceAndComments()
949 if (c2 ==
'/') { p = CharacterFunctions::find (p, (
juce_wchar)
'\n');
continue; }
953 location.location = p;
955 if (p.
isEmpty()) location.throwError (
"Unterminated '/*' comment");
964 bool parseStringLiteral (
juce_wchar quoteType)
966 if (quoteType !=
'"' && quoteType !=
'\'')
969 auto r = JSON::parseQuotedString (p, currentValue);
970 if (r.failed()) location.throwError (r.getErrorMessage());
974 bool parseHexLiteral()
976 if (*p !=
'0' || (p[1] !=
'x' && p[1] !=
'X'))
return false;
979 int64 v = CharacterFunctions::getHexDigitValue (*++t);
980 if (v < 0)
return false;
984 auto digit = CharacterFunctions::getHexDigitValue (*++t);
985 if (digit < 0)
break;
989 currentValue = v; p = t;
993 bool parseFloatLiteral()
997 while (t.isDigit()) { ++t; ++numDigits; }
999 const bool hasPoint = (*t ==
'.');
1002 while ((++t).isDigit()) ++numDigits;
1008 const bool hasExponent = (c ==
'e' || c ==
'E');
1013 if (c ==
'+' || c ==
'-') ++t;
1014 if (! t.isDigit())
return false;
1015 while ((++t).isDigit()) {}
1018 if (! (hasExponent || hasPoint))
return false;
1020 currentValue = CharacterFunctions::getDoubleValue (p); p = t;
1024 bool parseOctalLiteral()
1028 if (v != 0)
return false;
1032 auto digit = (
int) (*++t -
'0');
1034 else if (
isPositiveAndBelow (digit, 10)) location.throwError (
"Decimal digit in octal constant");
1038 currentValue = v; p = t;
1042 bool parseDecimalLiteral()
1048 auto digit = (
int) (*p -
'0');
1067 while (currentType != TokenTypes::closeBrace && currentType != TokenTypes::eof)
1068 b->statements.add (parseStatement());
1075 match (TokenTypes::openParen);
1077 while (currentType != TokenTypes::closeParen)
1079 auto paramName = currentValue.toString();
1080 match (TokenTypes::identifier);
1081 fo.parameters.add (paramName);
1083 if (currentType != TokenTypes::closeParen)
1084 match (TokenTypes::comma);
1087 match (TokenTypes::closeParen);
1088 fo.body.reset (parseBlock());
1093 ExpPtr lhs (parseLogicOperator());
1095 if (matchIf (TokenTypes::question))
return parseTernaryOperator (lhs);
1096 if (matchIf (TokenTypes::assign)) {
ExpPtr rhs (parseExpression());
return new Assignment (location, lhs, rhs); }
1097 if (matchIf (TokenTypes::plusEquals))
return parseInPlaceOpExpression<AdditionOp> (lhs);
1098 if (matchIf (TokenTypes::minusEquals))
return parseInPlaceOpExpression<SubtractionOp> (lhs);
1099 if (matchIf (TokenTypes::timesEquals))
return parseInPlaceOpExpression<MultiplyOp> (lhs);
1100 if (matchIf (TokenTypes::divideEquals))
return parseInPlaceOpExpression<DivideOp> (lhs);
1101 if (matchIf (TokenTypes::moduloEquals))
return parseInPlaceOpExpression<ModuloOp> (lhs);
1102 if (matchIf (TokenTypes::leftShiftEquals))
return parseInPlaceOpExpression<LeftShiftOp> (lhs);
1103 if (matchIf (TokenTypes::rightShiftEquals))
return parseInPlaceOpExpression<RightShiftOp> (lhs);
1109 void throwError (
const String& err)
const { location.throwError (err); }
1111 template <
typename OpType>
1114 ExpPtr rhs (parseExpression());
1116 return new SelfAssignment (location, bareLHS,
new OpType (location, lhs, rhs));
1121 match (TokenTypes::openBrace);
1123 match (TokenTypes::closeBrace);
1129 if (currentType == TokenTypes::openBrace)
return parseBlock();
1130 if (matchIf (TokenTypes::var))
return parseVar();
1131 if (matchIf (TokenTypes::if_))
return parseIf();
1132 if (matchIf (TokenTypes::while_))
return parseDoOrWhileLoop (
false);
1133 if (matchIf (TokenTypes::do_))
return parseDoOrWhileLoop (
true);
1134 if (matchIf (TokenTypes::for_))
return parseForLoop();
1135 if (matchIf (TokenTypes::return_))
return parseReturn();
1136 if (matchIf (TokenTypes::break_))
return new BreakStatement (location);
1138 if (matchIf (TokenTypes::function))
return parseFunction();
1139 if (matchIf (TokenTypes::semicolon))
return new Statement (location);
1140 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1141 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1143 if (matchesAny (TokenTypes::openParen, TokenTypes::openBracket))
1144 return matchEndOfStatement (parseFactor());
1146 if (matchesAny (TokenTypes::identifier, TokenTypes::literal, TokenTypes::minus))
1147 return matchEndOfStatement (parseExpression());
1149 throwError (
"Found " + getTokenName (currentType) +
" when expecting a statement");
1159 match (TokenTypes::openParen);
1160 s->condition.
reset (parseExpression());
1161 match (TokenTypes::closeParen);
1162 s->trueBranch.
reset (parseStatement());
1163 s->falseBranch.
reset (matchIf (TokenTypes::else_) ? parseStatement() :
new Statement (location));
1169 if (matchIf (TokenTypes::semicolon))
1173 matchIf (TokenTypes::semicolon);
1180 s->name = parseIdentifier();
1181 s->initialiser.
reset (matchIf (TokenTypes::assign) ? parseExpression() :
new Expression (location));
1183 if (matchIf (TokenTypes::comma))
1186 block->statements.add (std::move (s));
1187 block->statements.add (parseVar());
1191 match (TokenTypes::semicolon);
1198 auto fn = parseFunctionDefinition (name);
1201 throwError (
"Functions defined at statement-level must have a name");
1210 match (TokenTypes::openParen);
1211 s->initialiser.
reset (parseStatement());
1213 if (matchIf (TokenTypes::semicolon))
1217 s->condition.
reset (parseExpression());
1218 match (TokenTypes::semicolon);
1221 if (matchIf (TokenTypes::closeParen))
1225 s->iterator.
reset (parseExpression());
1226 match (TokenTypes::closeParen);
1229 s->body.
reset (parseStatement());
1233 Statement* parseDoOrWhileLoop (
bool isDoLoop)
1241 s->body.
reset (parseBlock());
1242 match (TokenTypes::while_);
1245 match (TokenTypes::openParen);
1246 s->condition.
reset (parseExpression());
1247 match (TokenTypes::closeParen);
1250 s->body.
reset (parseStatement());
1258 if (currentType == TokenTypes::identifier)
1261 match (TokenTypes::identifier);
1267 auto functionStart = location.location;
1269 if (currentType == TokenTypes::identifier)
1270 functionName = parseIdentifier();
1273 parseFunctionParamsAndBody (*fo);
1274 fo->functionCode =
String (functionStart, location.location);
1281 s->object = std::move (function);
1282 match (TokenTypes::openParen);
1284 while (currentType != TokenTypes::closeParen)
1286 s->arguments.add (parseExpression());
1287 if (currentType != TokenTypes::closeParen)
1288 match (TokenTypes::comma);
1291 return matchCloseParen (s.
release());
1298 if (matchIf (TokenTypes::dot))
1299 return parseSuffixes (
new DotOperator (location, input, parseIdentifier()));
1301 if (currentType == TokenTypes::openParen)
1302 return parseSuffixes (parseFunctionCall (
new FunctionCall (location), input));
1304 if (matchIf (TokenTypes::openBracket))
1307 s->object = std::move (input);
1308 s->index.
reset (parseExpression());
1309 match (TokenTypes::closeBracket);
1310 return parseSuffixes (s.
release());
1313 if (matchIf (TokenTypes::plusplus))
return parsePostIncDec<AdditionOp> (input);
1314 if (matchIf (TokenTypes::minusminus))
return parsePostIncDec<SubtractionOp> (input);
1321 if (currentType == TokenTypes::identifier)
return parseSuffixes (
new UnqualifiedName (location, parseIdentifier()));
1322 if (matchIf (TokenTypes::openParen))
return parseSuffixes (matchCloseParen (parseExpression()));
1323 if (matchIf (TokenTypes::true_))
return parseSuffixes (
new LiteralValue (location, (
int) 1));
1324 if (matchIf (TokenTypes::false_))
return parseSuffixes (
new LiteralValue (location, (
int) 0));
1325 if (matchIf (TokenTypes::null_))
return parseSuffixes (
new LiteralValue (location,
var()));
1326 if (matchIf (TokenTypes::undefined))
return parseSuffixes (
new Expression (location));
1328 if (currentType == TokenTypes::literal)
1330 var v (currentValue); skip();
1334 if (matchIf (TokenTypes::openBrace))
1338 while (currentType != TokenTypes::closeBrace)
1340 auto memberName = currentValue.toString();
1341 match ((currentType == TokenTypes::literal && currentValue.isString())
1342 ? TokenTypes::literal : TokenTypes::identifier);
1343 match (TokenTypes::colon);
1345 e->names.add (memberName);
1346 e->initialisers.add (parseExpression());
1348 if (currentType != TokenTypes::closeBrace)
1349 match (TokenTypes::comma);
1352 match (TokenTypes::closeBrace);
1353 return parseSuffixes (e.
release());
1356 if (matchIf (TokenTypes::openBracket))
1360 while (currentType != TokenTypes::closeBracket)
1362 e->values.add (parseExpression());
1364 if (currentType != TokenTypes::closeBracket)
1365 match (TokenTypes::comma);
1368 match (TokenTypes::closeBracket);
1369 return parseSuffixes (e.
release());
1372 if (matchIf (TokenTypes::function))
1375 var fn = parseFunctionDefinition (name);
1378 throwError (
"Inline functions definitions cannot have a name");
1383 if (matchIf (TokenTypes::new_))
1387 while (matchIf (TokenTypes::dot))
1390 return parseFunctionCall (
new NewOperator (location), name);
1393 throwError (
"Found " + getTokenName (currentType) +
" when expecting an expression");
1397 template <
typename OpType>
1402 return new SelfAssignment (location, e,
new OpType (location, lhs, one));
1405 template <
typename OpType>
1410 return new PostAssignment (location, e,
new OpType (location, lhs2, one));
1417 f->arguments.add (parseUnary());
1424 if (matchIf (TokenTypes::logicalNot)) {
ExpPtr a (
new LiteralValue (location, (
int) 0)), b (parseUnary());
return new EqualsOp (location, a, b); }
1425 if (matchIf (TokenTypes::plusplus))
return parsePreIncDec<AdditionOp>();
1426 if (matchIf (TokenTypes::minusminus))
return parsePreIncDec<SubtractionOp>();
1427 if (matchIf (TokenTypes::typeof_))
return parseTypeof();
1429 return parseFactor();
1438 if (matchIf (TokenTypes::times)) {
ExpPtr b (parseUnary()); a.
reset (
new MultiplyOp (location, a, b)); }
1439 else if (matchIf (TokenTypes::divide)) {
ExpPtr b (parseUnary()); a.
reset (
new DivideOp (location, a, b)); }
1440 else if (matchIf (TokenTypes::modulo)) {
ExpPtr b (parseUnary()); a.
reset (
new ModuloOp (location, a, b)); }
1449 ExpPtr a (parseMultiplyDivide());
1453 if (matchIf (TokenTypes::plus)) {
ExpPtr b (parseMultiplyDivide()); a.
reset (
new AdditionOp (location, a, b)); }
1454 else if (matchIf (TokenTypes::minus)) {
ExpPtr b (parseMultiplyDivide()); a.
reset (
new SubtractionOp (location, a, b)); }
1463 ExpPtr a (parseAdditionSubtraction());
1467 if (matchIf (TokenTypes::leftShift)) {
ExpPtr b (parseExpression()); a.
reset (
new LeftShiftOp (location, a, b)); }
1468 else if (matchIf (TokenTypes::rightShift)) {
ExpPtr b (parseExpression()); a.
reset (
new RightShiftOp (location, a, b)); }
1478 ExpPtr a (parseShiftOperator());
1482 if (matchIf (TokenTypes::equals)) {
ExpPtr b (parseShiftOperator()); a.
reset (
new EqualsOp (location, a, b)); }
1483 else if (matchIf (TokenTypes::notEquals)) {
ExpPtr b (parseShiftOperator()); a.
reset (
new NotEqualsOp (location, a, b)); }
1484 else if (matchIf (TokenTypes::typeEquals)) {
ExpPtr b (parseShiftOperator()); a.
reset (
new TypeEqualsOp (location, a, b)); }
1485 else if (matchIf (TokenTypes::typeNotEquals)) {
ExpPtr b (parseShiftOperator()); a.
reset (
new TypeNotEqualsOp (location, a, b)); }
1486 else if (matchIf (TokenTypes::lessThan)) {
ExpPtr b (parseShiftOperator()); a.
reset (
new LessThanOp (location, a, b)); }
1488 else if (matchIf (TokenTypes::greaterThan)) {
ExpPtr b (parseShiftOperator()); a.
reset (
new GreaterThanOp (location, a, b)); }
1498 ExpPtr a (parseComparator());
1502 if (matchIf (TokenTypes::logicalAnd)) {
ExpPtr b (parseComparator()); a.
reset (
new LogicalAndOp (location, a, b)); }
1503 else if (matchIf (TokenTypes::logicalOr)) {
ExpPtr b (parseComparator()); a.
reset (
new LogicalOrOp (location, a, b)); }
1504 else if (matchIf (TokenTypes::bitwiseAnd)) {
ExpPtr b (parseComparator()); a.
reset (
new BitwiseAndOp (location, a, b)); }
1505 else if (matchIf (TokenTypes::bitwiseOr)) {
ExpPtr b (parseComparator()); a.
reset (
new BitwiseOrOp (location, a, b)); }
1506 else if (matchIf (TokenTypes::bitwiseXor)) {
ExpPtr b (parseComparator()); a.
reset (
new BitwiseXorOp (location, a, b)); }
1516 e->condition = std::move (condition);
1517 e->trueBranch.
reset (parseExpression());
1518 match (TokenTypes::colon);
1519 e->falseBranch.
reset (parseExpression());
1699 setMethod (
"abs", Math_abs); setMethod (
"round", Math_round);
1700 setMethod (
"random", Math_random); setMethod (
"randInt", Math_randInt);
1701 setMethod (
"min", Math_min); setMethod (
"max", Math_max);
1702 setMethod (
"range", Math_range); setMethod (
"sign", Math_sign);
1703 setMethod (
"toDegrees", Math_toDegrees); setMethod (
"toRadians", Math_toRadians);
1704 setMethod (
"sin", Math_sin); setMethod (
"asin", Math_asin);
1705 setMethod (
"sinh", Math_sinh); setMethod (
"asinh", Math_asinh);
1706 setMethod (
"cos", Math_cos); setMethod (
"acos", Math_acos);
1707 setMethod (
"cosh", Math_cosh); setMethod (
"acosh", Math_acosh);
1708 setMethod (
"tan", Math_tan); setMethod (
"atan", Math_atan);
1709 setMethod (
"tanh", Math_tanh); setMethod (
"atanh", Math_atanh);
1710 setMethod (
"log", Math_log); setMethod (
"log10", Math_log10);
1711 setMethod (
"exp", Math_exp); setMethod (
"pow", Math_pow);
1712 setMethod (
"sqr", Math_sqr); setMethod (
"sqrt", Math_sqrt);
1713 setMethod (
"ceil", Math_ceil); setMethod (
"floor", Math_floor);
1714 setMethod (
"hypot", Math_hypot);
1719 setProperty (
"SQRT1_2",
std::sqrt (0.5));
1720 setProperty (
"LN2",
std::log (2.0));
1721 setProperty (
"LN10",
std::log (10.0));
1726 static var Math_random (
Args) {
return Random::getSystemRandom().nextDouble(); }
1727 static var Math_randInt (
Args a) {
return Random::getSystemRandom().nextInt (
Range<int> (getInt (a, 0), getInt (a, 1))); }
1728 static var Math_abs (
Args a) {
return isInt (a, 0) ?
var (std::abs (getInt (a, 0))) :
var (std::abs (getDouble (a, 0))); }
1730 static var Math_sign (
Args a) {
return isInt (a, 0) ?
var (sign (getInt (a, 0))) :
var (sign (getDouble (a, 0))); }
1731 static var Math_range (
Args a) {
return isInt (a, 0) ?
var (
jlimit (getInt (a, 1), getInt (a, 2), getInt (a, 0))) :
var (
jlimit (getDouble (a, 1), getDouble (a, 2), getDouble (a, 0))); }
1732 static var Math_min (
Args a) {
return (isInt (a, 0) && isInt (a, 1)) ?
var (
jmin (getInt (a, 0), getInt (a, 1))) :
var (
jmin (getDouble (a, 0), getDouble (a, 1))); }
1733 static var Math_max (
Args a) {
return (isInt (a, 0) && isInt (a, 1)) ?
var (
jmax (getInt (a, 0), getInt (a, 1))) :
var (
jmax (getDouble (a, 0), getDouble (a, 1))); }
1748 static var Math_pow (
Args a) {
return std::pow (getDouble (a, 0), getDouble (a, 1)); }
1749 static var Math_sqr (
Args a) {
return square (getDouble (a, 0)); }
1753 static var Math_hypot (
Args a) {
return std::hypot (getDouble (a, 0), getDouble (a, 1)); }
1757 static var Math_asinh (
Args a) {
return asinh (getDouble (a, 0)); }
1758 static var Math_acosh (
Args a) {
return acosh (getDouble (a, 0)); }
1759 static var Math_atanh (
Args a) {
return atanh (getDouble (a, 0)); }
1762 template <
typename Type>
static Type sign (Type n)
noexcept {
return n > 0 ? (Type) 1 : (n < 0 ? (Type) -1 : 0); }