add helper functions for manipulating the focus_order list.
[mikachu/openbox.git] / openbox / parse.y
1 %{
2 #include <glib.h>
3 #ifdef HAVE_STDIO_H
4 #  include <stdio.h>
5 #endif
6
7 %}
8
9 %union ParseTokenData {
10     float real;
11     int integer;
12     char *string;
13     char *identifier;
14     gboolean bool;
15     char character;
16     GList *list;
17 }
18
19 %{
20 #define NO_TAB_H
21 #include "parse.h"
22 #undef NO_TAB_H
23
24 extern int yylex();
25 extern int yyparse();
26 void yyerror(char *err);
27
28 extern int lineno;
29 extern FILE *yyin;
30
31 static char *path;
32 static ParseToken t;
33
34 /* in parse.c */
35 void parse_token(ParseToken *token);
36 void parse_assign(char *name, ParseToken *token);
37 void parse_set_section(char *section);
38 %}
39
40 %token <real> REAL
41 %token <integer> INTEGER
42 %token <string> STRING
43 %token <identifier> IDENTIFIER
44 %token <bool> BOOL
45 %token <character> '('
46 %token <character> ')'
47 %token <character> '{'
48 %token <character> '}'
49 %token <character> '='
50 %token <character> ','
51 %token <character> '\n'
52 %token INVALID
53
54 %type <list> list
55 %type <list> listtokens
56
57 %%
58
59 sections:
60   | sections '[' IDENTIFIER ']' { parse_set_section($3); } '\n'
61     { ++lineno; } lines
62   ;
63
64 lines:
65   | lines tokens { t.type='\n'; t.data.character='\n'; parse_token(&t); } '\n'
66     { ++lineno; }
67   | lines IDENTIFIER '=' listtoken { parse_assign($2, &t); } '\n'
68     { ++lineno; }
69   ;
70
71 tokens:
72     tokens token { parse_token(&t); }
73   | token        { parse_token(&t); }
74   ;
75
76 token:
77     REAL       { t.type = TOKEN_REAL; t.data.real = $1; }
78   | INTEGER    { t.type = TOKEN_INTEGER; t.data.integer = $1; }
79   | STRING     { t.type = TOKEN_STRING; t.data.string = $1; }
80   | IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
81   | BOOL       { t.type = TOKEN_BOOL; t.data.bool = $1; }
82   | list       { t.type = TOKEN_LIST; t.data.list = $1; }
83   | '{'        { t.type = $1; t.data.character = $1; }
84   | '}'        { t.type = $1; t.data.character = $1; }
85   | ','        { t.type = $1; t.data.character = $1; }
86   ;
87
88 list:
89     '(' listtokens ')' { $$ = $2; }
90   ;
91
92 listtokens:
93     listtokens listtoken { ParseToken *nt = g_new(ParseToken, 1);
94                            nt->type = t.type;
95                            nt->data = t.data;
96                            $$ = g_list_append($1, nt);
97                          }
98   | listtoken            { ParseToken *nt = g_new(ParseToken, 1);
99                            nt->type = t.type;
100                            nt->data = t.data;
101                            $$ = g_list_append(NULL, nt);
102                          }
103   ;
104
105 listtoken:
106     REAL       { t.type = TOKEN_REAL; t.data.real = $1; }
107   | INTEGER    { t.type = TOKEN_INTEGER; t.data.integer = $1; }
108   | STRING     { t.type = TOKEN_STRING; t.data.string = $1; }
109   | IDENTIFIER { t.type = TOKEN_IDENTIFIER; t.data.identifier = $1; }
110   | BOOL       { t.type = TOKEN_BOOL; t.data.bool = $1; }
111   | list       { t.type = TOKEN_LIST; t.data.list = $1; }
112   | '{'        { t.type = $1; t.data.character = $1; }
113   | '}'        { t.type = $1; t.data.character = $1; }
114   | ','        { t.type = $1; t.data.character = $1; }
115   ;
116
117
118 %%
119
120 int lineno;
121
122 void yyerror(char *err) {
123     g_message("%s:%d: %s", path, lineno, err);
124 }
125
126 void parse_rc()
127 {
128     /* try the user's rc */
129     path = g_build_filename(g_get_home_dir(), ".openbox", "rc3", NULL);
130     if ((yyin = fopen(path, "r")) == NULL) {
131         g_free(path);
132         /* try the system wide rc */
133         path = g_build_filename(RCDIR, "rc3", NULL);
134         if ((yyin = fopen(path, "r")) == NULL) {
135             g_warning("No rc2 file found!");
136             g_free(path);
137             return;
138         }
139     }
140
141     lineno = 1;
142
143     yyparse();
144
145     g_free(path);
146 }