42sh/src/parser/grammar_advanced.c
2026-01-29 12:19:21 +01:00

82 lines
2 KiB
C

#define _POSIX_C_SOURCE 200809L
#include "grammar_advanced.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "grammar_basic.h"
static enum ast_redir_type redir_tok_to_ast_type(enum token_type tok_type)
{
switch (tok_type)
{
case TOKEN_REDIR_LEFT:
return AST_REDIR_TYPE_LESS;
case TOKEN_REDIR_RIGHT:
return AST_REDIR_TYPE_GREAT;
case TOKEN_REDIR_DOUBLE_RIGHT:
return AST_REDIR_TYPE_DGREAT;
case TOKEN_REDIR_LEFT_RIGHT:
return AST_REDIR_TYPE_LESSGREAT;
case TOKEN_REDIR_LEFT_AMP:
return AST_REDIR_TYPE_LESSAND;
case TOKEN_REDIR_RIGHT_AMP:
return AST_REDIR_TYPE_GREATAND;
case TOKEN_REDIR_RIGHT_PIPE:
return AST_REDIR_TYPE_CLOBBER;
default:
return AST_REDIR_TYPE_NULL;
}
}
struct ast *parse_redirection(struct lexer_context *ctx)
{
struct token *token = PEEK_TOKEN();
int io_number = -1;
if (token->type == TOKEN_IONUMBER)
{
io_number = atoi(token->data);
POP_TOKEN();
token = PEEK_TOKEN();
}
if (!is_token_redir(token))
{
perror("Syntax error: expected a redirection token but got something "
"else");
return NULL;
}
enum ast_redir_type redir_type = redir_tok_to_ast_type(token->type);
POP_TOKEN();
token = PEEK_TOKEN();
if (token->type != TOKEN_WORD)
{
perror("Syntax error: expected a word after redirection");
return NULL;
}
char *target = strdup(token->data);
POP_TOKEN();
return ast_create_redir(target, io_number, redir_type);
}
struct ast *parse_prefix(struct lexer_context *ctx)
{
struct token *token = TOKEN_PEEK();
if (token->type == TOKEN_ASSIGNMENT_WORD)
{
token = TOKEN_POP();
return ast_create_assignment_word(token->data);
}
else if (is_first(*token, RULE_REDIRECTION))
return parse_redirection(ctx);
else
{
perror("Syntax error: expected a prefix (redirection or assignment)");
return NULL;
}
}