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
|
/**
* forspll - LLVM-based Forsp compiler
* Copyright (C) 2024 Clyne Sullivan <clyne@bitgloo.com>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "parser.hpp"
#include <cctype>
#include <iostream>
std::string name;
static bool isname(char ch) {
return !isspace(ch) && ch != ')';
}
static std::string_view extractName(std::string_view sv)
{
name.clear();
while (!sv.empty()) {
const auto ch = sv.front();
if (isname(ch)) {
name += ch;
sv.remove_prefix(1);
} else {
break;
}
}
return sv;
}
std::pair<std::string_view, Token> nextToken(std::string_view sv)
{
if (sv.empty())
return {sv, Token::none};
while (std::isspace(sv.front()))
sv.remove_prefix(1);
if (sv.empty())
return {sv, Token::none};
const auto ch = sv.front();
if (ch == ';') {
return {{}, Token::none};
} else if (ch == '(') {
return {sv.substr(1), Token::ThunkOpen};
} else if (ch == ')') {
return {sv.substr(1), Token::ThunkClose};
} else if (ch == '\'') {
return {extractName(sv.substr(1)), Token::Quote};
} else if (ch == '$') {
return {extractName(sv.substr(1)), Token::PopVar};
} else if (ch == '^') {
return {extractName(sv.substr(1)), Token::PushVar};
} else if (isdigit(ch) || (ch == '-' && sv.size() > 1 && isdigit(sv[1]))) {
return {extractName(sv), Token::Number};
} else if (isname(ch)) {
return {extractName(sv), Token::Var};
}
return {sv, Token::none};
}
void printToken(Token tok)
{
switch (tok) {
case Token::ThunkOpen:
std::cout << "ThunkOpen ";
break;
case Token::ThunkClose:
std::cout << "ThunkClose ";
break;
case Token::Quote:
std::cout << "Quote ";
break;
case Token::PopVar:
std::cout << "PopVar ";
break;
case Token::PushVar:
std::cout << "PushVar ";
break;
case Token::Var:
std::cout << "Var ";
break;
case Token::Number:
std::cout << "Number ";
break;
case Token::none:
//std::cout << "none ";
break;
}
}
|