~ecs/hq

ref: 05e89aaebceb0242aaa43c75277e0b2cc05a11a0 hq/parse.y -rw-r--r-- 1.7 KiB
05e89aaeEmber Sawady Improve multi error handling 6 months ago
                                                                                
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
%{
package main

import (
	"fmt"
	"io"
	"os"
)

type Pipe struct {
	First  Expr
	Second Expr
}

type Multi struct {
	Cmds []Expr
	Out  Expr
}

type Expr struct {
	Pipe  *Pipe
	Cmd   []string
	Multi *Multi
}

var Exp Expr
%}

%union {
	expr   Expr
	exprs  []Expr
	filter []string
	rune   rune
	str    string
}

%token <rune> '|'
%token <rune> '>'
%token <rune> '('
%token <rune> ')'
%token <rune> '&'
%token <str> STRING

%type <expr> expr
%type <expr> filter
%type <expr> multi
%type <exprs> join

%%

top:
	expr {
		Exp = $1
	}

expr:
	filter
	| multi
	| expr '|' filter {
		$$ = Expr{
			Pipe: &Pipe{
				First:  $1,
				Second: $3,
			},
		}
	}
	| expr '|' multi {
		$$ = Expr{
			Pipe: &Pipe{
				First:  $1,
				Second: $3,
			},
		}
	}

multi:
	join '>' filter {
		$$ = Expr{
			Multi: &Multi{
				Cmds: $1,
				Out: $3,
			},
		}
	}

join:
	filter {
		$$ = []Expr{$1}
	}
	| join '&' filter {
		$$ = append($1, $3)
	}

filter:
	STRING {
		$$ = Expr{Cmd: []string{$1}}
	}
	| filter STRING {
		$$.Cmd = append($1.Cmd, $2)
	}
	| '(' expr ')' {
		$$ = $2
	}
%%

type yyLex struct {
	Toks  []string
	index int
	Err   io.Writer
}

func (x *yyLex) Lex(yylval *yySymType) int {
	if len(x.Toks) == 0 {
		return 0
	}

	if len(x.Toks[0]) == 0 {
		goto str
	} else if len(x.Toks[0]) <= x.index {
		x.Toks = x.Toks[1:]
		x.index = 0
		return x.Lex(yylval)
	}

	switch x.Toks[0][x.index] {
	case '|':
		fallthrough
	case '>':
		fallthrough
	case '(':
		fallthrough
	case ')':
		fallthrough
	case '&':
		ret := x.Toks[0][x.index]
		x.index++
		return int(ret)
	}
str:
	yylval.str = x.Toks[0][x.index:]
	x.Toks = x.Toks[1:]
	return STRING
}

func (x *yyLex) Error(s string) {
	fmt.Fprintln(x.Err, "parse: " + s)
	os.Exit(1)
}