~crm/uni

b8350feec76cd459f94c1511783ceb2576ec84ed — Christos Margiolis 2 months ago 1d7fb22
almost
M lex_yacc_compilers/part3/Makefile => lex_yacc_compilers/part3/Makefile +1 -1
@@ 2,7 2,7 @@ all:
	bison -d syntax.y
	flex lex.l
	cc syntax.tab.c lex.yy.c -lm -o uniclips
	./uniclips input.txt
	./uniclips input.txt output.txt

clean:
	rm -f *.yy.c *.output *.tab.c *.tab.h uniclips *.core

M lex_yacc_compilers/part3/input.txt => lex_yacc_compilers/part3/input.txt +12 -31
@@ 1,31 1,12 @@
+1234
50
-115
3.14
-10.0
+0.0001
3.14e-10
0e0
static-facts
MoveUp
CUBES
sum-1
table
pacman
A-21-b
?x
?X
?3
?ad
?X1b23
?32AbC
?ABcd1234de
""
"Test"
"Hello world"
"Mark said, \"Boo!\""
; this is a comment
ignore                whitespace
#unknown ?2 ? ?hello ?world
deffacts defrule test
2 + 2
(printout "hello" "hello")
(bind ?var 1)
(bind ?var (+ 1 2))
(test (= 1 2))
(= 1 (+ 2 3))

(defrule move-up
	(+ 1 2)
	(- 1 (+ 1 (* 1 2)))
	(test (= 1 2))
	->
	(printout "hello"))

M lex_yacc_compilers/part3/lex.l => lex_yacc_compilers/part3/lex.l +16 -9
@@ 8,8 8,8 @@
 * Με βάση το μέρος Α2, υλοποιούμε τις κανονικές εκφράσεις και τις
 * αντιστοιχούμε στα κατάλληλα tokens.
 */
FUNC		deffacts|defrule|test|bind|read|printout|quit|"+"|"-"|"*"|"/"|"="|"e"
DELIM		[ \t]+
ARITH		"+"|"-"|"*"|"/"|"="
DELIM		[ \t\n]+
INT		0|[+-]?[1-9]+[0-9]*
FLOAT		[+-]?[0-9]+((\.[0-9]+)([eE][+-]?[0-9]*)?|([eE][+-]?[0-9]*)?)
STR		\"[^\"\\]*(?:\\.[^\"\\]*)*\"


@@ 22,17 22,24 @@ COMMENT		;.*
 * οποίο ανήκει
 */
%%
{FUNC}		{ yylval.sval = strdup(yytext); return FUNC; }
{INT}		{ yylval.dval = strtod(yytext, NULL); return INT; }
{FLOAT}		{ yylval.dval = strtod(yytext, NULL); return FLOAT; }
{STR}		{ yylval.sval = strdup(yytext); return STR; }
{DEFIN}		{ yylval.sval = strdup(yytext); return DEFIN; }
{VAR}		{ yylval.sval = strdup(yytext); return VAR; }
"deffacts"	{ return DEFFACTS; }
"defrule"	{ return DEFRULE; }
"bind"		{ return BIND; }
"read"		{ return READ; }
"printout"	{ return PRINT; }
"test"		{ return TEST; }
"="		{ return COMP; }
"("		{ return LPAR; }
")"		{ return RPAR; }
"->"		{ return ARROW; }
\n		{ return NEWLINE; }
{ARITH}		{ return ARITH; }
{INT}		{ return INT; }
{FLOAT}		{ return FLOAT;}
{STR}		{ return STR; }
{DEFIN}		{ return DEFIN; }
{VAR}		{ return VAR; }
{DELIM}		{ /* ignore whitespace */ }
{COMMENT}	{ /* skip comments */ }
"\n"		{ return NEWLINE; }
.		{ return UNKNOWN; }
%%

A lex_yacc_compilers/part3/output.txt => lex_yacc_compilers/part3/output.txt +6 -0
@@ 0,0 1,6 @@
input.txt: success

correct words: 0
correct expressions: 12
wrong words: 0
wrong expressions: 0

M lex_yacc_compilers/part3/syntax.y => lex_yacc_compilers/part3/syntax.y +97 -81
@@ 2,116 2,132 @@
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>

/* Silence warnings... */
extern int	yylex(void);
extern int	yyparse(void);

/* Input and output files. */
extern FILE	*yyin, *yyout;
extern char	*yytext;

double	func(char *);
double	calc(char *, double, double);
int	cw = 0;	/* correct words */
int	ce = 0;	/* correct expressions */
int	ww = 0;	/* wrong words */
int	we = 0;	/* wrong expressions */

void	yyerror(const char *);
%}

%union {
	double	dval;
	char	*sval;
}

%token <sval> FUNC STR DEFIN VAR
%token <dval> INT FLOAT
%token NEWLINE UNKNOWN LPAR RPAR ARROW

%type <dval> expr
/* Tokens declared from flex. */
%token DEFFACTS DEFRULE BIND READ PRINT TEST ARITH INT FLOAT COMP
%token STR DEFIN VAR LPAR RPAR ARROW NEWLINE UNKNOWN

