core: Add initial lexer and parser sources

Signed-off-by: Ian Moffett <ian@mirocom.org>
This commit is contained in:
2026-02-14 00:11:26 -05:00
parent f249a12b5a
commit 9e22c31a2f
5 changed files with 182 additions and 0 deletions

93
core/lexer.c Normal file
View File

@@ -0,0 +1,93 @@
#include <stdint.h>
#include <stddef.h>
#include <unistd.h>
#include <stdbool.h>
#include "rifle/lexer.h"
#include "rifle/trace.h"
/*
* Returns true if the given input character is a
* whitespace character
*/
static inline bool
lexer_is_ws(char c)
{
switch (c) {
case '\n':
case '\t':
case '\r':
case '\f':
case ' ':
return true;
}
return false;
}
/*
* Consume a single byte from the input source file
* while skipping any whitespace characters.
*
* @state: Compiler state
* @keep_ws: If true, preserve whitespace
*
* Returns the consumed character on success, otherwise
* '\0' upon failure.
*/
static char
lexer_nom(struct rifle_state *state, bool keep_ws)
{
char c;
if (state == NULL) {
return '\0';
}
while (read(state->in_fd, &c, 1) > 0) {
if (lexer_is_ws(c) && !keep_ws) {
continue;
}
return c;
}
return '\0';
}
int
lexer_scan(struct rifle_state *state, struct token *res)
{
char c;
if (state == NULL || res == NULL) {
return -1;
}
if ((c = lexer_nom(state, false)) == '\0') {
return -1;
}
switch (c) {
case '+':
res->type = TT_PLUS;
res->c = c;
return 0;
case '-':
res->type = TT_MINUS;
res->c = c;
return 0;
case '*':
res->type = TT_STAR;
res->c = c;
return 0;
case '/':
res->type = TT_SLASH;
res->c = c;
return 0;
default:
trace_error(state, "unexpected token '%c'\n", c);
break;
}
return -1;
}

51
core/parser.c Normal file
View File

@@ -0,0 +1,51 @@
#include <stdint.h>
#include <stddef.h>
#include "rifle/parser.h"
#include "rifle/token.h"
#include "rifle/trace.h"
#include "rifle/lexer.h"
#include "rifle/state.h"
/* Symbolic token */
#define symtok(tok) \
"[" tok "]"
/* Quoted token */
#define qtok(tok) \
"'" tok "'"
/* Convert token to string */
#define tokstr1(tt) \
toktab[(tt)]
/* Convert token to string */
#define tokstr(tok) \
tokstr1((tok)->type)
/*
* Table used to convert token constants into human
* readable strings
*/
static const char *toktab[] = {
[TT_NONE] = symtok("none"),
[TT_PLUS] = qtok("+"),
[TT_MINUS] = qtok("-"),
[TT_STAR] = qtok("*"),
[TT_SLASH] = qtok("/")
};
int
parser_parse(struct rifle_state *state)
{
struct token tok;
if (state == NULL) {
return 0;
}
while (lexer_scan(state, &tok) == 0) {
trace_debug("got %s\n", tokstr(&tok));
}
return 0;
}

View File

@@ -2,6 +2,7 @@
#include <unistd.h>
#include <fcntl.h>
#include "rifle/state.h"
#include "rifle/parser.h"
/* Compiler version */
#define RIFLE_VERSION "0.0.1"
@@ -38,6 +39,11 @@ compile(const char *in_path)
return -1;
}
if (parser_parse(&state) < 0) {
rifle_state_destroy(&state);
return -1;
}
rifle_state_destroy(&state);
return 0;
}
@@ -72,5 +78,6 @@ main(int argc, char **argv)
printf("fatal: no input files\n");
return -1;
}
return 0;
}

18
inc/rifle/lexer.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef RIFLE_LEXER_H
#define RIFLE_LEXER_H 1
#include <stdint.h>
#include "rifle/token.h"
#include "rifle/state.h"
/*
* Scan a single token from the source input
*
* @state: Compiler state
* @res: Result is written here
*
* Returns zero on success
*/
int lexer_scan(struct rifle_state *state, struct token *res);
#endif /* !RIFLE_LEXER_H */

13
inc/rifle/parser.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef RIFLE_PARSER_H
#define RIFLE_PARSER_H 1
#include "rifle/state.h"
/*
* Begin parsing the input source file
*
* @state: Compiler state
*/
int parser_parse(struct rifle_state *state);
#endif /* !RIFLE_PARSER_H */