about summary refs log tree commit diff
path: root/src/fix-ng/parser.cc
blob: e0812817af59d0366d4a9dff4cfe70c7e72ecf04 (plain) (blame)
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 <sstream>

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

extern "C" {
#include <sglr.h>
#include <asfix2.h>
}

#include "parser.hh"
#include "shared.hh"
#include "fix-expr.hh"
#include "expr.hh"
#include "parse-table.h"


struct Cleanup : TermFun
{
    string basePath;

    virtual ATerm operator () (ATerm e)
    {
        char * s;

        if (ATmatch(e, "Str(<str>)", &s)) {
            string s2(s);
            return ATmake("Str(<str>)",
                string(s2, 1, s2.size() - 2).c_str());
        }

        if (ATmatch(e, "Path(<str>)", &s)) {
            string path(s);
            if (path[0] != '/')
                path = basePath + "/" + path;
            return ATmake("Str(<str>)", canonPath(path).c_str());
        }

        if (ATmatch(e, "Int(<str>)", &s)) {
            istringstream s2(s);
            int n;
            s2 >> n;
            return ATmake("Int(<int>)", n);
        }

        return e;
    }
};


Expr parseExprFromFile(Path path)
{
#if 0
    /* Perhaps this is already an imploded parse tree? */
    Expr e = ATreadFromNamedFile(path.c_str());
    if (e) return e;
#endif

    /* If `path' refers to a directory, append `/default.fix'. */
    struct stat st;
    if (stat(path.c_str(), &st))
        throw SysError(format("getting status of `%1%'") % path);
    if (S_ISDIR(st.st_mode))
        path = canonPath(path + "/default.fix");

    /* Initialise the SDF libraries. */
    static bool initialised = false;
    static ATerm parseTable = 0;
    static language lang = 0;

    if (!initialised) {
        PT_initMEPTApi();
        PT_initAsFix2Api();
        SGinitParser(ATfalse);

        ATprotect(&parseTable);
        parseTable = ATreadFromBinaryString(
            (char *) fixParseTable, sizeof fixParseTable);
        if (!parseTable)
            throw Error(format("cannot construct parse table term"));

        ATprotect(&lang);
        lang = ATmake("Fix");
        if (!SGopenLanguageFromTerm(
                (char *) programId.c_str(), lang, parseTable))
            throw Error(format("cannot open language"));

        SG_STARTSYMBOL_ON();
        SG_OUTPUT_ON();
        SG_ASFIX2ME_ON();
        SG_AMBIGUITY_ERROR_ON();

        initialised = true;
    }

    ATerm result = SGparseFile((char *) programId.c_str(), lang,
        "Expr", (char *) path.c_str());
    if (!result)
        throw SysError(format("parse failed in `%1%'") % path);
    if (SGisParseError(result))
        throw Error(format("parse error in `%1%': %2%")
            % path % printTerm(result));

    PT_ParseTree tree = PT_makeParseTreeFromTerm(result);
    if (!tree)
        throw Error(format("cannot create parse tree"));
    
    ATerm imploded = PT_implodeParseTree(tree,
        ATtrue,
        ATtrue,
        ATtrue,
        ATtrue,
        ATtrue,
        ATtrue,
        ATfalse,
        ATtrue,
        ATtrue,
        ATtrue,
        ATfalse);
    if (!imploded)
        throw Error(format("cannot implode parse tree"));

    Cleanup cleanup;
    cleanup.basePath = dirOf(path);
    return bottomupRewrite(cleanup, imploded);
}