Parser

Recursive-descent parser: transforms the token stream into an AST.

Parser definitions for the 42sh shell.

Author

jguillem pulgamecanica

Functions

t_ast *parser_parse(t_list *tokens, t_shell *shell)

consume a t_list* of tokens and return the AST root.

Returns NULL on syntax error (error printed to stderr).

The token list is NOT freed here, caller frees it with lexer_free_tokens().

consume a t_list* of tokens and return the AST root.

this is the main function of the parser module

call parse list which wrap all the layers and check for EOF

parse_list (“;” and “&” separators) -> parse_and_or

parse_and_or (”&&” and “||” separators) -> parse_pipeline

parse_pipeline (“|” separator) -> parse_command

parse_command (read simple command) -> parse_subshell

parse_subshell recurse on parse_list

parse_heredoc walk ast and collect heredocs

Parameters:
  • tokens – pointer on a struct s_list of tokens

  • shell – pointer on a struct s_shell

Returns:

t_ast struct

int parser_collect_heredocs(t_ast *ast, t_shell *shell)

walk the AST after parsing and read heredoc content

from stdin for each << redirection.

shell is needed to read from the correct fd and to check SIGINT.

Returns 0 on success, -1 if SIGINT aborted heredoc input.

walk the AST after parsing and read heredoc content

Parameters:
  • ast – : struct s_ast pointer

  • shell – : struct s_shell pointer

Returns:

0 on success, -1 on SIGINT

void heredoc_expand_config(t_redir *redir)

fill the heredoc_delim and heredoc_quoted fields of the t_redir struct

Parameters:

redir – : t_redir struct

int parser_accept(t_parser *p, t_token_type type)

consume token when type correspondance

Parameters:
  • p – struct s_parser pointer

  • type – enum e_token_type

Returns:

1 | 0

int is_redir(t_token_type type)

check is the the token is a redirect one

Parameters:

type – enum e_token_type

Returns:

1 | 0

t_token *parser_peek(t_parser *p)

recuperate current token without consume it

Parameters:

p – struct s_parser pointer

Returns:

struct s_token (current token)

t_token *parser_next(t_parser *p)

recuperate current token and consume it

Parameters:

p – struct s_parser pointer

Returns:

struct s_token (current token)

t_ast *parse_subshell(t_parser *p)

create a new NODE_SUBSHELL with its child and redirs

Parameters:

p – struct s_parser pointer

Returns:

pointer on struct s_ast

t_ast *parse_block(t_parser *p)

create a new NODE_BLOCK with its child and redirs

Parameters:

p – struct s_parser pointer

Returns:

pointer on struct s_ast

t_ast *parse_command(t_parser *p)

handle (subshell) and (block) then parser command

Parameters:

pt_parser struct

Returns:

t_ast struct

t_ast *parse_simple_command(t_parser *p)

handle commands and detect subshells

Parameters:

p – struct s_parser

Returns:

a pointer on a struct s_ast

t_ast *parse_pipeline(t_parser *p)

detect the pipe and create a t_ast node with two commands

Parameters:

p – struct s_parser

Returns:

a pointer on a struct s_ast

t_ast *parse_and_or(t_parser *p)

detect && or || and create a t_ast node with two commands

Parameters:

p – struct s_parser

Returns:

a pointer on a struct s_ast

t_ast *parse_list(t_parser *p)

handle list (& or ; separator)

Parameters:

p – struct s_parser pointer

Returns:

struct s_ast pointer

struct t_parser
#include <parser.h>

Parser internal state.

Param tokens:

the t_list* of t_token* produced by the lexer.

Param current:

the list node the parser is currently examining.

Param error:

human-readable error string (set on syntax error, free’d by parser).

Public Members

t_list *tokens
t_list *current
char *error

parser.c — Main Entry Point

main file of parser module

file for parser utils functions

Author

jguillem, pulgamecanica

Author

jguillem

Functions

t_ast *parser_parse(t_list *tokens, t_shell *shell)

receive a tokens from lexer and build an ast binary tree

