%{
#include <stdio.h>
+#include <string.h>
+#include <pcre.h>
+
+#include "lex.h"
+
+#define OVECCOUNT 3
int yylex (void);
void yyerror (char const *);
+int regex_cmp(char* s, char* r);
+struct tree* tree_malloc(int type);
+void print_tree(struct tree* t, int ind);
+
+struct tree {
+ enum {
+ ST_IF,
+ ST_COND,
+ ST_BLOCK,
+ ST_ASS,
+ ST_LEAF,
+ ST_EMPTY
+ } st; /* subtree type */
+ union {
+ struct {
+ struct tree* c; /* condition */
+ struct tree* i; /* if */
+ struct tree* e; /* else */
+ } tif;
+
+ struct {
+ int op;
+ struct tree* left;
+ struct tree* right;
+ } cond; /* binary operator */
+
+ struct {
+ struct tree* head;
+ struct tree* tail;
+ } block;
+
+ struct {
+ struct tree* left;
+ struct tree* right;
+ } ass;
+
+ struct {
+ enum {
+ L_VAR,
+ L_CONST,
+ L_NUM
+ } type;
+ union {
+ char* s;
+ int n;
+ } value;
+ } leaf;
+
+ } pt;
+};
+
+struct tree* input_tree;
+
%}
-%token CONST
-%left EQ
-%left '|' '&' '^'
-%left '!'
+%union {
+ int n;
+ char* str;
+ struct tree* tr;
+}
+
+%token <str> CONST
+%token <n> NUM
+%token <str> VAR
+%token KW_PIPE KW_MAIL KW_COPY
+%token '(' ')' '{' '}' ';'
+%nonassoc KW_IF
+%nonassoc KW_ELSE
+%left ARROW
+%left <n> EQ NEQ GE LE '<' '>' RE NRE
+%left '='
+%left '.'
+%left '+' '-'
+%left '*' '/'
+%left <n> '|'
+%left <n> '^'
+%left <n> '&'
+%left <n> '!'
+%type <tr> input
+%type <tr> command
+%type <tr> next
+%type <tr> ass
+%type <tr> ass_right
+%type <tr> cif
+%type <tr> cond
+%type <n> rop
%%
-input: /* empty */
- | input line
+input: /* empty */ { $$ = input_tree = NULL; }
+ | command input { $$ = tree_malloc(ST_BLOCK);
+ $$->pt.block.head = $1;
+ $$->pt.block.tail = $2;
+
+ input_tree = $$;
+ }
+;
+
+command: ';' { $$ = tree_malloc(ST_EMPTY); }
+ | '{' command next '}' {
+ $$ = tree_malloc(ST_BLOCK);
+ $$->pt.block.head = $2;
+ $$->pt.block.tail = $3;
+ }
+ | '{' '}' { $$ = tree_malloc(ST_EMPTY); }
+ | cif
+ | ass ';' { $$ = $1}
+
+
+;
+
+next: /* empty */ {$$ = NULL}
+ | command
+
+
;
-line: '\n'
- | boo '\n' { printf("%s\n",$1?"true":"false"); }
- | boo EQ boo { $$ = $1 == $2 }
- | boo '|' boo { $$ = $1 || $2 }
- | boo '&' boo { $$ = $1 && $2 }
- | boo '^' boo { $$ = ($1 || $2) && !($1 && $2) }
- | '!' boo { $$ = ! $1 }
+cif: KW_IF cond command KW_ELSE command {
+ $$ = tree_malloc(ST_IF);
+ $$->pt.tif.c = $2;
+ $$->pt.tif.i = $3;
+ $$->pt.tif.e = $5;
+ }
+ | KW_IF cond command {
+ $$ = tree_malloc(ST_IF);
+ $$->pt.tif.c = $2;
+ $$->pt.tif.i = $3;
+ $$->pt.tif.e = NULL;
+ }
;
-boo:
+cond: '!' cond {
+ $$ = tree_malloc(ST_COND);
+ $$->pt.cond.left = $2;
+ $$->pt.cond.right = NULL;
+ $$->pt.cond.op = $1;
+
+ }
+ | cond '|' cond {
+ $$ = tree_malloc(ST_COND);
+ $$->pt.cond.left = $1;
+ $$->pt.cond.right = $3;
+ $$->pt.cond.op = $2;
+
+ }
+ | cond '&' cond {
+ $$ = tree_malloc(ST_COND);
+ $$->pt.cond.left = $1;
+ $$->pt.cond.right = $3;
+ $$->pt.cond.op = $2;
+
+ }
+ | cond '^' cond {
+ $$ = tree_malloc(ST_COND);
+ $$->pt.cond.left = $1;
+ $$->pt.cond.right = $3;
+ $$->pt.cond.op = $2;
+ }
+ | '(' cond ')' { $$ = $2; }
+ | ass_right rop ass_right {
+ $$ = tree_malloc(ST_COND);
+ $$->pt.cond.left = $1;
+ $$->pt.cond.right = $3;
+ $$->pt.cond.op = $2;
+ }
;
-%%
-#include <ctype.h>
-#include <string.h>
+rop: '>'
+ | '<'
+ | EQ
+ | NEQ
+ | LE
+ | GE
+ | RE
+ | NRE
+;
-#define BUFSIZE 4096
+ass:
+ VAR '=' ass_right {
+ $$ = tree_malloc(ST_ASS);
-int
-yylex(void)
+ $$->pt.ass.left = tree_malloc(ST_LEAF);
+ $$->pt.ass.left->pt.leaf.type = L_VAR;
+ $$->pt.ass.left->pt.leaf.value.s = $1;
+
+ $$->pt.ass.right = $3;
+ }
+;
+
+ass_right: NUM {
+ $$ = tree_malloc(ST_LEAF);
+ $$->pt.leaf.type = L_NUM;
+ $$->pt.leaf.value.n = $1;
+ }
+ | VAR {
+ $$ = tree_malloc(ST_LEAF);
+ $$->pt.leaf.type = L_VAR;
+ $$->pt.leaf.value.s = $1;
+ }
+ | CONST {
+ $$ = tree_malloc(ST_LEAF);
+ $$->pt.leaf.type = L_CONST;
+ $$->pt.leaf.value.s = $1;
+ }
+
+;
+
+%%
+
+struct tree*
+tree_malloc(int type)
{
+ struct tree* temp;
+ temp = xmalloc(sizeof (struct tree));
+ temp->st=type;
- int c, last;
- char temp[BUFSIZE];
- char* p=temp;
-
- while ((c = getchar ()) == ' ' || c == '\t');
-
- if (c == '"'){
- last = '"';
- while ((c = getchar()) != '"' || last == '\\'){
- *p = c;
- last = c;
- p++;
- if (p-temp >= BUFSIZE-1)
- break;
- }
- *p = '\0';
-
- strcpy(&yylval,temp);
- return CONST;
- }
+ return temp;
+}
- if (c == '='){
- if ((c = getchar ()) == '=')
- return EQ;
- }
+int
+regex_cmp(char* s, char* r)
+{
+ pcre *brum;
+ int erroroffset;
+ const char* error;
+ int ovector[OVECCOUNT];
- if (c == EOF)
- return 0;
+ brum = pcre_compile(r,0,&error,&erroroffset,NULL);
+ if (!brum)
+ return -1;
- return c;
+ int res = pcre_exec(brum,NULL,s,strlen(s),0,0,ovector,OVECCOUNT);
+ pcre_free(brum);
+
+ return res;
}
void
fprintf (stderr, "%s\n", s);
}
+void
+print_ind(int num, char c)
+{
+ int i;
+
+ for (i = 0; i < num; i++){
+ putchar(c);
+ }
+}
+
+void
+print_tree(struct tree* t, int ind)
+{
+ if (!t)
+ return;
+
+ switch (t->st){
+ case ST_IF:
+ print_ind(ind,' ');
+ puts("if");
+ print_tree(t->pt.tif.c,ind+1);
+ print_ind(ind,' ');
+ puts("then");
+ print_tree(t->pt.tif.i,ind+1);
+ print_ind(ind,' ');
+ puts("else");
+ print_tree(t->pt.tif.e,ind+1);
+ break;
+ case ST_COND:
+#define UPPER(a) ((a) >> 8)
+#define LOWER(a) ((a) & 0xFF)
+ print_tree(t->pt.cond.left, ind+1);
+ print_ind(ind,' ');
+
+ if (UPPER(t->pt.cond.op) > 0)
+ putchar(UPPER(t->pt.cond.op));
+ putchar(LOWER(t->pt.cond.op));
+ putchar('\n');
+ print_tree(t->pt.cond.right, ind+1);
+ break;
+ case ST_BLOCK:
+ print_tree(t->pt.block.head,ind);
+ print_tree(t->pt.block.tail,ind);
+ break;
+ case ST_ASS:
+ print_tree(t->pt.ass.left, ind+1);
+ print_ind(ind,' ');
+ puts("=");
+ print_tree(t->pt.ass.right, ind+1);
+ break;
+ case ST_LEAF:
+ print_ind(ind, ' ');
+ switch (t->pt.leaf.type){
+ case L_VAR:
+ putchar('$');
+ case L_CONST:
+ puts(t->pt.leaf.value.s);
+ break;
+ case L_NUM:
+ printf("%d\n",t->pt.leaf.value.n);
+ break;
+ }
+ break;
+ case ST_EMPTY:
+ break;
+
+
+ }
+}
+
+
int
main(void)
{
- return yyparse ();
+ yydebug=1;
+ yyparse ();
+
+ print_tree(input_tree,0);
+ return 0;
}