Files
minishell/minishell-codex/src/parser/lexer.c
2026-02-09 20:47:43 +01:00

132 lines
2.0 KiB
C

#include "minishell.h"
static t_token *token_new(t_tokentype type, const char *text, size_t len)
{
t_token *t = (t_token *)calloc(1, sizeof(t_token));
if (!t)
return NULL;
t->type = type;
if (text)
t->text = ms_strndup(text, len);
return t;
}
static void token_add(t_token **head, t_token *new)
{
t_token *cur;
if (!new)
return;
if (!*head)
{
*head = new;
return;
}
cur = *head;
while (cur->next)
cur = cur->next;
cur->next = new;
}
void free_tokens(t_token *toks)
{
t_token *n;
while (toks)
{
n = toks->next;
free(toks->text);
free(toks);
toks = n;
}
}
static int is_meta(char c)
{
return (c == '|' || c == '<' || c == '>');
}
static int read_word(const char *line, size_t *i, t_token **out)
{
size_t start = *i;
int in_single = 0;
int in_double = 0;
while (line[*i])
{
if (line[*i] == '\'' && !in_double)
in_single = !in_single;
else if (line[*i] == '"' && !in_single)
in_double = !in_double;
else if (!in_single && !in_double)
{
if (ms_is_space(line[*i]) || is_meta(line[*i]))
break;
}
(*i)++;
}
if (in_single || in_double)
return 1;
*out = token_new(TOK_WORD, line + start, *i - start);
return 0;
}
t_token *lex_line(const char *line, int *error)
{
t_token *toks = NULL;
size_t i = 0;
*error = 0;
while (line[i])
{
if (ms_is_space(line[i]))
{
i++;
continue;
}
if (line[i] == '|')
{
token_add(&toks, token_new(TOK_PIPE, "|", 1));
i++;
continue;
}
if (line[i] == '<')
{
if (line[i + 1] == '<')
{
token_add(&toks, token_new(TOK_HEREDOC, "<<", 2));
i += 2;
}
else
{
token_add(&toks, token_new(TOK_REDIR_IN, "<", 1));
i++;
}
continue;
}
if (line[i] == '>')
{
if (line[i + 1] == '>')
{
token_add(&toks, token_new(TOK_REDIR_APPEND, ">>", 2));
i += 2;
}
else
{
token_add(&toks, token_new(TOK_REDIR_OUT, ">", 1));
i++;
}
continue;
}
{
t_token *w = NULL;
if (read_word(line, &i, &w))
{
*error = 1;
free_tokens(toks);
return NULL;
}
token_add(&toks, w);
}
}
return toks;
}