%start prog

%%
/* Start here. */
prog:
	{ printf("> "); }
	| prog expr NEWLINE		{ printf("%f\n> ", $2); }
	| prog NEWLINE
	| prog expr
	;

expr:
	INT				{ $$ = $1; }
	| FLOAT				{ $$ = $1; }
	| LPAR FUNC RPAR		{ $$ = func($2); }
	| LPAR FUNC expr expr RPAR	{ $$ = calc($2, $3, $4); }
	| error				{ yyerror("error"); }
/*
 * Declare numbers. Variables only accept numerical values so add them here as
 * well.
 */
num:
	INT
	| FLOAT
	| VAR
	;
%%

double
func(char *op)
{
	double n;
	int rc;

	if (strcmp(op, "quit") == 0) {
		exit(0);
	} else if (strcmp(op, "read") == 0) {
		do {
			printf("read> ");
			rc = scanf("%lf", &n);
			(void)getchar();
		} while (rc != 1);
		return (n);
	}
/* Accept any number of strings (for use in printout) */
str:
	STR
	| str STR
	;

	yyerror("invalid expression");
	/* NOT REACHED */
	return (0);
}
/* (= (expr)) */
cmp:
	LPAR COMP expr expr RPAR
	;

double
calc(char *op, double arg1, double arg2)
{
	if (strcmp(op, "+") == 0)
		return (arg1 + arg2);
	else if (strcmp(op, "-") == 0)
		return (arg1 - arg2);
	else if (strcmp(op, "*") == 0)
		return (arg1 * arg2);
	else if (strcmp(op, "/") == 0) {
		if (arg2 == 0)
			yyerror("cannot divide by 0");
		return (arg1 / arg2);
	}
	else if (strcmp(op, "e") == 0)
		return (pow(arg1, arg2));
	else if (strcmp(op, "=") == 0)
		return (arg1 == arg2);
/* (test (= (expr))) */
test:
	LPAR TEST cmp RPAR
	;

	yyerror("invalid expression");
	/* NOT REACHED */
	return (0);
}
/* (prinout (str)...) */
print:
	LPAR PRINT str RPAR
	;

fact:
	expr
	| fact expr
	;

/* We match expressions here. */
expr:
	num						/* numbers */
	| cmp				{ ce++; }	/* comparisons */
	| test				{ ce++; }	/* test keyword */
	| print				{ ce++; }	/* (printout "str"...) */
	| LPAR READ RPAR		{ ce++; }	/* (read) */
	| LPAR ARITH expr expr RPAR	{ ce++; }	/* (arithmetic_op (expr)...) */
	| LPAR BIND VAR expr RPAR	{ ce++; }	/* (bind ?var (expr)) */
	| LPAR DEFFACTS DEFIN fact RPAR { ce++; }	/* (deffacts DEF facts...) */
	/* (defrule DEF
	 *	(facts)
	 *	...
	 *	(test)
	 *	->
	 *	(printout))
	 */
	| LPAR DEFRULE DEFIN fact test ARROW print RPAR { ce++; }
	| error				{ we++; if (ce > 0) ce--; }
	;
%%

/* Print errors. */
void
yyerror(const char *s)
{
	fprintf(stderr, "%s\n", s);
	exit(1);
}

int
main(int argc, char *argv[])
{
	/*if (argc < 2) {*/
		/*fprintf(stderr, "usage: %s input [output]\n", *argv);*/
		/*return (-1);*/
	/*}*/
	/*if ((yyin = fopen(argv[1], "r")) == NULL)*/
		/*err(1, "fopen(%s)", argv[1]);*/
	/*if (argc == 3 && (yyout = fopen(argv[2], "w")) == NULL)*/
		/*err(1, "fopen(%s)", argv[2]);*/

	if (yyparse() == 0)
		fprintf(stderr, "success\n");
	else
		fprintf(stderr, "failure\n");
	/* We need at least 1 input and 1 output file... */
	if (argc < 3) {
		fprintf(stderr, "usage: %s input... output\n", *argv);
		return (-1);
	}

	/* Open last file as output. */
	if ((yyout = fopen(argv[--argc], "w")) == NULL)
		err(1, "fopen(%s)", argv[argc]);

	/* Parse all input files in reverse order. */
	while (argc-- > 1) {
		if ((yyin = fopen(argv[argc], "r")) == NULL)
			err(1, "fopen(%s)", argv[argc]);
		/* Parse file */
		if (yyparse() == 0)
			fprintf(yyout, "%s: success\n", argv[argc]);
		else
			fprintf(yyout, "%s: failure\n", argv[argc]);
		fclose(yyin);
	}

	/* Print results. */
	fprintf(yyout, "\n");
	fprintf(yyout, "correct words: %d\n", cw);
	fprintf(yyout, "correct expressions: %d\n", ce);
	fprintf(yyout, "wrong words: %d\n", ww);
	fprintf(yyout, "wrong expressions: %d\n", we);

	fclose(yyout);

	return (0);
}