VirtualBox

Changeset 44840 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Feb 26, 2013 11:41:06 PM (12 years ago)
Author:
vboxsync
Message:

Storage/testcase: Updates for VDScript, parser not quite working yet

Location:
trunk/src/VBox/Storage/testcase
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Storage/testcase/VDScript.cpp

    r44811 r44840  
    3636 * code. Could be used as a scripting language for the VBox debugger for example or in the scm
    3737 * 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
    3843 */
    3944#define LOGGROUP LOGGROUP_DEFAULT
     
    4247#include <iprt/mem.h>
    4348#include <iprt/ctype.h>
     49#include <iprt/stream.h>
    4450
    4551#include <VBox/log.h>
     
    4753#include "VDScript.h"
    4854#include "VDScriptAst.h"
    49 
    50 /**
    51  * Position information.
    52  */
    53 typedef struct VDSRCPOS
    54 {
    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;
    6455
    6556/**
     
    10293    VDSCRIPTTOKENKEYWORD_WHILE,
    10394    VDSCRIPTTOKENKEYWORD_BREAK,
     95    VDSCRIPTTOKENKEYWORD_FALSE,
     96    VDSCRIPTTOKENKEYWORD_TRUE,
    10497    VDSCRIPTTOKENKEYWORD_ELSE,
    10598    VDSCRIPTTOKENKEYWORD_CASE,
     
    135128        struct
    136129        {
    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;
    144131        } NumConst;
    145132        /** String constant */
     
    297284    {"<",   1},
    298285    {">",   1},
    299     {"!",   1}
     286    {"!",   1},
     287    {"~",   1}
    300288};
    301289
     
    339327    {"while",    5, VDSCRIPTTOKENKEYWORD_WHILE},
    340328    {"break",    5, VDSCRIPTTOKENKEYWORD_BREAK},
     329    {"false",    5, VDSCRIPTTOKENKEYWORD_FALSE},
     330    {"true",     4, VDSCRIPTTOKENKEYWORD_TRUE},
    341331    {"else",     4, VDSCRIPTTOKENKEYWORD_ELSE},
    342332    {"case",     4, VDSCRIPTTOKENKEYWORD_CASE},
     
    348338static int vdScriptParseCompoundStatement(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTSTMT *ppAstNodeCompound);
    349339static int vdScriptParseStatement(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTSTMT *ppAstNodeStmt);
     340static int vdScriptParseExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr);
     341static int vdScriptParseAssignmentExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr);
    350342
    351343/**
     
    458450            vdScriptTokenizerSkipCh(pTokenizer);
    459451    }
     452
     453    if (!vdScriptTokenizerIsEos(pTokenizer))
     454        vdScriptTokenizerSkipCh(pTokenizer);
     455    if (!vdScriptTokenizerIsEos(pTokenizer))
     456        vdScriptTokenizerSkipCh(pTokenizer);
    460457}
    461458
     
    469466DECLINLINE(void) vdScriptTokenizerSkipWhitespace(PVDTOKENIZER pTokenizer)
    470467{
    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')
    476472            vdScriptTokenizerSkipCh(pTokenizer);
    477473
     
    481477            if (   vdScriptTokenizerGetCh(pTokenizer) == '/'
    482478                && vdScriptTokenizerPeekCh(pTokenizer) == '*')
     479            {
     480                vdScriptTokenizerSkipCh(pTokenizer);
     481                vdScriptTokenizerSkipCh(pTokenizer);
    483482                vdScriptTokenizerSkipComment(pTokenizer);
     483            }
    484484            else
    485485                break; /* Skipped everything, next is some real content. */
     
    545545{
    546546    unsigned uBase = 10;
    547     size_t cchNumber = 0;
     547    char *pszNext = NULL;
    548548
    549549    Assert(RT_C_IS_DIGIT(vdScriptTokenizerGetCh(pTokenizer)));
    550550
    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);
    555560}
    556561
     
    846851
    847852/**
     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 */
     861static 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 */
     881static 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/**
    848891 * Record an error while parsing.
    849892 *
     
    854897    NOREF(pThis);
    855898    NOREF(pszFmt);
     899    RTPrintf(pszFmt);
    856900    return rc;
    857901}
     
    885929
    886930            *ppAstNodeIde = pAstNodeIde;
     931            vdScriptTokenizerConsume(pThis->pTokenizer);
    887932        }
    888933        else
     
    895940
    896941/**
    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 */
     948static 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 */
     1013static 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.
    8981040 *
    8991041 * @returns VBox status code.
    9001042 * @param   pThis                The script context.
    9011043 * @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 */
     1052static 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.
    9111120 *
    9121121 * @returns VBox status code.
    9131122 * @param   pThis                The script context.
    9141123 * @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 */
     1135static 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 */
     1238static 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 */
     1304static 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 */
     1362static 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 */
     1422static 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 */
     1496static 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 */
     1553static 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 */
     1599static 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 */
     1645static 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 */
     1691static 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 */
     1737static 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 */
     1781static 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 */
     1798static 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
    9151926 */
    9161927static int vdScriptParseExpression(PVDSCRIPTCTXINT pThis, PVDSCRIPTASTEXPR *ppAstNodeExpr)
    9171928{
    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
    9191961    return rc;
    9201962}
     
    12022244                    if (RT_SUCCESS(rc))
    12032245                        pAstNodeStmt->pStmt = pAstNodeStmtDef;
    1204                 } 
     2246                }
    12052247                else
    12062248                    rc = vdScriptParserError(pThis, VERR_INVALID_PARAMETER, RT_SRC_POS, "Parser: Expected \":\", got ...\n");
     
    12702312            {
    12712313                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                }
    12762321            }
    12772322            else
  • trunk/src/VBox/Storage/testcase/VDScriptAst.cpp

    r44811 r44840  
    4848        case VDSCRIPTASTCLASS_STATEMENT:
    4949            break;
     50        case VDSCRIPTASTCLASS_EXPRESSION:
     51            break;
    5052        case VDSCRIPTASTCLASS_INVALID:
    5153        default:
     
    7375        case VDSCRIPTASTCLASS_STATEMENT:
    7476            cbAlloc = sizeof(VDSCRIPTASTSTMT);
     77            break;
     78        case VDSCRIPTASTCLASS_EXPRESSION:
     79            cbAlloc = sizeof(VDSCRIPTASTEXPR);
    7580            break;
    7681        case VDSCRIPTASTCLASS_IDENTIFIER:
  • trunk/src/VBox/Storage/testcase/VDScriptAst.h

    r44811 r44840  
    1919
    2020#include <iprt/list.h>
     21
     22/**
     23 * Position information.
     24 */
     25typedef 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. */
     35typedef struct VDSRCPOS *PVDSRCPOS;
    2136
    2237/**
     
    5570    /** List which might be used. */
    5671    RTLISTNODE       ListNode;
     72    /** Position in the source file of this node. */
     73    VDSRCPOS         Pos;
    5774} VDSCRIPTASTCORE;
    5875/** Pointer to an AST core structure. */
     
    6178/** Pointer to an statement node - forward declaration. */
    6279typedef struct VDSCRIPTASTSTMT *PVDSCRIPTASTSTMT;
     80/** Pointer to an expression node - forward declaration. */
     81typedef struct VDSCRIPTASTEXPR *PVDSCRIPTASTEXPR;
    6382
    6483/**
     
    90109
    91110/**
     111 * Expression types.
     112 */
     113typedef 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. */
     207typedef VDSCRIPTEXPRTYPE *PVDSCRIPTEXPRTYPE;
     208
     209/**
    92210 * AST expression node.
    93211 */
     
    96214    /** Core structure. */
    97215    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    };
    100248} VDSCRIPTASTEXPR;
    101 /** Pointer to an expression node. */
    102 typedef VDSCRIPTASTEXPR *PVDSCRIPTASTEXPR;
    103249
    104250/**
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette