-
Notifications
You must be signed in to change notification settings - Fork 21
/
type_checker.cpp
73 lines (60 loc) · 1.97 KB
/
type_checker.cpp
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
/**
* This example shows how the parser behaviour changes with a grammar
* ambigouity in a c-like language. It is implemented using a filter callback in
* the `Typename` rule.
*
* Note the different interpretation of `x * y` as either a pointer definition
* or a multiplication.
*
* Example input:
* `x * y` -> parsed as a multiplication
* `type x` -> parsed as a type definition
* `x * y` -> now parsed as a variable definition (pointer to `y` of type `x`)
*/
#include <peg_parser/generator.h>
#include <iostream>
#include <unordered_set>
int main() {
using namespace std;
peg_parser::ParserGenerator<std::string> typeChecker;
unordered_set<string> types;
auto &g = typeChecker;
g.setSeparator(g["Whitespace"] << "[\t ]");
g.setStart(g["Expression"] << "Typedef | Vardef | Multiplication");
g["Typedef"] << "'type' Name" >> [&](auto e) {
types.emplace(e[0].string());
return "type definition";
};
g["Multiplication"] << "Variable '*' Variable" >> [](auto) { return "multiplication"; };
g["Vardef"] << "Type Name" >> [](auto) { return "variable definition"; };
// this rule only accepts types that have are declared in `types`
g["Typename"] << "Name" << [&](auto s) -> bool {
auto name = s->inner[0]->string();
return types.find(name) != types.end();
};
g["Type"] << "Typename '*'?";
g["Variable"] << "Name";
g["Atomic"] << "Variable";
g["Name"] << "[a-zA-Z] [a-zA-Z0-9]*";
while (true) {
string str;
cout << "> ";
getline(cin, str);
if (str == "q" || str == "quit") {
break;
}
try {
auto result = typeChecker.run(str);
cout << str << " = " << result << endl;
} catch (peg_parser::SyntaxError &error) {
auto syntax = error.syntax;
cout << " ";
cout << string(syntax->begin, ' ');
cout << string(syntax->length(), '~');
cout << "^\n";
cout << " "
<< "Syntax error while parsing " << syntax->rule->name << endl;
}
}
return 0;
}