%{
/*
 * Shell input grammar (yacc/bison format).
 *
 * Sander van Veen (6167969) / Taddeus Kroes (6054129).
 * <sandervv@gmail.com>      / <taddeuskroes@hotmail.com>
 */

#define YYDEBUG 1
#define YYERROR_VERBOSE 1

#include <stdio.h>
#include <string.h>

#include "input.yacc.h"
#include "input.lex.h"
#include "input.l.h"

void yyerror(const char *str) {
    fprintf(stderr, "error: parser reported \"%s\" (line %d, column %d)\n", str,
            current_line(), current_column());

    exit(EXIT_FAILURE);
}

%}

%token COMMENT IDENTIFIER ARGUMENT STRING INTEGER
%token EOL EOS CD EXIT PATH HELP

%type <str> PATH INTEGER IDENTIFIER ARGUMENT STRING
%type <str> Argument

%union {
    char * str;
}

%left '-' '+'

%%

Start: Commands { shell_exec(shell_pop_args()); }
    ;

Commands: Command
    | Commands EOL { shell_exec(shell_pop_args()); } Command
    | Commands '|' { shell_pipe(); shell_exec(shell_pop_args()); } Command
    ;

Command: /* Empty */
    | Builtin
    | IDENTIFIER { shell_push_args($1); }
    | IDENTIFIER { shell_push_args($1); } Arguments;

Builtin: EXIT     { shell_exit(); }
    | HELP        { shell_help(); }
    | CD Argument { shell_change_dir($2); }
    | '!' '!'     { shell_repeat(1); }
    | '!' INTEGER { shell_repeat(atoi($2)); }
    ;

Arguments: Argument      { shell_append_args($1); }
    | Arguments Argument { shell_append_args($2); }
    ;

Argument: STRING
    | ARGUMENT
    | IDENTIFIER
    | INTEGER
    | PATH
    ;

%%