consume a t_list* of tokens and return the AST root.

this is the main function of the parser module

call parse list which wrap all the layers and check for EOF

parse_list (“;” and “&” separators) -> parse_and_or

parse_and_or (”&&” and “||” separators) -> parse_pipeline

parse_pipeline (“|” separator) -> parse_command

parse_command (read simple command) -> parse_subshell

parse_subshell recurse on parse_list

parse_heredoc walk ast and collect heredocs

Parameters:
  • tokens – pointer on a struct s_list of tokens

  • shell – pointer on a struct s_shell

Returns:

t_ast struct

parser_command.c — Simple Commands

file for parse command

Author

jguillem

Functions

t_ast *ast_new_command(t_cmd *cmd)

allocate memory and define type for a NODE_COMMAND

AST construction helpers.

Parameters:

cmd – struct s_cmd

Returns:

pointer on struct s_ast

t_ast *parse_command(t_parser *p)

handle (subshell) and (block) then parser command

Parameters:

pt_parser struct

Returns:

t_ast struct

static t_cmd *command_init(void)

initialize t_cmd struct

static void parser_error_unexpected(t_parser *p, t_token *token)

handle t_parser error field

Parameters:
static char **command_size(t_parser *p, t_cmd *command)

allocate memory of t_cmd struct argv field

Parameters:
Returns:

char **argv

static t_ast *command_build(t_parser *p, t_cmd *command)

fill the t_cmd struct

Parameters:
Returns:

t_ast struct

static int is_assignment(char *str)

check for valid assignment

Parameters:

str – char *

Returns:

0 | 1

static void parse_assignment(t_parser *p, t_cmd *command)

append assignments to t_cmd struct

Parameters:
t_ast *parse_simple_command(t_parser *p)

handle commands and detect subshells

Parameters:

p – struct s_parser

Returns:

a pointer on a struct s_ast

parser_pipeline.c — Pipes

file for pipeline parser

Author

jguillem

Functions

t_ast *parse_pipeline(t_parser *p)

detect the pipe and create a t_ast node with two commands

Parameters:

p – struct s_parser

Returns:

a pointer on a struct s_ast

parser_and_or.c — Logical Operators

file for && and || parser

Author

jguillem

Functions

static int detect_and_or(t_parser *p, t_node_type *type)

helper function to detect TOK_AND and TOK_OR

Parameters:
  • p – struct s_parser

  • type – enum e_node_type

Returns:

0 (no one), 1 (TOK_AND), 2 (TOK_OR)

t_ast *parse_and_or(t_parser *p)

detect && or || and create a t_ast node with two commands

Parameters:

p – struct s_parser

Returns:

a pointer on a struct s_ast

parser_list.c — Sequences and Background

file for parse list

Author

jguillem

Functions

static int detect_separator(t_parser *p, t_node_type *operator)

helper function for parse_list

Parameters:
  • p – struc s_parser pointer

  • operator – enum e_node_type pointer

Returns:

0 (no separator), 1 (; separator), 2 (&separator)

t_ast *parse_list(t_parser *p)

handle list (& or ; separator)

Parameters:

p – struct s_parser pointer

Returns:

struct s_ast pointer

parser_group.c — Subshells and Blocks

file for parse group

Author

jguillem

Functions

t_ast *ast_new_group(t_node_type type, t_ast *child, t_list *redirs)

helper function for the parse_subshell function

Parameters:
  • type – enum e_node_type

  • child – struct s_ast

  • redirs – struct s_list with a t_redir * as content

Returns:

pointer on struct s_ast

static t_ast *parse_group(t_parser *p, t_ast *child, t_node_type node)

factorization of the end of parse_subshell and parse_block

Parameters:
  • p – struct s_parser pointer

  • child – struct s_ast pointer @paran node enum e_node_type

Returns:

pointer on struct s_ast

t_ast *parse_subshell(t_parser *p)

create a new NODE_SUBSHELL with its child and redirs

Parameters:

p – struct s_parser pointer

