1/*
2 * Copyright © 2016-2018 Sören Tempel
3 *
4 * This program is free software: you can redistribute it and/or
5 * modify it under the terms of the GNU Affero General Public
6 * License as published by the Free Software Foundation, either
7 * version 3 of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Affero General Public License for more details.
13 *
14 * You should have received a copy of the GNU Affero General Public
15 * License along with this program. If not, see
16 * <http://www.gnu.org/licenses/>.
17 */
18
19#ifndef TMSIM_SCANNER_H
20#define TMSIM_SCANNER_H
21
22#include <pthread.h>
23
24#include <sys/types.h>
25
26#include "queue.h"
27#include "token.h"
28
29/**
30 * Can be used in conjunction with emit if the character in the input
31 * string at the start position of this token should be used as the
32 * value field of the enqueued token.
33 *
34 * @param SCANNER Scanner for which a value should be emitted.
35 */
36#define TOKAUTO(SCANNER) (SCANNER->input[scr->start])
37
38/**
39 * Macro which must be used to return from a ::scanfn function. This
40 * macro sets the state field of given scanner and returns afterwards.
41 *
42 * @param SCANNER Scanner for which state field should be modified.
43 * @param FUNCTION Function pointer which should be used as the next
44 * state.
45 */
46#define LEXRET(SCANNER, FUNCTION) \
47 do { \
48 SCANNER->state = FUNCTION; \
49 return; \
50 } while (0)
51
52enum {
53 /**
54 * Passed to emit (as value) if the token doesn't have a
55 * meaningful character value.
56 */
57 TOKNOP = 0,
58
59 /**
60 * Amount of bytes needed for a string representation of the
61 * ::tmname type plus one byte for null termination. This value
62 * is somewhat heuristic.
63 */
64 STATELEN = 64,
65};
66
67/**
68 * Multithreaded lexer for the tmsim input files.
69 */
70typedef struct _scanner scanner;
71
72/**
73 * Function pointer representing the current state of a ::scanner.
74 */
75typedef void (*scanfn)(scanner *scr);
76
77struct _scanner {
78 /**
79 * Current state of the scanner. This field points to the
80 * function which should be invoked next for parsing the
81 * upcoming characters.
82 */
83 scanfn state;
84
85 /**
86 * Thread used to perform lexical scanning of the input string.
87 */
88 pthread_t thread;
89
90 /**
91 * Queue to which recognized tokens should be added.
92 */
93 queue *tqueue;
94
95 char *input; /**< Input string passed to ::scanstr. */
96 size_t inlen; /**< Length of the input string. */
97
98 size_t pos; /**< Current position in the input string. */
99 size_t start; /**< Start position of current token in input string. */
100
101 unsigned int line; /**< Line being analyzed currently. */
102 unsigned int column; /**< Column being analyzed currently. */
103};
104
105scanner *scanstr(char *, size_t);
106token *nexttoken(scanner *);
107void freescanner(scanner *);
108
109#endif