File: declarationparser.cpp

package info (click to toggle)
openmw 0.50.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 37,076 kB
  • sloc: cpp: 380,958; xml: 2,192; sh: 1,449; python: 911; makefile: 26; javascript: 5
file content (127 lines) | stat: -rw-r--r-- 3,606 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#include "declarationparser.hpp"

#include <components/misc/strings/lower.hpp>

#include "context.hpp"
#include "errorhandler.hpp"
#include "extensions.hpp"
#include "locals.hpp"
#include "scanner.hpp"
#include "skipparser.hpp"

Compiler::DeclarationParser::DeclarationParser(ErrorHandler& errorHandler, const Context& context, Locals& locals)
    : Parser(errorHandler, context)
    , mLocals(locals)
    , mState(State_Begin)
    , mType(0)
{
}

bool Compiler::DeclarationParser::parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner)
{
    if (mState == State_Name)
    {
        std::string name2 = ::Misc::StringUtils::lowerCase(name);

        char type = mLocals.getType(name2);

        if (type != ' ')
            getErrorHandler().warning("Local variable re-declaration", loc);
        else
            mLocals.declare(mType, name2);

        mState = State_End;
        return true;
    }
    else if (mState == State_End)
    {
        getErrorHandler().warning("Extra text after local variable declaration", loc);
        SkipParser skip(getErrorHandler(), getContext());
        scanner.scan(skip);
        return false;
    }

    return Parser::parseName(name, loc, scanner);
}

bool Compiler::DeclarationParser::parseKeyword(int keyword, const TokenLoc& loc, Scanner& scanner)
{
    if (mState == State_Begin)
    {
        switch (keyword)
        {
            case Scanner::K_short:
                mType = 's';
                break;
            case Scanner::K_long:
                mType = 'l';
                break;
            case Scanner::K_float:
                mType = 'f';
                break;
            default:
                mType = 0;
        }

        if (mType)
        {
            mState = State_Name;
            return true;
        }
    }
    else if (mState == State_Name)
    {
        // allow keywords to be used as local variable names. MW script compiler, you suck!
        if (const Extensions* extensions = getContext().getExtensions())
        {
            std::string argumentType;
            bool hasExplicit = false;
            char returnType;
            if (extensions->isFunction(keyword, returnType, argumentType, hasExplicit))
                getErrorHandler().warning("Local variable declaration shadows a function", loc);
        }

        return parseName(loc.mLiteral, loc, scanner);
    }
    else if (mState == State_End)
    {
        getErrorHandler().warning("Extra text after local variable declaration", loc);
        SkipParser skip(getErrorHandler(), getContext());
        scanner.scan(skip);
        return false;
    }

    return Parser::parseKeyword(keyword, loc, scanner);
}

bool Compiler::DeclarationParser::parseSpecial(int code, const TokenLoc& loc, Scanner& scanner)
{
    if (mState == State_End)
    {
        if (code != Scanner::S_newline)
        {
            getErrorHandler().warning("Extra text after local variable declaration", loc);
            SkipParser skip(getErrorHandler(), getContext());
            scanner.scan(skip);
        }
        return false;
    }

    return Parser::parseSpecial(code, loc, scanner);
}

bool Compiler::DeclarationParser::parseInt(int value, const TokenLoc& loc, Scanner& scanner)
{
    if (mState == State_Name)
    {
        // Allow integers to be used as variable names
        getErrorHandler().warning("Integer is used as a local variable name", loc);
        return parseName(loc.mLiteral, loc, scanner);
    }
    return Parser::parseInt(value, loc, scanner);
}

void Compiler::DeclarationParser::reset()
{
    mState = State_Begin;
}