aboutsummaryrefslogtreecommitdiff
path: root/lib/Parser/ParserFile.cc
blob: 99a939f72c7de7bb2b7921d1798b47ef717777b7 (plain)
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

#include "cps/Diagnostics.h"
#include "cps/Parser.h"
#include "cps/FileAST.h"
#include <cstdio>

using namespace cps;

// OPENFILE <expr> FOR READ|WRITE|APPEND
std::unique_ptr<StmtAST> Parser::ParseOpenFile() {
    int Line = Lex.getLine();
    getNextToken(); // eat OPENFILE

    auto FileName = ParseExpression();
    if (!FileName) return nullptr;

    if (CurTok != tok_for) {
        cps::sourceDiagnostic(Lex.getLine(), "error: Expected FOR after OPENFILE filename at line %d\n", Lex.getLine());
        return nullptr;
    }
    getNextToken(); // eat FOR

    FileMode Mode;
    switch (CurTok) {
    case tok_read:   Mode = FileMode::Read;   break;
    case tok_write:  Mode = FileMode::Write;  break;
    case tok_append: Mode = FileMode::Append; break;
    case tok_random:
        cps::sourceDiagnostic(Lex.getLine(), "error: File mode RANDOM is not implemented (text files only) at line %d\n",
                Lex.getLine());
        return nullptr;
    default:
        cps::sourceDiagnostic(Lex.getLine(), "error: Expected file mode READ, WRITE or APPEND at line %d\n", Lex.getLine());
        return nullptr;
    }
    getNextToken(); // eat the mode keyword

    return std::make_unique<OpenFileStmtAST>(std::move(FileName), Mode, Line);
}

// READFILE <expr>, <identifier>
std::unique_ptr<StmtAST> Parser::ParseReadFile() {
    int Line = Lex.getLine();
    getNextToken(); // eat READFILE

    auto FileName = ParseExpression();
    if (!FileName) return nullptr;

    if (CurTok != ',') {
        cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' after READFILE filename at line %d\n", Lex.getLine());
        return nullptr;
    }
    getNextToken(); // eat ','

    if (CurTok != tok_identifier) {
        cps::sourceDiagnostic(Lex.getLine(), "error: Expected variable name after ',' in READFILE at line %d\n", Lex.getLine());
        return nullptr;
    }
    std::string VarName = Lex.IdentifierStr;
    getNextToken(); // eat the variable name

    if (CurTok == '[' || CurTok == '.' || CurTok == '^') {
        // Consume the whole designator so it cannot replay as statements.
        std::vector<DesignatorAccess> Dummy;
        ParseDesignatorSuffix(Dummy);
        cps::sourceDiagnostic(Lex.getLine(), "error: READFILE target must be a plain STRING variable at line %d\n", Line);
        return nullptr;
    }

    return std::make_unique<ReadFileStmtAST>(std::move(FileName), VarName, Line);
}

// WRITEFILE <expr>, <expr>
std::unique_ptr<StmtAST> Parser::ParseWriteFile() {
    int Line = Lex.getLine();
    getNextToken(); // eat WRITEFILE

    auto FileName = ParseExpression();
    if (!FileName) return nullptr;

    if (CurTok != ',') {
        cps::sourceDiagnostic(Lex.getLine(), "error: Expected ',' after WRITEFILE filename at line %d\n", Lex.getLine());
        return nullptr;
    }
    getNextToken(); // eat ','

    auto Data = ParseExpression();
    if (!Data) return nullptr;

    return std::make_unique<WriteFileStmtAST>(std::move(FileName), std::move(Data), Line);
}

// CLOSEFILE <expr>
std::unique_ptr<StmtAST> Parser::ParseCloseFile() {
    int Line = Lex.getLine();
    getNextToken(); // eat CLOSEFILE

    auto FileName = ParseExpression();
    if (!FileName) return nullptr;

    return std::make_unique<CloseFileStmtAST>(std::move(FileName), Line);
}