Line data Source code
1 : /***************************************************************************//**
2 :
3 : @file lex.c
4 :
5 : @author Stephen Brennan
6 :
7 : @date Created Friday, 29 January 2016
8 :
9 : @brief All lexer-related functions.
10 :
11 : @copyright Copyright (c) 2016, Stephen Brennan. Released under the Revised
12 : BSD License. See LICENSE.txt for details.
13 :
14 : *******************************************************************************/
15 :
16 : #include <stdio.h>
17 :
18 : #include "libstephen/re_internals.h"
19 :
20 34 : void escape(Lexer *l)
21 : {
22 34 : switch (InputIdx(l->input, l->index)) {
23 : case L'(':
24 2 : l->tok = (Token){CharSym, L'('};
25 2 : break;
26 : case L')':
27 2 : l->tok = (Token){CharSym, L')'};
28 2 : break;
29 : case L'[':
30 2 : l->tok = (Token){CharSym, L'['};
31 2 : break;
32 : case L']':
33 2 : l->tok = (Token){CharSym, L']'};
34 2 : break;
35 : case L'+':
36 2 : l->tok = (Token){CharSym, L'+'};
37 2 : break;
38 : case L'-':
39 2 : l->tok = (Token){CharSym, L'-'};
40 2 : break;
41 : case L'*':
42 2 : l->tok = (Token){CharSym, L'*'};
43 2 : break;
44 : case L'?':
45 2 : l->tok = (Token){CharSym, L'?'};
46 2 : break;
47 : case L'^':
48 2 : l->tok = (Token){CharSym, L'^'};
49 2 : break;
50 : case L'n':
51 2 : l->tok = (Token){CharSym, L'\n'};
52 2 : break;
53 : case L'.':
54 2 : l->tok = (Token){CharSym, L'.'};
55 2 : break;
56 : case L'|':
57 2 : l->tok = (Token){CharSym, L'|'};
58 2 : break;
59 : default:
60 10 : l->tok = (Token){Special, InputIdx(l->input, l->index)};
61 10 : break;
62 : }
63 34 : }
64 :
65 532 : Token nextsym(Lexer *l)
66 : {
67 532 : if (l->tok.sym == Eof) {
68 97 : return l->tok; // eof never ceases to be eof!
69 : }
70 :
71 : // Handle buffered symbols first.
72 435 : l->prev = l->tok;
73 435 : if (l->nbuf > 0) {
74 15 : l->tok = l->buf[0];
75 27 : for (size_t i = 0; i < l->nbuf - 1; i++) {
76 12 : l->buf[i] = l->buf[i+1];
77 : }
78 15 : l->nbuf--;
79 : //printf(";; nextsym(): unbuffering {%s, '%s'}\n", names[l->tok.sym],
80 : // char_to_string(l->tok.c));
81 15 : return l->tok;
82 : }
83 :
84 420 : switch (InputIdx(l->input, l->index)) {
85 : case L'(':
86 13 : l->tok = (Token){LParen, L'('};
87 13 : break;
88 : case L')':
89 13 : l->tok = (Token){RParen, L')'};
90 13 : break;
91 : case L'[':
92 12 : l->tok = (Token){LBracket, L'['};
93 12 : break;
94 : case L']':
95 12 : l->tok = (Token){RBracket, L']'};
96 12 : break;
97 : case L'+':
98 17 : l->tok = (Token){Plus, L'+'};
99 17 : break;
100 : case L'-':
101 24 : l->tok = (Token){Minus, L'-'};
102 24 : break;
103 : case L'*':
104 25 : l->tok = (Token){Star, L'*'};
105 25 : break;
106 : case L'?':
107 19 : l->tok = (Token){Question, L'?'};
108 19 : break;
109 : case L'^':
110 9 : l->tok = (Token){Caret, L'^'};
111 9 : break;
112 : case L'|':
113 9 : l->tok = (Token){Pipe, L'|'};
114 9 : break;
115 : case L'.':
116 9 : l->tok = (Token){Dot, L'.'};
117 9 : break;
118 : case L'\\':
119 34 : l->index++;
120 34 : escape(l);
121 34 : break;
122 : case L'\0':
123 97 : l->tok = (Token){Eof, L'\0'};
124 97 : break;
125 : default:
126 127 : l->tok = (Token){CharSym, InputIdx(l->input, l->index)};
127 127 : break;
128 : }
129 420 : l->index++;
130 : //printf(";; nextsym(): {%s, '%s'}\n", names[l->tok.sym], char_to_string(l->tok.c));
131 420 : return l->tok;
132 : }
133 :
134 15 : void unget(Token t, Lexer *l)
135 : {
136 15 : if (l->nbuf >= LEXER_BUFSIZE) {
137 0 : fprintf(stderr, "error: maximum lexer buffer size exceeded, dumbass.\n");
138 0 : exit(1);
139 : }
140 :
141 : //printf(";; unget(): buffering {%s, '%s'}\n", names[t.sym], char_to_string(t.c));
142 :
143 27 : for (int i = l->nbuf - 1; i >= 0; i--) {
144 12 : l->buf[i+1] = l->buf[i];
145 : }
146 15 : l->buf[0] = l->tok;
147 15 : l->tok = t;
148 15 : l->nbuf++;
149 15 : }
|