(file) Return to lexer.c CVS log (file) (dir) Up to [OMI] / omi / wql

File: [OMI] / omi / wql / lexer.c (download)
Revision: 1.1.1.1 (vendor branch), Wed May 30 21:47:49 2012 UTC (12 years ago) by mike
Branch: TOG
CVS Tags: OMI_1_0_2_Branch, OMI_1_0_2, OMI_1_0_1_PRE, OMI_1_0_1, OMI_1_0_0
Changes since 1.1: +0 -0 lines
Initial Import

/*
**==============================================================================
**
** Open Management Infrastructure (OMI)
**
** Copyright (c) Microsoft Corporation
** 
** Licensed under the Apache License, Version 2.0 (the "License"); you may not 
** use this file except in compliance with the License. You may obtain a copy 
** of the License at 
**
**     http://www.apache.org/licenses/LICENSE-2.0 
**
** THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
** KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED 
** WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, 
** MERCHANTABLITY OR NON-INFRINGEMENT. 
**
** See the Apache 2 License for the specific language governing permissions 
** and limitations under the License.
**
**==============================================================================
*/

#include "wql.h"
#include <ctype.h>
#include <base/strings.h>
#include "state.h"
#include "wqlyacc.h"

extern void* wqlmalloc(size_t size);
extern MI_Char* wqlstrdup(const MI_Char* str);

int wqllex()
{
    const MI_Char* p = wqlstate.ptr;

    /* Skip whitespace */
    while (*p && isspace(*p))
        p++;

    /* Return on end-of-file */
    if (*p == '\0')
    {
        wqlstate.ptr = p;
        return 0;
    }

    /* Recognize identifier */
    if (isalpha(*p) || *p == '_')
    {
        const MI_Char* start = p++;
        size_t n;

        while (isalnum(*p) || *p == '_')
            p++;

        wqlstate.ptr = p;

        if (Zncasecmp(start, MI_T("select"), 6) == 0)
            return WQL_SELECT;
        else if (Zncasecmp(start, MI_T("from"), 4) == 0)
            return WQL_FROM;
        else if (Zncasecmp(start, MI_T("where"), 5) == 0)
            return WQL_WHERE;
        else if (Zncasecmp(start, MI_T("not"), 3) == 0)
            return WQL_NOT;
        else if (Zncasecmp(start, MI_T("and"), 3) == 0)
            return WQL_AND;
        else if (Zncasecmp(start, MI_T("or"), 2) == 0)
            return WQL_OR;
        else if (Zncasecmp(start, MI_T("null"), 2) == 0)
            return WQL_NULL;
        else if (Zncasecmp(start, MI_T("true"), 4) == 0)
        {
            wqllval.boolean = 1;
            return WQL_BOOLEAN;
        }
        else if (Zncasecmp(start, MI_T("false"), 5) == 0)
        {
            wqllval.boolean = 0;
            return WQL_BOOLEAN;
        }

        n = p - start;
        wqllval.string = (MI_Char*)wqlmalloc(n + 1);

        if (!wqllval.string)
            return -1;

        memcpy(wqllval.string, start, n);
        wqllval.string[n] = '\0';

        return WQL_IDENTIFIER;
    }

    /* Recognize number (integer or double) */
    if (*p == '+' || *p == '-' || isdigit(*p))
    {
        const MI_Char* start = p++;

        while (isdigit(*p))
            p++;

        if (*p == '.')
        {
            MI_Char* end;
            wqllval.real = Ztod(start, &end);
            p = end;
            wqlstate.ptr = p;
            return WQL_REAL;
        }
        else
        {
            MI_Char* end;
            wqllval.integer = Ztoll(start, &end, 10);
            p = end;
            wqlstate.ptr = p;
            return WQL_INTEGER;
        }
    }

    /* Recognize string literal */
    if (*p == '"')
    {
        const MI_Char* start = ++p;
        size_t n = 0;
        MI_Char* q;

        /* Determine the length of the string */
        while (*p && *p != '"')
        {
            if (*p == '\\')
            {
                if (*++p == '\0')
                    return -1;
            }

            p++;
            n++;
        }

        /* Allocate new string */
        {
            q = wqlmalloc(n + 1);

            if (!q)
                return -1;

            wqllval.string = q;
        }

        /* Convert string */
        for (p = start; *p && *p != '"'; )
        {
            if (*p == '\\')
            {
                p++;
                switch (*p)
                {
                    case '\0':
                        return -1;
                    case 'n':
                        *q++ = '\n';
                        break;
                    case 'r':
                        *q++ = '\r';
                        break;
                    case 'f':
                        *q++ = '\r';
                        break;
                    case '"':
                        *q++ = '"';
                        break;
                    case '\\':
                        *q++ = '\\';
                        break;
                    default:
                        *q++ = *p;
                }
                p++;
            }
            else
                *q++ = *p++;
        }

        /* String literal must be terminated */
        if (*p++ != '"')
            return -1;

        /* Null terminate string */
        *q = '\0';
        wqlstate.ptr = p;
        return WQL_STRING;
    }

    /* WQL_EQ */
    if (p[0] == '=')
    {
        wqlstate.ptr = p + 1;
        return WQL_EQ;
    }

    /* WQL_NE */
    if ((p[0] == '<' && p[1] == '>') || (p[0] == '!' && p[1] == '='))
    {
        wqlstate.ptr = p + 2;
        return WQL_NE;
    }

    /* WQL_LE */
    if (p[0] == '<' && p[1] == '=')
    {
        wqlstate.ptr = p + 2;
        return WQL_LE;
    }

    /* WQL_LT */
    if (p[0] == '<')
    {
        wqlstate.ptr = p + 1;
        return WQL_LT;
    }

    /* WQL_GE */
    if (p[0] == '>' && p[1] == '=')
    {
        wqlstate.ptr = p + 2;
        return WQL_GE;
    }

    /* WQL_GT */
    if (p[0] == '>')
    {
        wqlstate.ptr = p + 1;
        return WQL_GT;
    }

    /* Match single characters */
    if (*p == '*' || *p == '(' || *p == ')' || *p == ',')
    {
        wqlstate.ptr = p + 1;
        return *p;
    }

    /* Unrecognized tokens */
    return WQL_ERROR;
}

ViewCVS 0.9.2