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
|
#include <stdio.h>
#include "parser/parser.h"
struct Parser
{
struct Lexer* lexer;
struct Token current;
struct Token previous;
bool had_error;
};
static void advance_parser(struct Parser* parser)
{
parser->previous = parser->current;
parser->current = scan_token(parser->lexer);
}
static bool check(struct Parser* parser, enum TokenType type)
{
return parser->current.type == type;
}
static void error_at(struct Parser* parser, struct Token token, const char* message)
{
fprintf(stderr, "error: line %u: %s\n", token.line, message);
parser->had_error = true;
}
static bool consume(struct Parser* parser, enum TokenType type, const char* message)
{
if (check(parser, type))
{
advance_parser(parser);
return true;
}
error_at(parser, parser->current, message);
return false;
}
static bool parse_const(struct Parser* parser, struct Program* program)
{
struct ConstDecl decl;
if (!consume(parser, TOKEN_IDENTIFIER, "expected constant name after 'const'"))
return false;
decl.name = parser->previous;
if (!consume(parser, TOKEN_EQUAL, "expected '=' after constant name"))
return false;
if (!consume(parser, TOKEN_INTEGER, "expected integer value after '='"))
return false;
decl.value = parser->previous;
add_const(program, decl);
return true;
}
static bool parse_data(struct Parser* parser, struct Program* program)
{
struct DataDecl decl;
if (!consume(parser, TOKEN_IDENTIFIER, "expected data name after 'data'"))
return false;
decl.name = parser->previous;
if (!consume(parser, TOKEN_EQUAL, "expected '=' after data name"))
return false;
if (!consume(parser, TOKEN_STRING, "expected string value after '='"))
return false;
decl.value = parser->previous;
add_data(program, decl);
return true;
}
bool parse_program(struct Lexer* lexer, struct Program* out)
{
struct Parser parser;
parser.lexer = lexer;
parser.had_error = false;
advance_parser(&parser);
*out = create_program();
while (!check(&parser, TOKEN_EOF))
{
if (check(&parser, TOKEN_CONST))
{
advance_parser(&parser);
if (!parse_const(&parser, out))
return false;
}
else if (check(&parser, TOKEN_DATA))
{
advance_parser(&parser);
if (!parse_data(&parser, out))
return false;
}
else
{
error_at(&parser, parser.current, "expected a top-level declaration");
return false;
}
}
return !parser.had_error;
}
|