/*
 * Shell input lexer (flex format).
 *
 * Sander van Veen (6167969) / Taddeus Kroes (6054129).
 * <sandervv@gmail.com>      / <taddeuskroes@hotmail.com>
 */

%{

// To get rid of the error "‘input’ defined but not used".
#define YY_NO_INPUT

#include <stdio.h>
#include "input.l.h"
#include "input.yacc.h"

// Column / line counters (used in error reporting)
int line_no = 1, column_no = 0;

extern int current_line(void){ return line_no; }
extern int current_column(void){ return column_no; }
extern void reset_line(void){ line_no = 1; }
extern void reset_column(void){ column_no = 0; }

%}

%option noyywrap
%option nounput

%x id
%x num

id  [a-zA-Z_][[:alnum:]_.-]*
num [0-9]+
wsp [\r\t ]

%%

    /* Strings, like "abc" */
\"([^\\"]|\\.)*\" {
        column_no += yyleng;
        yylval.str = strdup(yytext);
        return STRING;
    }

    /* Hexadecimal e.g. 0xf00fcafe */
    /* Octal e.g. 0777 */
    /* Numbers 0, 42, 9001 etc. */
0x[0-9a-f]+|{num} {
        column_no += yyleng;
        yylval.str = strdup(yytext);
        return INTEGER;
    }

    /* Exit shell builtin */
exit {
        column_no += 4;
        return EXIT;
    }

    /* Help shell builtin */
help {
        column_no += 4;
        return HELP;
    }

    /* Change directory builtin */
cd {
        column_no += 2;
        return CD;
    }

    /* Identifiers: source, cat, echo */
{id} {
        column_no += yyleng;
        yylval.str = strdup(yytext);
        return IDENTIFIER;
    }

    /* Pipe operator */
\| {
        column_no++;
        return *yytext;
    }

    /* Repeat operator */
! {
        column_no++;
        return *yytext;
    }

    /* Path or path with filename: ./a/, ../, config/, /tmp/, /tmp/file  */
\.*{id}?\/[^\t\n ]* {
        column_no += yyleng;
        yylval.str = strdup(yytext);
        return PATH;
    }

    /* Argument (filenames and such): hello.txt, .config */
{id}[^\t\n |]+ {
        column_no += yyleng;
        yylval.str = strdup(yytext);
        return ARGUMENT;
    }

#[^\n]+ { /* ignore comments */ }

    /* White space */
\n {
        line_no++;
        reset_column();
        shell_entry();
        return EOL;
    }

    /* White space */
{wsp} {
        column_no++;
    }

. {
        column_no++;
        fprintf(stderr, "error: lexer found illegal character '%c' (0%o)"
            " at line %d, column %d\n", yytext[0], yytext[0],
            line_no, column_no);
        exit(EXIT_FAILURE);
    }

%%

