Changeset 44840 in vbox for trunk/src/VBox
- Timestamp:
- Feb 26, 2013 11:41:06 PM (12 years ago)
- Location:
- trunk/src/VBox/Storage/testcase
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Storage/testcase/VDScript.cpp
r44811 r44840 36 36 * code. Could be used as a scripting language for the VBox debugger for example or in the scm 37 37 * tool to automatically rewrite C code using the AST VDSCript generates... 38 * 39 * The syntax of VDSCript is derived from the C syntax. The syntax of C in BNF was taken 40 * from: http://www.csci.csusb.edu/dick/samples/c.syntax.html 41 * and: http://slps.github.com/zoo/c/iso-9899-tc3.html 42 * and: http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf 38 43 */ 39 44 #define LOGGROUP LOGGROUP_DEFAULT … … 42 47 #include <iprt/mem.h> 43 48 #include <iprt/ctype.h> 49 #include <iprt/stream.h> 44 50 45 51 #include <VBox/log.h> … … 47 53 #include "VDScript.h" 48 54 #include "VDScriptAst.h" 49 50 /**51 * Position information.52 */53 typedef struct VDSRCPOS54 {55 /** Line in the source. */56 unsigned iLine;57 /** Current start character .*/58 unsigned iChStart;59 /** Current end character. */60 unsigned iChEnd;61 } VDSRCPOS;62 /** Pointer to a source position. */63 typedef struct VDSRCPOS *PVDSRCPOS;64 55 65 56 /** … … 102 93 VDSCRIPTTOKENKEYWORD_WHILE, 103 94 VDSCRIPTTOKENKEYWORD_BREAK, 95 VDSCRIPTTOKENKEYWORD_FALSE, 96 VDSCRIPTTOKENKEYWORD_TRUE, 104 97 VDSCRIPTTOKENKEYWORD_ELSE, 105 98 VDSCRIPTTOKENKEYWORD_CASE, … … 135 128 struct 136 129 { 137 /** Flag whether the number is negative. */ 138 bool fNegative; 139 union 140 { 141 uint64_t u64; 142 int64_t i64; 143 }; 130 uint64_t u64; 144 131 } NumConst; 145 132 /** String constant */ … … 297 284 {"<", 1}, 298 285 {">", 1}, 299 {"!", 1} 286 {"!", 1}, 287 {"~", 1} 300 288 }; 301 289 … … 339 327 {"while", 5, VDSCRIPTTOKENKEYWORD_WHILE}, 340 328 {"break", 5, VDSCRIPTTOKENKEYWORD_BREAK}, 329 {"false", 5, VDSCRIPTTOKENKEYWORD_FALSE}, 330 {"true", 4, VDSCRIPTTOKENKEYWORD_TRUE}, 341 331 {"else", 4, VDSCRIPTTOKENKEYWORD_ELSE}, 342 332 {"case", 4, VDSCRIPTTOKENKEYWORD_CASE}, … … 348 338 static int vdScriptParseCompoundStatement(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTSTMT *ppAstNodeCompound); 349 339 static int vdScriptParseStatement(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTSTMT *ppAstNodeStmt); 340 static int vdScriptParseExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr); 341 static int vdScriptParseAssignmentExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr); 350 342 351 343 /** … … 458 450 vdScriptTokenizerSkipCh(pTokenizer); 459 451 } 452 453 if (!vdScriptTokenizerIsEos(pTokenizer)) 454 vdScriptTokenizerSkipCh(pTokenizer); 455 if (!vdScriptTokenizerIsEos(pTokenizer)) 456 vdScriptTokenizerSkipCh(pTokenizer); 460 457 } 461 458 … … 469 466 DECLINLINE(void) vdScriptTokenizerSkipWhitespace(PVDTOKENIZER pTokenizer) 470 467 { 471 while (true) 472 { 473 while ( !vdScriptTokenizerIsEos(pTokenizer) 474 && ( vdScriptTokenizerGetCh(pTokenizer) == ' ' 475 || vdScriptTokenizerGetCh(pTokenizer) == '\t')) 468 while (!vdScriptTokenizerIsEos(pTokenizer)) 469 { 470 while ( vdScriptTokenizerGetCh(pTokenizer) == ' ' 471 || vdScriptTokenizerGetCh(pTokenizer) == '\t') 476 472 vdScriptTokenizerSkipCh(pTokenizer); 477 473 … … 481 477 if ( vdScriptTokenizerGetCh(pTokenizer) == '/' 482 478 && vdScriptTokenizerPeekCh(pTokenizer) == '*') 479 { 480 vdScriptTokenizerSkipCh(pTokenizer); 481 vdScriptTokenizerSkipCh(pTokenizer); 483 482 vdScriptTokenizerSkipComment(pTokenizer); 483 } 484 484 else 485 485 break; /* Skipped everything, next is some real content. */ … … 545 545 { 546 546 unsigned uBase = 10; 547 size_t cchNumber = 0;547 char *pszNext = NULL; 548 548 549 549 Assert(RT_C_IS_DIGIT(vdScriptTokenizerGetCh(pTokenizer))); 550 550 551 if (vdScriptTokenizerGetCh(pTokenizer) == '0') 552 { 553 /* Maybe octal or hex representation. */ 554 } 551 /* Let RTStrToUInt64Ex() do all the work, looks C compliant :). */ 552 pToken->enmClass = VDTOKENCLASS_NUMCONST; 553 int rc = RTStrToUInt64Ex(pTokenizer->pszInput, &pszNext, 0, &pToken->Class.NumConst.u64); 554 Assert(RT_SUCCESS(rc) || rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES); 555 /** @todo: Handle number to big, throw a warning */ 556 557 unsigned cchNumber = pszNext - pTokenizer->pszInput; 558 for (unsigned i = 0; i < cchNumber; i++) 559 vdScriptTokenizerSkipCh(pTokenizer); 555 560 } 556 561 … … 846 851 847 852 /** 853 * Check whether the next token in the input stream is a keyword and matches the given 854 * keyword. 855 * 856 * @returns true if the token matched. 857 * false otherwise. 858 * @param pTokenizer The tokenizer state. 859 * @param pszOp The operation to check against. 860 */ 861 static bool vdScriptTokenizerIsOperatorEqual(PVDTOKENIZER pTokenizer, const char *pszOp) 862 { 863 PCVDSCRIPTTOKEN pToken = vdScriptTokenizerGetToken(pTokenizer); 864 865 if ( pToken->enmClass == VDTOKENCLASS_OPERATORS 866 && !RTStrCmp(pToken->Class.Operator.aszOp, pszOp)) 867 return true; 868 869 return false; 870 } 871 872 /** 873 * Check whether the next token in the input stream is an operator and matches the given 874 * keyword and skips it. 875 * 876 * @returns true if the token matched and was skipped. 877 * false otherwise. 878 * @param pTokenizer The tokenizer state. 879 * @param pszOp The operation to check against. 880 */ 881 static bool vdScriptTokenizerSkipIfIsOperatorEqual(PVDTOKENIZER pTokenizer, const char *pszOp) 882 { 883 bool fEqual = vdScriptTokenizerIsOperatorEqual(pTokenizer, pszOp); 884 if (fEqual) 885 vdScriptTokenizerConsume(pTokenizer); 886 887 return fEqual; 888 } 889 890 /** 848 891 * Record an error while parsing. 849 892 * … … 854 897 NOREF(pThis); 855 898 NOREF(pszFmt); 899 RTPrintf(pszFmt); 856 900 return rc; 857 901 } … … 885 929 886 930 *ppAstNodeIde = pAstNodeIde; 931 vdScriptTokenizerConsume(pThis->pTokenizer); 887 932 } 888 933 else … … 895 940 896 941 /** 897 * Parse a conditional expression. 942 * Parse a primary expression. 943 * 944 * @returns VBox status code. 945 * @param pThis The script context. 946 * @param ppAstNodeExpr Where to store the primary expression on success. 947 */ 948 static int vdScriptParsePrimaryExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 949 { 950 int rc = VINF_SUCCESS; 951 952 if (vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, '(')) 953 { 954 rc = vdScriptParseExpression(pThis, ppAstNodeExpr); 955 if (RT_SUCCESS(rc) 956 && !vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ')')) 957 rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Expected \")\", got ...\n"); 958 } 959 else 960 { 961 PVDSCRIPTASTEXPR pExpr = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 962 if (pExpr) 963 { 964 if (vdScriptTokenizerGetTokenClass(pThis->pTokenizer) == VDTOKENCLASS_IDENTIFIER) 965 { 966 PVDSCRIPTASTIDE pIde = NULL; 967 rc = vdScriptParseIde(pThis, &pIde); 968 if (RT_SUCCESS(rc)) 969 { 970 pExpr->enmType = VDSCRIPTEXPRTYPE_PRIMARY_IDENTIFIER; 971 pExpr->pIde = pIde; 972 } 973 } 974 else if (vdScriptTokenizerGetTokenClass(pThis->pTokenizer) == VDTOKENCLASS_NUMCONST) 975 { 976 PCVDSCRIPTTOKEN pToken = vdScriptTokenizerGetToken(pThis->pTokenizer); 977 pExpr->enmType = VDSCRIPTEXPRTYPE_PRIMARY_NUMCONST; 978 pExpr->u64 = pToken->Class.NumConst.u64; 979 vdScriptTokenizerConsume(pThis->pTokenizer); 980 } 981 else if (vdScriptTokenizerGetTokenClass(pThis->pTokenizer) == VDTOKENCLASS_STRINGCONST) 982 { 983 PCVDSCRIPTTOKEN pToken = vdScriptTokenizerGetToken(pThis->pTokenizer); 984 pExpr->enmType = VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST; 985 pExpr->pszStr = RTStrDup(pToken->Class.StringConst.pszString); 986 vdScriptTokenizerConsume(pThis->pTokenizer); 987 988 if (!pExpr->pszStr) 989 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating string\n"); 990 } 991 else 992 rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Expected \"(\" | identifier | constant | string, got ...\n"); 993 994 if (RT_FAILURE(rc)) 995 vdScriptAstNodeFree(&pExpr->Core); 996 else 997 *ppAstNodeExpr = pExpr; 998 } 999 else 1000 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1001 } 1002 1003 return rc; 1004 } 1005 1006 /** 1007 * Parse an argument list for a function call. 1008 * 1009 * @returns VBox status code. 1010 * @param pThis The script context. 1011 * @param pFnCall The function call AST node. 1012 */ 1013 static int vdScriptParseFnCallArgumentList(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR pFnCall) 1014 { 1015 int rc = VINF_SUCCESS; 1016 PVDSCRIPTASTEXPR pExpr = NULL; 1017 1018 rc = vdScriptParseAssignmentExpression(pThis, &pExpr); 1019 if (RT_SUCCESS(rc)) 1020 { 1021 RTListAppend(&pFnCall->FnCall.ListArgs, &pExpr->Core.ListNode); 1022 while (vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ',')) 1023 { 1024 rc = vdScriptParseAssignmentExpression(pThis, &pExpr); 1025 if (RT_SUCCESS(rc)) 1026 RTListAppend(&pFnCall->FnCall.ListArgs, &pExpr->Core.ListNode); 1027 else 1028 break; 1029 } 1030 if ( RT_SUCCESS(rc) 1031 && !vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ')')) 1032 rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Expected \")\", got ...\n"); 1033 } 1034 1035 return rc; 1036 } 1037 1038 /** 1039 * Parse a postfix expression. 898 1040 * 899 1041 * @returns VBox status code. 900 1042 * @param pThis The script context. 901 1043 * @param ppAstNodeExpr Where to store the expression AST node on success. 902 */ 903 static int vdScriptParseCondExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 904 { 905 int rc = VERR_NOT_IMPLEMENTED; 906 return rc; 907 } 908 909 /** 910 * Parse an expression. 1044 * 1045 * @note Syntax: 1046 * postfix-expression: 1047 * primary-expression 1048 * postfix-expression ( argument-expression ) 1049 * postfix-expression ++ 1050 * postfix-expression -- 1051 */ 1052 static int vdScriptParsePostfixExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1053 { 1054 int rc = VINF_SUCCESS; 1055 PVDSCRIPTASTEXPR pExpr = NULL; 1056 1057 rc = vdScriptParsePrimaryExpression(pThis, &pExpr); 1058 if (RT_SUCCESS(rc)) 1059 { 1060 while (true) 1061 { 1062 PVDSCRIPTASTEXPR pExprNew = NULL; 1063 1064 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "++")) 1065 { 1066 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1067 if (pExprNew) 1068 { 1069 pExprNew->enmType = VDSCRIPTEXPRTYPE_POSTFIX_INCREMENT; 1070 pExprNew->pExpr = pExpr; 1071 pExpr = pExprNew; 1072 } 1073 else 1074 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1075 } 1076 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "--")) 1077 { 1078 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1079 if (pExprNew) 1080 { 1081 pExprNew->enmType = VDSCRIPTEXPRTYPE_POSTFIX_DECREMENT; 1082 pExprNew->pExpr = pExpr; 1083 pExpr = pExprNew; 1084 } 1085 else 1086 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1087 } 1088 else if (vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, '(')) 1089 { 1090 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1091 if (pExprNew) 1092 { 1093 pExprNew->enmType = VDSCRIPTEXPRTYPE_POSTFIX_FNCALL; 1094 RTListInit(&pExprNew->FnCall.ListArgs); 1095 if (!vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ')')) 1096 rc = vdScriptParseFnCallArgumentList(pThis, pExprNew); 1097 pExprNew->FnCall.pFnIde = pExpr; 1098 pExpr = pExprNew; 1099 } 1100 else 1101 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1102 } 1103 else 1104 break; 1105 1106 if (RT_FAILURE(rc)) 1107 break; 1108 } 1109 1110 if (RT_SUCCESS(rc)) 1111 *ppAstNodeExpr = pExpr; 1112 else 1113 vdScriptAstNodeFree(&pExpr->Core); 1114 } 1115 return rc; 1116 } 1117 1118 /** 1119 * Parse an unary expression. 911 1120 * 912 1121 * @returns VBox status code. 913 1122 * @param pThis The script context. 914 1123 * @param ppAstNodeExpr Where to store the expression AST node on success. 1124 * 1125 * @note Syntax: 1126 * unary-expression: 1127 * postfix-expression 1128 * ++ unary-expression 1129 * -- unary-expression 1130 * + unary-expression 1131 * - unary-expression 1132 * ~ unary-expression 1133 * ! unary-expression 1134 */ 1135 static int vdScriptParseUnaryExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1136 { 1137 int rc = VINF_SUCCESS; 1138 PVDSCRIPTASTEXPR pExpr = NULL; 1139 PVDSCRIPTASTEXPR pExprTop = NULL; 1140 1141 while (true) 1142 { 1143 PVDSCRIPTASTEXPR pExprNew = NULL; 1144 1145 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "++")) 1146 { 1147 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1148 if (pExprNew) 1149 pExprNew->enmType = VDSCRIPTEXPRTYPE_UNARY_INCREMENT; 1150 else 1151 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1152 } 1153 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "--")) 1154 { 1155 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1156 if (pExprNew) 1157 pExprNew->enmType = VDSCRIPTEXPRTYPE_UNARY_DECREMENT; 1158 else 1159 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1160 } 1161 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "+")) 1162 { 1163 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1164 if (pExprNew) 1165 pExprNew->enmType = VDSCRIPTEXPRTYPE_UNARY_POSSIGN; 1166 else 1167 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1168 } 1169 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "-")) 1170 { 1171 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1172 if (pExprNew) 1173 pExprNew->enmType = VDSCRIPTEXPRTYPE_UNARY_NEGSIGN; 1174 else 1175 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1176 } 1177 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "~")) 1178 { 1179 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1180 if (pExprNew) 1181 pExprNew->enmType = VDSCRIPTEXPRTYPE_UNARY_INVERT; 1182 else 1183 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1184 } 1185 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "!")) 1186 { 1187 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1188 if (pExprNew) 1189 pExprNew->enmType = VDSCRIPTEXPRTYPE_UNARY_NEGATE; 1190 else 1191 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1192 } 1193 else 1194 { 1195 /* Must be a postfix expression. */ 1196 rc = vdScriptParsePostfixExpression(pThis, &pExprNew); 1197 } 1198 1199 if (RT_SUCCESS(rc)) 1200 { 1201 if (!pExprTop) 1202 { 1203 pExprTop = pExprNew; 1204 pExpr = pExprNew; 1205 } 1206 else 1207 { 1208 pExpr->pExpr = pExprNew; 1209 pExpr = pExprNew; 1210 } 1211 } 1212 else 1213 break; 1214 } 1215 1216 if (RT_SUCCESS(rc)) 1217 *ppAstNodeExpr = pExprTop; 1218 else if (pExprTop) 1219 vdScriptAstNodeFree(&pExprTop->Core); 1220 1221 return rc; 1222 } 1223 1224 /** 1225 * Parse a multiplicative expression. 1226 * 1227 * @returns VBox status code. 1228 * @param pThis The script context. 1229 * @param ppAstNodeExpr Where to store the expression AST node on success. 1230 * 1231 * @note Syntax: 1232 * multiplicative-expression: 1233 * unary-expression 1234 * multiplicative-expression * unary-expression 1235 * multiplicative-expression / unary-expression 1236 * multiplicative-expression % unary-expression 1237 */ 1238 static int vdScriptParseMultiplicativeExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1239 { 1240 int rc = VINF_SUCCESS; 1241 PVDSCRIPTASTEXPR pExpr = NULL; 1242 1243 rc = vdScriptParseUnaryExpression(pThis, &pExpr); 1244 if (RT_SUCCESS(rc)) 1245 { 1246 PVDSCRIPTASTEXPR pExprNew = NULL; 1247 while (RT_SUCCESS(rc)) 1248 { 1249 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "*")) 1250 { 1251 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1252 if (pExprNew) 1253 pExprNew->enmType = VDSCRIPTEXPRTYPE_MULTIPLICATION; 1254 else 1255 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1256 } 1257 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "/")) 1258 { 1259 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1260 if (pExprNew) 1261 pExprNew->enmType = VDSCRIPTEXPRTYPE_DIVISION; 1262 else 1263 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1264 } 1265 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "%")) 1266 { 1267 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1268 if (pExprNew) 1269 pExprNew->enmType = VDSCRIPTEXPRTYPE_MODULUS; 1270 else 1271 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1272 } 1273 else 1274 break; 1275 1276 pExprNew->BinaryOp.pLeftExpr = pExpr; 1277 pExpr = pExprNew; 1278 rc = vdScriptParseUnaryExpression(pThis, &pExprNew); 1279 if (RT_SUCCESS(rc)) 1280 pExpr->BinaryOp.pRightExpr = pExprNew; 1281 } 1282 1283 if (RT_SUCCESS(rc)) 1284 *ppAstNodeExpr = pExpr; 1285 else 1286 vdScriptAstNodeFree(&pExpr->Core); 1287 } 1288 return rc; 1289 } 1290 1291 /** 1292 * Parse a additive expression. 1293 * 1294 * @returns VBox status code. 1295 * @param pThis The script context. 1296 * @param ppAstNodeExpr Where to store the expression AST node on success. 1297 * 1298 * @note Syntax: 1299 * additive-expression: 1300 * multiplicative-expression 1301 * additive-expression + multiplicative-expression 1302 * additive-expression - multiplicative-expression 1303 */ 1304 static int vdScriptParseAdditiveExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1305 { 1306 int rc = VINF_SUCCESS; 1307 PVDSCRIPTASTEXPR pExpr = NULL; 1308 1309 rc = vdScriptParseMultiplicativeExpression(pThis, &pExpr); 1310 if (RT_SUCCESS(rc)) 1311 { 1312 PVDSCRIPTASTEXPR pExprNew = NULL; 1313 while (RT_SUCCESS(rc)) 1314 { 1315 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "+")) 1316 { 1317 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1318 if (pExprNew) 1319 pExprNew->enmType = VDSCRIPTEXPRTYPE_ADDITION; 1320 else 1321 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1322 } 1323 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "-")) 1324 { 1325 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1326 if (pExprNew) 1327 pExprNew->enmType = VDSCRIPTEXPRTYPE_SUBTRACTION; 1328 else 1329 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1330 } 1331 else 1332 break; 1333 1334 pExprNew->BinaryOp.pLeftExpr = pExpr; 1335 pExpr = pExprNew; 1336 rc = vdScriptParseMultiplicativeExpression(pThis, &pExprNew); 1337 if (RT_SUCCESS(rc)) 1338 pExpr->BinaryOp.pRightExpr = pExprNew; 1339 } 1340 1341 if (RT_SUCCESS(rc)) 1342 *ppAstNodeExpr = pExpr; 1343 else 1344 vdScriptAstNodeFree(&pExpr->Core); 1345 } 1346 return rc; 1347 } 1348 1349 /** 1350 * Parse a shift expression. 1351 * 1352 * @returns VBox status code. 1353 * @param pThis The script context. 1354 * @param ppAstNodeExpr Where to store the expression AST node on success. 1355 * 1356 * @note Syntax: 1357 * shift-expression: 1358 * additive-expression 1359 * shift-expression << additive-expression 1360 * shift-expression >> additive-expression 1361 */ 1362 static int vdScriptParseShiftExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1363 { 1364 int rc = VINF_SUCCESS; 1365 PVDSCRIPTASTEXPR pExpr = NULL; 1366 1367 rc = vdScriptParseAdditiveExpression(pThis, &pExpr); 1368 if (RT_SUCCESS(rc)) 1369 { 1370 PVDSCRIPTASTEXPR pExprNew = NULL; 1371 while (RT_SUCCESS(rc)) 1372 { 1373 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "<<")) 1374 { 1375 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1376 if (pExprNew) 1377 pExprNew->enmType = VDSCRIPTEXPRTYPE_LSL; 1378 else 1379 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1380 } 1381 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, ">>")) 1382 { 1383 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1384 if (pExprNew) 1385 pExprNew->enmType = VDSCRIPTEXPRTYPE_LSR; 1386 else 1387 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1388 } 1389 else 1390 break; 1391 1392 pExprNew->BinaryOp.pLeftExpr = pExpr; 1393 pExpr = pExprNew; 1394 rc = vdScriptParseAdditiveExpression(pThis, &pExprNew); 1395 if (RT_SUCCESS(rc)) 1396 pExpr->BinaryOp.pRightExpr = pExprNew; 1397 } 1398 1399 if (RT_SUCCESS(rc)) 1400 *ppAstNodeExpr = pExpr; 1401 else 1402 vdScriptAstNodeFree(&pExpr->Core); 1403 } 1404 return rc; 1405 } 1406 1407 /** 1408 * Parse a relational expression. 1409 * 1410 * @returns VBox status code. 1411 * @param pThis The script context. 1412 * @param ppAstNodeExpr Where to store the expression AST node on success. 1413 * 1414 * @note Syntax: 1415 * relational-expression: 1416 * shift-expression 1417 * relational-expression < shift-expression 1418 * relational-expression > shift-expression 1419 * relational-expression >= shift-expression 1420 * relational-expression <= shift-expression 1421 */ 1422 static int vdScriptParseRelationalExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1423 { 1424 int rc = VINF_SUCCESS; 1425 PVDSCRIPTASTEXPR pExpr = NULL; 1426 1427 rc = vdScriptParseShiftExpression(pThis, &pExpr); 1428 if (RT_SUCCESS(rc)) 1429 { 1430 PVDSCRIPTASTEXPR pExprNew = NULL; 1431 while (RT_SUCCESS(rc)) 1432 { 1433 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "<")) 1434 { 1435 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1436 if (pExprNew) 1437 pExprNew->enmType = VDSCRIPTEXPRTYPE_LOWER; 1438 else 1439 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1440 } 1441 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, ">")) 1442 { 1443 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1444 if (pExprNew) 1445 pExprNew->enmType = VDSCRIPTEXPRTYPE_HIGHER; 1446 else 1447 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1448 } 1449 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, ">=")) 1450 { 1451 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1452 if (pExprNew) 1453 pExprNew->enmType = VDSCRIPTEXPRTYPE_HIGHEREQUAL; 1454 else 1455 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1456 } 1457 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "<=")) 1458 { 1459 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1460 if (pExprNew) 1461 pExprNew->enmType = VDSCRIPTEXPRTYPE_LOWEREQUAL; 1462 else 1463 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1464 } 1465 else 1466 break; 1467 1468 pExprNew->BinaryOp.pLeftExpr = pExpr; 1469 pExpr = pExprNew; 1470 rc = vdScriptParseShiftExpression(pThis, &pExprNew); 1471 if (RT_SUCCESS(rc)) 1472 pExpr->BinaryOp.pRightExpr = pExprNew; 1473 } 1474 1475 if (RT_SUCCESS(rc)) 1476 *ppAstNodeExpr = pExpr; 1477 else 1478 vdScriptAstNodeFree(&pExpr->Core); 1479 } 1480 return rc; 1481 } 1482 1483 /** 1484 * Parse a equality expression. 1485 * 1486 * @returns VBox status code. 1487 * @param pThis The script context. 1488 * @param ppAstNodeExpr Where to store the expression AST node on success. 1489 * 1490 * @note Syntax: 1491 * equality-expression: 1492 * relational-expression 1493 * equality-expression == relational-expression 1494 * equality-expression != relational-expression 1495 */ 1496 static int vdScriptParseEqualityExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1497 { 1498 int rc = VINF_SUCCESS; 1499 PVDSCRIPTASTEXPR pExpr = NULL; 1500 1501 rc = vdScriptParseRelationalExpression(pThis, &pExpr); 1502 if (RT_SUCCESS(rc)) 1503 { 1504 PVDSCRIPTASTEXPR pExprNew = NULL; 1505 while (RT_SUCCESS(rc)) 1506 { 1507 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "==")) 1508 { 1509 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1510 if (pExprNew) 1511 pExprNew->enmType = VDSCRIPTEXPRTYPE_EQUAL; 1512 else 1513 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1514 } 1515 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "!=")) 1516 { 1517 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1518 if (pExprNew) 1519 pExprNew->enmType = VDSCRIPTEXPRTYPE_NOTEQUAL; 1520 else 1521 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1522 } 1523 else 1524 break; 1525 1526 pExprNew->BinaryOp.pLeftExpr = pExpr; 1527 pExpr = pExprNew; 1528 rc = vdScriptParseRelationalExpression(pThis, &pExprNew); 1529 if (RT_SUCCESS(rc)) 1530 pExpr->BinaryOp.pRightExpr = pExprNew; 1531 } 1532 1533 if (RT_SUCCESS(rc)) 1534 *ppAstNodeExpr = pExpr; 1535 else 1536 vdScriptAstNodeFree(&pExpr->Core); 1537 } 1538 return rc; 1539 } 1540 1541 /** 1542 * Parse a bitwise and expression. 1543 * 1544 * @returns VBox status code. 1545 * @param pThis The script context. 1546 * @param ppAstNodeExpr Where to store the expression AST node on success. 1547 * 1548 * @note Syntax: 1549 * and-expression: 1550 * equality-expression 1551 * and-expression & equality-expression 1552 */ 1553 static int vdScriptParseBitwiseAndExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1554 { 1555 int rc = VINF_SUCCESS; 1556 PVDSCRIPTASTEXPR pExpr = NULL; 1557 1558 rc = vdScriptParseEqualityExpression(pThis, &pExpr); 1559 if (RT_SUCCESS(rc)) 1560 { 1561 PVDSCRIPTASTEXPR pExprNew = NULL; 1562 while ( RT_SUCCESS(rc) 1563 && vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "&")) 1564 { 1565 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1566 if (pExprNew) 1567 { 1568 pExprNew->enmType = VDSCRIPTEXPRTYPE_EQUAL; 1569 pExprNew->BinaryOp.pLeftExpr = pExpr; 1570 pExpr = pExprNew; 1571 rc = vdScriptParseEqualityExpression(pThis, &pExprNew); 1572 if (RT_SUCCESS(rc)) 1573 pExpr->BinaryOp.pRightExpr = pExprNew; 1574 } 1575 else 1576 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1577 } 1578 1579 if (RT_SUCCESS(rc)) 1580 *ppAstNodeExpr = pExpr; 1581 else 1582 vdScriptAstNodeFree(&pExpr->Core); 1583 } 1584 return rc; 1585 } 1586 1587 /** 1588 * Parse a bitwise xor expression. 1589 * 1590 * @returns VBox status code. 1591 * @param pThis The script context. 1592 * @param ppAstNodeExpr Where to store the expression AST node on success. 1593 * 1594 * @note Syntax: 1595 * xor-expression: 1596 * and-expression 1597 * xor-expression ^ equality-expression 1598 */ 1599 static int vdScriptParseBitwiseXorExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1600 { 1601 int rc = VINF_SUCCESS; 1602 PVDSCRIPTASTEXPR pExpr = NULL; 1603 1604 rc = vdScriptParseBitwiseAndExpression(pThis, &pExpr); 1605 if (RT_SUCCESS(rc)) 1606 { 1607 PVDSCRIPTASTEXPR pExprNew = NULL; 1608 while ( RT_SUCCESS(rc) 1609 && vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "^")) 1610 { 1611 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1612 if (pExprNew) 1613 { 1614 pExprNew->enmType = VDSCRIPTEXPRTYPE_BITWISE_XOR; 1615 pExprNew->BinaryOp.pLeftExpr = pExpr; 1616 pExpr = pExprNew; 1617 rc = vdScriptParseBitwiseAndExpression(pThis, &pExprNew); 1618 if (RT_SUCCESS(rc)) 1619 pExpr->BinaryOp.pRightExpr = pExprNew; 1620 } 1621 else 1622 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1623 } 1624 1625 if (RT_SUCCESS(rc)) 1626 *ppAstNodeExpr = pExpr; 1627 else 1628 vdScriptAstNodeFree(&pExpr->Core); 1629 } 1630 return rc; 1631 } 1632 1633 /** 1634 * Parse a bitwise or expression. 1635 * 1636 * @returns VBox status code. 1637 * @param pThis The script context. 1638 * @param ppAstNodeExpr Where to store the expression AST node on success. 1639 * 1640 * @note Syntax: 1641 * or-expression: 1642 * xor-expression 1643 * or-expression | xor-expression 1644 */ 1645 static int vdScriptParseBitwiseOrExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1646 { 1647 int rc = VINF_SUCCESS; 1648 PVDSCRIPTASTEXPR pExpr = NULL; 1649 1650 rc = vdScriptParseBitwiseXorExpression(pThis, &pExpr); 1651 if (RT_SUCCESS(rc)) 1652 { 1653 PVDSCRIPTASTEXPR pExprNew = NULL; 1654 while ( RT_SUCCESS(rc) 1655 && vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "|")) 1656 { 1657 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1658 if (pExprNew) 1659 { 1660 pExprNew->enmType = VDSCRIPTEXPRTYPE_BITWISE_OR; 1661 pExprNew->BinaryOp.pLeftExpr = pExpr; 1662 pExpr = pExprNew; 1663 rc = vdScriptParseBitwiseXorExpression(pThis, &pExprNew); 1664 if (RT_SUCCESS(rc)) 1665 pExpr->BinaryOp.pRightExpr = pExprNew; 1666 } 1667 else 1668 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1669 } 1670 1671 if (RT_SUCCESS(rc)) 1672 *ppAstNodeExpr = pExpr; 1673 else 1674 vdScriptAstNodeFree(&pExpr->Core); 1675 } 1676 return rc; 1677 } 1678 1679 /** 1680 * Parse a logical and expression. 1681 * 1682 * @returns VBox status code. 1683 * @param pThis The script context. 1684 * @param ppAstNodeExpr Where to store the expression AST node on success. 1685 * 1686 * @note Syntax: 1687 * logical-and-expression: 1688 * or-expression 1689 * logical-and-expression | or-expression 1690 */ 1691 static int vdScriptParseLogicalAndExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1692 { 1693 int rc = VINF_SUCCESS; 1694 PVDSCRIPTASTEXPR pExpr = NULL; 1695 1696 rc = vdScriptParseBitwiseOrExpression(pThis, &pExpr); 1697 if (RT_SUCCESS(rc)) 1698 { 1699 PVDSCRIPTASTEXPR pExprNew = NULL; 1700 while ( RT_SUCCESS(rc) 1701 && vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "&&")) 1702 { 1703 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1704 if (pExprNew) 1705 { 1706 pExprNew->enmType = VDSCRIPTEXPRTYPE_LOGICAL_AND; 1707 pExprNew->BinaryOp.pLeftExpr = pExpr; 1708 pExpr = pExprNew; 1709 rc = vdScriptParseBitwiseOrExpression(pThis, &pExprNew); 1710 if (RT_SUCCESS(rc)) 1711 pExpr->BinaryOp.pRightExpr = pExprNew; 1712 } 1713 else 1714 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1715 } 1716 1717 if (RT_SUCCESS(rc)) 1718 *ppAstNodeExpr = pExpr; 1719 else 1720 vdScriptAstNodeFree(&pExpr->Core); 1721 } 1722 return rc; 1723 } 1724 1725 /** 1726 * Parse a logical or expression. 1727 * 1728 * @returns VBox status code. 1729 * @param pThis The script context. 1730 * @param ppAstNodeExpr Where to store the expression AST node on success. 1731 * 1732 * @note Syntax: 1733 * logical-or-expression: 1734 * logical-and-expression 1735 * logical-or-expression | logical-and-expression 1736 */ 1737 static int vdScriptParseLogicalOrExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1738 { 1739 int rc = VINF_SUCCESS; 1740 PVDSCRIPTASTEXPR pExpr = NULL; 1741 1742 rc = vdScriptParseLogicalAndExpression(pThis, &pExpr); 1743 if (RT_SUCCESS(rc)) 1744 { 1745 PVDSCRIPTASTEXPR pExprNew = NULL; 1746 while ( RT_SUCCESS(rc) 1747 && vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "||")) 1748 { 1749 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1750 if (pExprNew) 1751 { 1752 pExprNew->enmType = VDSCRIPTEXPRTYPE_LOGICAL_OR; 1753 pExprNew->BinaryOp.pLeftExpr = pExpr; 1754 pExpr = pExprNew; 1755 rc = vdScriptParseLogicalAndExpression(pThis, &pExprNew); 1756 if (RT_SUCCESS(rc)) 1757 pExpr->BinaryOp.pRightExpr = pExprNew; 1758 } 1759 else 1760 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1761 } 1762 1763 if (RT_SUCCESS(rc)) 1764 *ppAstNodeExpr = pExpr; 1765 else 1766 vdScriptAstNodeFree(&pExpr->Core); 1767 } 1768 return rc; 1769 } 1770 1771 /** 1772 * Parse a conditional expression. 1773 * 1774 * @returns VBox status code. 1775 * @param pThis The script context. 1776 * @param ppAstNodeExpr Where to store the expression AST node on success. 1777 * 1778 * @note: VDScript doesn't support logical-or-expression ? expression : conditional-expression 1779 * so a conditional expression is equal to a logical-or-expression. 1780 */ 1781 static int vdScriptParseCondExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1782 { 1783 return vdScriptParseLogicalOrExpression(pThis, ppAstNodeExpr); 1784 } 1785 1786 /** 1787 * Parse an assignment expression. 1788 * 1789 * @returns VBox status code. 1790 * @param pThis The script context. 1791 * @param ppAstNodeExpr Where to store the expression AST node on success. 1792 * 1793 * @note Syntax: 1794 * assignment-expression: 1795 * conditional-expression 1796 * unary-expression assignment-operator assignment-expression 1797 */ 1798 static int vdScriptParseAssignmentExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 1799 { 1800 int rc = VINF_SUCCESS; 1801 PVDSCRIPTASTEXPR pExpr; 1802 1803 rc = vdScriptParseLogicalOrExpression(pThis, &pExpr); 1804 if (RT_SUCCESS(rc)) 1805 { 1806 PVDSCRIPTASTEXPR pExprNew = NULL; 1807 while (RT_SUCCESS(rc)) 1808 { 1809 if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "=")) 1810 { 1811 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1812 if (pExprNew) 1813 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN; 1814 else 1815 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1816 } 1817 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "*=")) 1818 { 1819 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1820 if (pExprNew) 1821 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_MULT; 1822 else 1823 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1824 } 1825 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "/=")) 1826 { 1827 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1828 if (pExprNew) 1829 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_DIV; 1830 else 1831 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1832 } 1833 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "%=")) 1834 { 1835 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1836 if (pExprNew) 1837 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_MOD; 1838 else 1839 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1840 } 1841 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "+=")) 1842 { 1843 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1844 if (pExprNew) 1845 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_ADD; 1846 else 1847 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1848 } 1849 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "-=")) 1850 { 1851 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1852 if (pExprNew) 1853 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_SUB; 1854 else 1855 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1856 } 1857 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "<<=")) 1858 { 1859 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1860 if (pExprNew) 1861 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_LSL; 1862 else 1863 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1864 } 1865 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, ">>=")) 1866 { 1867 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1868 if (pExprNew) 1869 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_LSR; 1870 else 1871 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1872 } 1873 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "&=")) 1874 { 1875 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1876 if (pExprNew) 1877 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_AND; 1878 else 1879 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1880 } 1881 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "^=")) 1882 { 1883 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1884 if (pExprNew) 1885 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_XOR; 1886 else 1887 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1888 } 1889 else if (vdScriptTokenizerSkipIfIsOperatorEqual(pThis->pTokenizer, "|=")) 1890 { 1891 pExprNew = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1892 if (pExprNew) 1893 pExprNew->enmType = VDSCRIPTEXPRTYPE_ASSIGN_OR; 1894 else 1895 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1896 } 1897 else 1898 break; 1899 1900 pExprNew->BinaryOp.pLeftExpr = pExpr; 1901 pExpr = pExprNew; 1902 rc = vdScriptParseLogicalOrExpression(pThis, &pExprNew); 1903 if (RT_SUCCESS(rc)) 1904 pExpr->BinaryOp.pRightExpr = pExprNew; 1905 } 1906 1907 if (RT_SUCCESS(rc)) 1908 *ppAstNodeExpr = pExpr; 1909 else 1910 vdScriptAstNodeFree(&pExpr->Core); 1911 } 1912 return rc; 1913 } 1914 1915 /** 1916 * Parse an expression. 1917 * 1918 * @returns VBox status code. 1919 * @param pThis The script context. 1920 * @param ppAstNodeExpr Where to store the expression AST node on success. 1921 * 1922 * @note Syntax: 1923 * expression: 1924 * assignment-expression 1925 * expression , assignment-expression 915 1926 */ 916 1927 static int vdScriptParseExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr) 917 1928 { 918 int rc = VERR_NOT_IMPLEMENTED; 1929 int rc = VINF_SUCCESS; 1930 PVDSCRIPTASTEXPR pAssignExpr = NULL; 1931 1932 rc = vdScriptParseAssignmentExpression(pThis, &pAssignExpr); 1933 if ( RT_SUCCESS(rc) 1934 && vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ',')) 1935 { 1936 PVDSCRIPTASTEXPR pListAssignExpr = (PVDSCRIPTASTEXPR)vdScriptAstNodeAlloc(VDSCRIPTASTCLASS_EXPRESSION); 1937 if (pListAssignExpr) 1938 { 1939 pListAssignExpr->enmType = VDSCRIPTEXPRTYPE_ASSIGNMENT_LIST; 1940 RTListInit(&pListAssignExpr->ListExpr); 1941 RTListAppend(&pListAssignExpr->ListExpr, &pAssignExpr->Core.ListNode); 1942 do 1943 { 1944 rc = vdScriptParseAssignmentExpression(pThis, &pAssignExpr); 1945 if (RT_SUCCESS(rc)) 1946 RTListAppend(&pListAssignExpr->ListExpr, &pAssignExpr->Core.ListNode); 1947 } while ( RT_SUCCESS(rc) 1948 && vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ',')); 1949 1950 if (RT_FAILURE(rc)) 1951 vdScriptAstNodeFree(&pListAssignExpr->Core); 1952 else 1953 *ppAstNodeExpr = pListAssignExpr; 1954 } 1955 else 1956 rc = vdScriptParserError(pThis, VERR_NO_MEMORY, RT_SRC_POS, "Parser: Out of memory allocating expression AST node\n"); 1957 } 1958 else if (RT_SUCCESS(rc)) 1959 *ppAstNodeExpr = pAssignExpr; 1960 919 1961 return rc; 920 1962 } … … 1202 2244 if (RT_SUCCESS(rc)) 1203 2245 pAstNodeStmt->pStmt = pAstNodeStmtDef; 1204 } 2246 } 1205 2247 else 1206 2248 rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Expected \":\", got ...\n"); … … 1270 2312 { 1271 2313 pAstNodeStmt->enmStmtType = VDSCRIPTSTMTTYPE_RETURN; 1272 rc = vdScriptParseExpression(pThis, &pAstNodeStmt->pExpr); 1273 if ( RT_SUCCESS(rc) 1274 && !vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ';')) 1275 rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Expected \";\", got ...\n"); 2314 if (!vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ';')) 2315 { 2316 rc = vdScriptParseExpression(pThis, &pAstNodeStmt->pExpr); 2317 if ( RT_SUCCESS(rc) 2318 && !vdScriptTokenizerSkipIfIsPunctuatorEqual(pThis->pTokenizer, ';')) 2319 rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Expected \";\", got ...\n"); 2320 } 1276 2321 } 1277 2322 else -
trunk/src/VBox/Storage/testcase/VDScriptAst.cpp
r44811 r44840 48 48 case VDSCRIPTASTCLASS_STATEMENT: 49 49 break; 50 case VDSCRIPTASTCLASS_EXPRESSION: 51 break; 50 52 case VDSCRIPTASTCLASS_INVALID: 51 53 default: … … 73 75 case VDSCRIPTASTCLASS_STATEMENT: 74 76 cbAlloc = sizeof(VDSCRIPTASTSTMT); 77 break; 78 case VDSCRIPTASTCLASS_EXPRESSION: 79 cbAlloc = sizeof(VDSCRIPTASTEXPR); 75 80 break; 76 81 case VDSCRIPTASTCLASS_IDENTIFIER: -
trunk/src/VBox/Storage/testcase/VDScriptAst.h
r44811 r44840 19 19 20 20 #include <iprt/list.h> 21 22 /** 23 * Position information. 24 */ 25 typedef struct VDSRCPOS 26 { 27 /** Line in the source. */ 28 unsigned iLine; 29 /** Current start character .*/ 30 unsigned iChStart; 31 /** Current end character. */ 32 unsigned iChEnd; 33 } VDSRCPOS; 34 /** Pointer to a source position. */ 35 typedef struct VDSRCPOS *PVDSRCPOS; 21 36 22 37 /** … … 55 70 /** List which might be used. */ 56 71 RTLISTNODE ListNode; 72 /** Position in the source file of this node. */ 73 VDSRCPOS Pos; 57 74 } VDSCRIPTASTCORE; 58 75 /** Pointer to an AST core structure. */ … … 61 78 /** Pointer to an statement node - forward declaration. */ 62 79 typedef struct VDSCRIPTASTSTMT *PVDSCRIPTASTSTMT; 80 /** Pointer to an expression node - forward declaration. */ 81 typedef struct VDSCRIPTASTEXPR *PVDSCRIPTASTEXPR; 63 82 64 83 /** … … 90 109 91 110 /** 111 * Expression types. 112 */ 113 typedef enum VDSCRIPTEXPRTYPE 114 { 115 /** Invalid. */ 116 VDSCRIPTEXPRTYPE_INVALID = 0, 117 /** Numerical constant. */ 118 VDSCRIPTEXPRTYPE_PRIMARY_NUMCONST, 119 /** String constant. */ 120 VDSCRIPTEXPRTYPE_PRIMARY_STRINGCONST, 121 /** Identifier. */ 122 VDSCRIPTEXPRTYPE_PRIMARY_IDENTIFIER, 123 /** List of assignment expressions. */ 124 VDSCRIPTEXPRTYPE_ASSIGNMENT_LIST, 125 /** Assignment expression. */ 126 VDSCRIPTEXPRTYPE_ASSIGNMENT, 127 /** Postfix increment expression. */ 128 VDSCRIPTEXPRTYPE_POSTFIX_INCREMENT, 129 /** Postfix decrement expression. */ 130 VDSCRIPTEXPRTYPE_POSTFIX_DECREMENT, 131 /** Postfix function call expression. */ 132 VDSCRIPTEXPRTYPE_POSTFIX_FNCALL, 133 /** Unary increment expression. */ 134 VDSCRIPTEXPRTYPE_UNARY_INCREMENT, 135 /** Unary decrement expression. */ 136 VDSCRIPTEXPRTYPE_UNARY_DECREMENT, 137 /** Unary positive sign expression. */ 138 VDSCRIPTEXPRTYPE_UNARY_POSSIGN, 139 /** Unary negtive sign expression. */ 140 VDSCRIPTEXPRTYPE_UNARY_NEGSIGN, 141 /** Unary invert expression. */ 142 VDSCRIPTEXPRTYPE_UNARY_INVERT, 143 /** Unary negate expression. */ 144 VDSCRIPTEXPRTYPE_UNARY_NEGATE, 145 /** Multiplicative expression. */ 146 VDSCRIPTEXPRTYPE_MULTIPLICATION, 147 /** Division expression. */ 148 VDSCRIPTEXPRTYPE_DIVISION, 149 /** Modulus expression. */ 150 VDSCRIPTEXPRTYPE_MODULUS, 151 /** Addition expression. */ 152 VDSCRIPTEXPRTYPE_ADDITION, 153 /** Subtraction expression. */ 154 VDSCRIPTEXPRTYPE_SUBTRACTION, 155 /** Logical shift right. */ 156 VDSCRIPTEXPRTYPE_LSR, 157 /** Logical shift left. */ 158 VDSCRIPTEXPRTYPE_LSL, 159 /** Lower than expression */ 160 VDSCRIPTEXPRTYPE_LOWER, 161 /** Higher than expression */ 162 VDSCRIPTEXPRTYPE_HIGHER, 163 /** Lower or equal than expression */ 164 VDSCRIPTEXPRTYPE_LOWEREQUAL, 165 /** Higher or equal than expression */ 166 VDSCRIPTEXPRTYPE_HIGHEREQUAL, 167 /** Equals expression */ 168 VDSCRIPTEXPRTYPE_EQUAL, 169 /** Not equal expression */ 170 VDSCRIPTEXPRTYPE_NOTEQUAL, 171 /** Bitwise and expression */ 172 VDSCRIPTEXPRTYPE_BITWISE_AND, 173 /** Bitwise xor expression */ 174 VDSCRIPTEXPRTYPE_BITWISE_XOR, 175 /** Bitwise or expression */ 176 VDSCRIPTEXPRTYPE_BITWISE_OR, 177 /** Logical and expression */ 178 VDSCRIPTEXPRTYPE_LOGICAL_AND, 179 /** Logical or expression */ 180 VDSCRIPTEXPRTYPE_LOGICAL_OR, 181 /** Assign expression */ 182 VDSCRIPTEXPRTYPE_ASSIGN, 183 /** Multiplicative assign expression */ 184 VDSCRIPTEXPRTYPE_ASSIGN_MULT, 185 /** Division assign expression */ 186 VDSCRIPTEXPRTYPE_ASSIGN_DIV, 187 /** Modulus assign expression */ 188 VDSCRIPTEXPRTYPE_ASSIGN_MOD, 189 /** Additive assign expression */ 190 VDSCRIPTEXPRTYPE_ASSIGN_ADD, 191 /** Subtractive assign expression */ 192 VDSCRIPTEXPRTYPE_ASSIGN_SUB, 193 /** Bitwise left shift assign expression */ 194 VDSCRIPTEXPRTYPE_ASSIGN_LSL, 195 /** Bitwise right shift assign expression */ 196 VDSCRIPTEXPRTYPE_ASSIGN_LSR, 197 /** Bitwise and assign expression */ 198 VDSCRIPTEXPRTYPE_ASSIGN_AND, 199 /** Bitwise xor assign expression */ 200 VDSCRIPTEXPRTYPE_ASSIGN_XOR, 201 /** Bitwise or assign expression */ 202 VDSCRIPTEXPRTYPE_ASSIGN_OR, 203 /** 32bit hack. */ 204 VDSCRIPTEXPRTYPE_32BIT_HACK = 0x7fffffff 205 } VDSCRIPTEXPRTYPE; 206 /** Pointer to an expression type. */ 207 typedef VDSCRIPTEXPRTYPE *PVDSCRIPTEXPRTYPE; 208 209 /** 92 210 * AST expression node. 93 211 */ … … 96 214 /** Core structure. */ 97 215 VDSCRIPTASTCORE Core; 98 /** @todo */ 99 unsigned uDummy; 216 /** Expression type. */ 217 VDSCRIPTEXPRTYPE enmType; 218 /** Expression type dependent data. */ 219 union 220 { 221 /** Numerical constant. */ 222 uint64_t u64; 223 /** Primary identifier. */ 224 PVDSCRIPTASTIDE pIde; 225 /** String literal */ 226 const char *pszStr; 227 /** List of expressions - VDSCRIPTASTEXPR. */ 228 RTLISTANCHOR ListExpr; 229 /** Pointer to another expression. */ 230 PVDSCRIPTASTEXPR pExpr; 231 /** Function call expression. */ 232 struct 233 { 234 /** Other postfix expression used as the identifier for the function. */ 235 PVDSCRIPTASTEXPR pFnIde; 236 /** Argument list if existing. */ 237 RTLISTANCHOR ListArgs; 238 } FnCall; 239 /** Binary operation. */ 240 struct 241 { 242 /** Left operator. */ 243 PVDSCRIPTASTEXPR pLeftExpr; 244 /** Right operator. */ 245 PVDSCRIPTASTEXPR pRightExpr; 246 } BinaryOp; 247 }; 100 248 } VDSCRIPTASTEXPR; 101 /** Pointer to an expression node. */102 typedef VDSCRIPTASTEXPR *PVDSCRIPTASTEXPR;103 249 104 250 /**
Note:
See TracChangeset
for help on using the changeset viewer.