Returns:

pointer on struct s_ast

t_ast *parse_block(t_parser *p)

create a new NODE_BLOCK with its child and redirs

Parameters:

p – struct s_parser pointer

Returns:

pointer on struct s_ast

parser_heredoc.c — Here-documents

file to handle heredoc

Author

jguillem

Functions

static char *result_concat(char *begin, size_t *len, size_t read, char *src)
static char *strip_tab(char *origin)

strip the leading tabulations of origin

Parameters:

origin – : raw string

Returns:

an allocated cleaned string

static char *read_heredoc(t_redir *redir, const char *prompt)

read the user input and store each line

Parameters:
  • redir – : a pointer on struct s_redir

  • prompt – : the prompt symbol of the heredoc

Returns:

a char pointer on the content of the heredoc

static void read_heredoc_from_pipe(t_redir *redir, int pipefd[2])

read from the pipe out

Parameters:
  • redir – pointer on a struct s_redir

  • pipefd – the 2 ends of the pipe

static int fork_heredoc(t_redir *redir)

create a fork for the heredoc collecting

in order to catch SIGINT only at the heredoc level

Parameters:

redir – pointer on a struct s_redir

Returns:

0 | -1

static int collect_heredocs_from_list(t_list *lst)

helper function for collect heredocs from command or subshell

store redirections

Parameters:

lst – : a struct s_list pointer

static int collect_heredocs_from_command(t_cmd *cmd)

collect redirections of commands

Parameters:

cmd – : struct s_cmd pointer

static int collect_heredocs_from_group(t_group *group)

collect redirections of group

Parameters:

group – : struct s_group pointer

void heredoc_expand_config(t_redir *redir)

fill the heredoc_delim and heredoc_quoted fields of the t_redir struct

Parameters:

redir – : t_redir struct

static int ast_walk(t_ast *ast, t_shell *shell)

traverses the ast tree and collect heredocs content, stopping on SIGINT

Parameters:
  • ast – : a pointer on a struct s_ast

  • shell – : the shell struct

Returns:

0 on success, -1 on SIGINT

static void heredoc_sigint_handler(int signal)
int parser_collect_heredocs(t_ast *ast, t_shell *shell)

stop ast walking and collect heredoc on SIGINT

walk the AST after parsing and read heredoc content

Parameters:
  • ast – : struct s_ast pointer

  • shell – : struct s_shell pointer

Returns:

0 on success, -1 on SIGINT

Variables

volatile sig_atomic_t g_sigint_heredoc = 0

parser_utils.c — Utilities

Functions

t_ast *ast_new_binary(t_node_type type, t_ast *left, t_ast *right)

create and allocate new binary ast node

Parameters:
  • type – enum e_node_type

  • left – struct s_ast pointer

  • right – struct s_ast pointer

Returns:

struct s_ast pointer

int is_redir(t_token_type type)

check is the the token is a redirect one

Parameters:

type – enum e_token_type

Returns:

1 | 0

t_token *parser_peek(t_parser *p)

recuperate current token without consume it

Parameters:

p – struct s_parser pointer

Returns:

struct s_token (current token)

t_token *parser_next(t_parser *p)

recuperate current token and consume it

Parameters:

p – struct s_parser pointer

Returns:

struct s_token (current token)

int parser_accept(t_parser *p, t_token_type type)

consume token when type correspondance

Parameters:
  • p – struct s_parser pointer

  • type – enum e_token_type

Returns:

1 | 0

memory.c — AST Memory Management

file for free memory functions

Author

jguillem

Functions

void redir_free(t_redir *redir)

free t_redir helper

Parameters:

redirt_redir struct

static void free_argv(char **argv)

free argv

Parameters:

argv – array of strings

static void cmd_free(t_cmd *cmd)

free t_cmd

Parameters:

cmdt_cmd struct

void ast_free(t_ast *node)

free ast recursively

Parameters:

nodet_ast struct

ast_display.c — Debug Display

Display and JSON serialization of AST trees.

Author

pulgamecanica