From 7aae14e9b83242c2778e57c069fb8f299b8172f3 Mon Sep 17 00:00:00 2001 From: Marius Nita Date: Mon, 14 Apr 2003 06:04:49 +0000 Subject: [PATCH] beginning of obcl. the parser works with semicolons after statements for now, there is much left to change and do. --- obcl/Makefile | 23 ++++++++ obcl/foo.conf | 21 ++++++++ obcl/lex.l | 86 +++++++++++++++++++++++++++++ obcl/main.c | 8 +++ obcl/obcl.c | 57 ++++++++++++++++++++ obcl/obcl.h | 38 +++++++++++++ obcl/parse.y | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 379 insertions(+) create mode 100644 obcl/Makefile create mode 100644 obcl/foo.conf create mode 100644 obcl/lex.l create mode 100644 obcl/main.c create mode 100644 obcl/obcl.h create mode 100644 obcl/parse.y diff --git a/obcl/Makefile b/obcl/Makefile new file mode 100644 index 00000000..03c3a5dc --- /dev/null +++ b/obcl/Makefile @@ -0,0 +1,23 @@ +CFLAGS=-ansi -pedantic -Wall `pkg-config --cflags glib-2.0` +LIBS=`pkg-config --libs glib-2.0` -ll + +targets = cltest + +sources = obcl.c main.c parse.c lex.c +headers = obcl.h + +.PHONY: all clean + +all: $(targets) + +$(targets): $(sources:.c=.o) + $(CC) -o $@ $^ $(LIBS) + +parse.c: parse.y + $(YACC) -d -o$@ $^ + +lex.c: lex.l + $(LEX) -o$@ $^ + +clean: + $(RM) $(targets) *.o core *~ lex.c parse.c parse.h diff --git a/obcl/foo.conf b/obcl/foo.conf new file mode 100644 index 00000000..648bb01c --- /dev/null +++ b/obcl/foo.conf @@ -0,0 +1,21 @@ +include "meh.conf"; +include "bummy.conf"; + +section mouse { + mbind titlebar, frame { + event click; + button middle; + action lower; + } + + mbind frame { + event click; + button right; + action launch_nukes; + } +} + +section theme { + theme "merry"; + font "tahoma-12 bold"; +} diff --git a/obcl/lex.l b/obcl/lex.l new file mode 100644 index 00000000..33a3c61a --- /dev/null +++ b/obcl/lex.l @@ -0,0 +1,86 @@ +%{ +#include "obcl.h" +#include "parse.h" +%} + +%option yylineno + +DGT [0-9] +ID [a-zA-Z_][a-zA-Z_\.\-0-9]* + + + /* string bummy */ +%x str +%% + + char str_buf[1024]; + char *str_buf_ptr; + int str_char; + + /* begin a string */ +[\"\'] { + str_buf_ptr = str_buf; + str_char = yytext[0]; + BEGIN(str); + } + + /* end a string */ +[\"\'] { + if (yytext[0] == str_char) { + BEGIN(INITIAL); + *str_buf_ptr = '\0'; + yylval.string = g_strdup(str_buf); + return TOK_STRING; + } else { + *str_buf_ptr++ = yytext[0]; + } + } + + /* can't have newlines in strings */ +\n { + printf("Error: Unterminated string constant.\n"); + BEGIN(INITIAL); + } + + /* handle \" and \' */ +"\\"[\"\'] { + if (yytext[1] == str_char) + *str_buf_ptr++ = yytext[1]; + else { + *str_buf_ptr++ = yytext[0]; + *str_buf_ptr++ = yytext[1]; + } + } + + /* eat valid string contents */ +[^\\\n\'\"]+ { + char *yptr = yytext; + while (*yptr) { + *str_buf_ptr++ = *yptr++; + } + } + + /* numberz */ +{DGT}+ { + yylval.num = atof(yytext); + return TOK_NUM; + } + + /* real numbers */ +{DGT}+"."{DGT}* { + yylval.num = atof(yytext); + return TOK_NUM; + } + + /* identifiers -- names without spaces and other crap in them */ +{ID} { + yylval.string = g_strdup(yytext); + return TOK_ID; + } + + /* skip comments */ +"#".*\n ; + /* skip other whitespace */ +[ \n\t]+ ; +. { return yytext[0]; } +%% diff --git a/obcl/main.c b/obcl/main.c new file mode 100644 index 00000000..5fb83967 --- /dev/null +++ b/obcl/main.c @@ -0,0 +1,8 @@ +#include "obcl.h" + +int main() +{ + GList *lst = cl_parse("foo.conf"); + cl_print_tree(lst,0); + return 0; +} diff --git a/obcl/obcl.c b/obcl/obcl.c index e69de29b..b4d9aeee 100644 --- a/obcl/obcl.c +++ b/obcl/obcl.c @@ -0,0 +1,57 @@ +#include "obcl.h" + +void free_cl_tree(GList *tree) +{ + +} + +GList *cl_parse(gchar *file) +{ + FILE *fh = fopen(file, "r"); + if (fh) + return cl_parse_fh(fh); + else { + printf("can't open file %s\n", file); + return 0; + } +} + +void cl_print_tree(GList *tree, int depth) +{ + CLNode *tmp; + int tmpd = depth; + + for (; tree; tree = tree->next) { + tmp = (CLNode*)tree->data; + + while (tmpd-- > 0) + printf(" "); + tmpd = depth; + + switch(tmp->type) { + case CL_ID: + printf("--ID-- %s\n", tmp->u.str); + break; + case CL_STR: + printf("--STR-- %s\n", tmp->u.str); + break; + case CL_NUM: + printf("--NUM-- %.2f\n", tmp->u.num); + break; + case CL_LIST: + printf("--LIST-- %s\n", tmp->u.lb.id); + cl_print_tree(tmp->u.lb.list, depth+2); + break; + case CL_BLOCK: + printf("--BLOCK-- %s\n", tmp->u.lb.id); + cl_print_tree(tmp->u.lb.block, depth+2); + break; + case CL_LISTBLOCK: + printf("--LISTBLOCK-- %s\n", tmp->u.lb.id); + cl_print_tree(tmp->u.lb.list, depth+2); + printf("\n"); + cl_print_tree(tmp->u.lb.block, depth+2); + break; + } + } +} diff --git a/obcl/obcl.h b/obcl/obcl.h new file mode 100644 index 00000000..a940e89d --- /dev/null +++ b/obcl/obcl.h @@ -0,0 +1,38 @@ +#ifndef __obcl_h +#define __obcl_h + +#include +#include +#include + +typedef enum CLNodeType { + CL_ID, + CL_NUM, + CL_STR, + CL_LIST, + CL_BLOCK, + CL_LISTBLOCK +} CLNodeType; + +typedef struct CLNode { + CLNodeType type; + union { + struct { + gchar *id; + GList *list; + GList *block; + } lb; + double num; + gchar *str; + } u; + +} CLNode; + +void free_cl_tree(GList *tree); +GList *cl_parse(gchar *file); +GList *cl_parse_fh(FILE *file); +void cl_print_tree(GList *tree, int depth); + +GList *parse_file(FILE *fh); + +#endif /* __obcl_h */ diff --git a/obcl/parse.y b/obcl/parse.y new file mode 100644 index 00000000..40a07181 --- /dev/null +++ b/obcl/parse.y @@ -0,0 +1,146 @@ +%{ +#include "obcl.h" + +int yylex(void); +void yyerror(char *msg, ...); + +extern int yylineno; +extern char *yytext; +GList *config; /* this is what we parse into */ + +%} + +%union { + double num; + gchar *string; + CLNode *node; + GList *glist; +}; + +%token TOK_NUM +%token TOK_ID TOK_STRING +%token TOK_SEP + +%type config +%type stmts +%type stmt +%type list +%type block +%type value + +%expect 2 /* for now */ + +%% + +config: stmts + { + config = $$ = $1; + } + ; + +stmts: + { $$ = NULL; } + | stmt + { $$ = g_list_append(NULL, $1); } + | stmts stmt + { $$ = g_list_append($1, $2); } + ; + +stmt: TOK_ID list ';' + { + CLNode *s = g_new(CLNode,1); + s->type = CL_LIST; + s->u.lb.list = $2; + s->u.lb.id = $1; + $$ = s; + } + | TOK_ID list block + { + CLNode *s = g_new(CLNode,1); + s->type = CL_LISTBLOCK; + s->u.lb.list = $2; + s->u.lb.block = $3; + s->u.lb.id = $1; + $$ = s; + } + | TOK_ID block + { + CLNode *s = g_new(CLNode,1); + s->type = CL_BLOCK; + s->u.lb.block = $2; + s->u.lb.id = $1; + $$ = s; + } + ; + +list: value + { + $$ = g_list_append(NULL, $1); + } + | list ',' value + { + $$ = g_list_append($1, $3); + } + ; + +block: '{' stmts '}' + { + $$ = $2; + } + ; + +value: TOK_ID + { + CLNode *node = g_new(CLNode,1); + node->type = CL_ID; + node->u.str = $1; + $$ = node; + } + | TOK_STRING + { + CLNode *node = g_new(CLNode,1); + node->type = CL_STR; + node->u.str = $1; + $$ = node; + } + | TOK_NUM + { + CLNode *node = g_new(CLNode,1); + node->type = CL_NUM; + node->u.num = $1; + $$ = node; + } + ; + +%% + +int yywrap() +{ + return 1; +} + +/* void yyerror(const char *err) */ +/* { */ +/* fprintf(stderr, "Parse error on line %d, near '%s': %s\n", */ +/* yylineno, yytext, err); */ +/* } */ + +void yyerror(char *msg, ...) +{ + va_list args; + va_start(args,msg); + + fprintf(stderr, "Error on line %d, near '%s': ", yylineno, yytext); + vfprintf(stderr, msg, args); + fprintf(stderr,"\n"); + + va_end(args); +} + +GList *cl_parse_fh(FILE *fh) +{ + extern FILE *yyin; + yyin = fh; + yyparse(); + return config; +} -- 2.39.2