-
Notifications
You must be signed in to change notification settings - Fork 0
/
parser.y
119 lines (99 loc) · 3.06 KB
/
parser.y
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
extern int yylex(void);
void yyerror(char *s);
%}
%code requires {
#include <stdbool.h>
typedef enum {
CMD_SIMPLE,
CMD_PIPE,
} cmd_type;
typedef struct {
char name[5000];
char in_redir[5000];
char out_redir[5000];
bool bg;
} cmd_simple;
typedef struct {
struct command *left;
struct command *right;
} cmd_pipe;
typedef struct command {
cmd_type type;
union {
cmd_simple simple;
cmd_pipe pipe;
};
} command;
extern bool empty_line;
extern command final_cmd;
}
%union {
bool bool_type;
char *string;
char string_buffer[5000];
struct {char *in; char *out;} redir_pair;
cmd_simple cmd_simple;
command command;
}
%type <command> pipeline
%type <cmd_simple> simple
%type <string_buffer> command
%type <redir_pair> redir
%type <string> input_redir
%type <string> output_redir
%type <bool_type> back_ground
%start cmd_line
%token PIPE INPUT_REDIR OUTPUT_REDIR STRING NL BACKGROUND
%%
cmd_line : /* empty */ { empty_line = true; }
| pipeline back_ground {
final_cmd = $1;
if (final_cmd.type == CMD_SIMPLE) {
final_cmd.simple.bg = $2;
} else {
final_cmd.pipe.right->simple.bg = $2;
}
empty_line = false;
}
;
back_ground : BACKGROUND { $$ = true; }
| /* empty */ { $$ = false; }
;
simple : command redir {
strcpy($$.name, $1);
strcpy($$.in_redir, $2.in);
strcpy($$.out_redir, $2.out);
}
;
command : command STRING { strcat($$, " "); strcat($$, yylval.string); }
| STRING { strcpy($$, yylval.string); }
;
redir : input_redir output_redir { $$.in = $1; $$.out = $2; }
;
input_redir : INPUT_REDIR STRING { $$ = yylval.string; }
| /* empty */ { $$ = ""; }
;
output_redir : OUTPUT_REDIR STRING { $$ = yylval.string; }
| /* empty */ { $$ = ""; }
;
pipeline : simple { $$.type = CMD_SIMPLE; $$.simple = $1; }
| pipeline PIPE simple {
$$.type = CMD_PIPE;
command *left = malloc(sizeof(command));
*left = $1;
$$.pipe.left = left;
command *right = malloc(sizeof(command));
right->type = CMD_SIMPLE;
right->simple = $3;
$$.pipe.right = right;
}
;
%%
void yyerror(char *s)
{
fprintf(stderr, "parsing error: %s\n", s);
}