summaryrefslogtreecommitdiff
path: root/core/lexer.c
diff options
context:
space:
mode:
Diffstat (limited to 'core/lexer.c')
-rw-r--r--core/lexer.c84
1 files changed, 84 insertions, 0 deletions
diff --git a/core/lexer.c b/core/lexer.c
new file mode 100644
index 0000000..d6e5e66
--- /dev/null
+++ b/core/lexer.c
@@ -0,0 +1,84 @@
+#include <errno.h>
+#include <stdbool.h>
+#include "cescal/lexer.h"
+#include "cescal/log.h"
+
+/*
+ * Returns true if the given character is a whitespace
+ *
+ * @c: Character to check
+ */
+static inline bool
+lexer_is_ws(char c)
+{
+ switch (c) {
+ case '\t':
+ case '\n':
+ case ' ':
+ case '\f':
+ case '\r':
+ return true;
+ }
+
+ return false;
+}
+
+/*
+ * Consume a single character from the input source file and
+ * optionally skip whitespace
+ *
+ * @state: Compiler state
+ * @skip_ws: If true skip whitespace
+ */
+static char
+lexer_consume_single(struct cescal_state *state, bool skip_ws)
+{
+ char c;
+
+ if (state == NULL) {
+ return '\0';
+ }
+
+ while ((c = readbuf_read(&state->rb, state->in_fd)) != '\0') {
+ if (lexer_is_ws(c)) {
+ continue;
+ }
+
+ return c;
+ }
+
+ return '\0';
+}
+
+int
+lexer_nom(struct cescal_state *state, struct token *res)
+{
+ char c;
+
+ if (state == NULL || res == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((c = lexer_consume_single(state, true)) == '\0') {
+ return -1;
+ }
+
+ switch (c) {
+ case '(':
+ res->type = TT_LPAREN;
+ res->c = c;
+ return 0;
+ case ')':
+ res->type = TT_RPAREN;
+ res->c = c;
+ return 0;
+ case ',':
+ res->type = TT_COMMA;
+ res->c = c;
+ return 0;
+ }
+
+ cc_error("got unknown token '%c'\n", c);
+ return -1;
+}