File: fileparser.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 (132 lines) | stat: -rw-r--r-- 3,899 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
128
129
130
131
132
#include "fileparser.hpp"

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

#include "scanner.hpp"
#include "tokenloc.hpp"

namespace Compiler
{
    FileParser::FileParser(ErrorHandler& errorHandler, Context& context)
        : Parser(errorHandler, context)
        , mScriptParser(errorHandler, context, mLocals, true)
        , mState(BeginState)
    {
    }

    Interpreter::Program FileParser::getProgram() const
    {
        return mScriptParser.getProgram();
    }

    const Locals& FileParser::getLocals() const
    {
        return mLocals;
    }

    bool FileParser::parseName(const std::string& name, const TokenLoc& loc, Scanner& scanner)
    {
        if (mState == NameState)
        {
            mName = name;
            mState = BeginCompleteState;
            return true;
        }

        if (mState == EndNameState)
        {
            // optional repeated name after end statement
            if (!Misc::StringUtils::ciEqual(mName, name))
                reportWarning("Names for script " + mName + " do not match", loc);

            mState = EndCompleteState;
            return false; // we are stopping here, because there might be more garbage on the end line,
                          // that we must ignore.
                          //
                          /// \todo allow this workaround to be disabled for newer scripts
        }

        if (mState == BeginCompleteState)
        {
            reportWarning("Stray string (" + name + ") after begin statement", loc);
            return true;
        }

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

    bool FileParser::parseKeyword(int keyword, const TokenLoc& loc, Scanner& scanner)
    {
        if (mState == BeginState && keyword == Scanner::K_begin)
        {
            mState = NameState;
            scanner.enableTolerantNames(); /// \todo disable
            return true;
        }

        if (mState == NameState)
        {
            // keywords can be used as script names too. Thank you Morrowind for another
            // syntactic perversity :(
            mName = loc.mLiteral;
            mState = BeginCompleteState;
            return true;
        }

        if (mState == EndNameState)
        {
            // optional repeated name after end statement
            if (!Misc::StringUtils::ciEqual(mName, loc.mLiteral))
                reportWarning("Names for script " + mName + " do not match", loc);

            mState = EndCompleteState;
            return false; // we are stopping here, because there might be more garbage on the end line,
                          // that we must ignore.
                          //
                          /// \todo allow this workaround to be disabled for newer scripts
        }

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

    bool FileParser::parseSpecial(int code, const TokenLoc& loc, Scanner& scanner)
    {
        if (code == Scanner::S_newline)
        {
            if (mState == BeginState)
                return true;
            if (mState == BeginCompleteState)
            {
                // parse the script body
                mScriptParser.reset();

                scanner.scan(mScriptParser);

                mState = EndNameState;
                return true;
            }

            if (mState == EndCompleteState || mState == EndNameState)
            {
                // we are done here -> ignore the rest of the script
                return false;
            }
        }

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

    void FileParser::parseEOF(Scanner& scanner)
    {
        if (mState != EndNameState && mState != EndCompleteState)
            Parser::parseEOF(scanner);
    }

    void FileParser::reset()
    {
        mState = BeginState;
        mName.clear();
        mScriptParser.reset();
        Parser::reset();
    }
}