blob: de1a2a7d2adc80a28e44cc591854304d4b00d171 [file] [log] [blame]
<appendix id="app:rpn">
<title>Complete code of RPN example</title>
<sect1><title>main.k</title>
<programlisting>
<![CDATA[
%{
#include <iostream>
#include "k.h"
#include "rk.h"
#include "unpk.h"
#include "csgiok.h"
int yyparse( );
aritherm root_term;
%}
%{ KC_TYPES_HEADER
extern aritherm root_term;
%}
%option yystype
void
printer( const char *s, uview v ) {
std::cout << s;
}
int
main( int argc, char** argv ) {
std::cout << "rpn calculator" << std::endl;
yyparse( );
aritherm canon_term = root_term -> rewrite( canonify );
aritherm simpl_term = canon_term -> rewrite( simplify );
std::cout << "simplified term in infix notation" << endl;
simpl_term -> unparse( printer, infix );
std::cout << std::endl;
}
]]>
</programlisting>
</sect1>
<sect1><title>abstr.k</title>
<programlisting>
<![CDATA[
aritherm: SimpleTerm ( simpleterm )
| Plus ( aritherm aritherm )
| Minus ( aritherm aritherm )
| Mul ( aritherm aritherm )
| Div ( aritherm aritherm );
simpleterm: Number ( integer )
| Ident ( casestring );
]]>
</programlisting>
</sect1>
<sect1><title>rpn.k</title>
<programlisting>
<![CDATA[
%rview simplify, canonify;
// 1 + 2 -> 3
Plus(SimpleTerm(Number(a)),SimpleTerm(Number(b)))->
<simplify:SimpleTerm(Number(plus(a,b)))>;
// 1 + 3 + b -> 4 + b
Plus(SimpleTerm(Number(a)),Plus(SimpleTerm(Number(b)),rem))->
<simplify:Plus(SimpleTerm(Number(plus(a,b))),rem)>;
// 1 + 3 - b -> 4 - b
Plus(SimpleTerm(Number(a)),Minus(SimpleTerm(Number(b)),rem))->
<simplify:Minus(SimpleTerm(Number(plus(a,b))),rem)>;
// 6 - 2 -> 4
Minus(SimpleTerm(Number(a)),SimpleTerm(Number(b)))->
<simplify:SimpleTerm(Number(minus(a,b)))>;
// 6 - 4 - b -> 2 - b
Minus(SimpleTerm(Number(a)),Minus(SimpleTerm(Number(b)),rem))->
<simplify:Minus(SimpleTerm(Number(minus(a,b))),rem)>;
// 6 - 4 + b -> 2 + b
Minus(SimpleTerm(Number(a)),Plus(SimpleTerm(Number(b)),rem))->
<simplify:Plus(SimpleTerm(Number(minus(a,b))),rem)>;
// 3 * 2 * b -> 6 * b
Mul(SimpleTerm(Number(a)),Mul(SimpleTerm(Number(b)),rem))->
<simplify:Mul(SimpleTerm(Number(mul(a,b))),rem)>;
// 3 * 2 / b -> 6 / b
Mul(SimpleTerm(Number(a)),Div(SimpleTerm(Number(b)),rem))->
<simplify:Div(SimpleTerm(Number(mul(a,b))),rem)>;
// 3 * 2 -> 6
Mul(SimpleTerm(Number(a)),SimpleTerm(Number(b)))->
<simplify:SimpleTerm(Number(mul(a,b)))>;
// 6 / 2 -> 3
Div(SimpleTerm(Number(a)),SimpleTerm(Number(b)))->
<simplify:SimpleTerm(Number(div(a,b)))>;
// 6 / 2 / b -> 3 / b
Div(SimpleTerm(Number(a)),Div(SimpleTerm(Number(b)),rem))->
<simplify:Div(SimpleTerm(Number(div(a,b))),rem)>;
// 6 / 2 * b -> 3 * b
Div(SimpleTerm(Number(a)),Mul(SimpleTerm(Number(b)),rem))->
<simplify:Mul(SimpleTerm(Number(div(a,b))),rem)>;
// a + a -> 2 * a
Plus(b=SimpleTerm(Ident(a)),SimpleTerm(Ident(a)))->
<simplify:Mul(SimpleTerm(Number(mkinteger(2))),b)>;
// a - a -> 0
Minus(SimpleTerm(Ident(a)),SimpleTerm(Ident(a)))->
<simplify: SimpleTerm(Number(mkinteger(0)))>;
// a / a -> 1
Div(SimpleTerm(Ident(a)),SimpleTerm(Ident(a)))->
<simplify: SimpleTerm(Number(mkinteger(1)))>;
// 6 * a + a -> 7 * a
Plus(Mul(SimpleTerm(Number(a)),SimpleTerm(Ident(b))),c=SimpleTerm(Ident(b)))->
<simplify: Mul(SimpleTerm(Number(plus(a,mkinteger(1)))),c)>;
// 6 * a -a -> 5 * a
Minus(Mul(SimpleTerm(Number(a)),SimpleTerm(Ident(b))),c=SimpleTerm(Ident(b)))->
<simplify: Mul(SimpleTerm(Number(minus(a,mkinteger(1)))),c)>;
// 6 * a + 3 * a -> 9 * a
Plus(Mul(SimpleTerm(Number(a)),SimpleTerm(Ident(b))),
Mul(SimpleTerm(Number(d)),c=SimpleTerm(Ident(b))))->
<simplify: Mul(SimpleTerm(Number(plus(a,d))),c)>;
// 6 * a - 2 * a -> 4 * a
Minus(Mul(SimpleTerm(Number(a)),SimpleTerm(Ident(b))),
Mul(SimpleTerm(Number(d)),c=SimpleTerm(Ident(b))))->
<simplify: Mul(SimpleTerm(Number(minus(a,d))),c)>;
// a + (a + 2 * b) -> 2 * a + 2 * b
Plus(b=SimpleTerm(Ident(a)),Plus(SimpleTerm(Ident(a)),rem))->
<simplify: Plus(Mul(SimpleTerm(Number(mkinteger(2))),b),rem)>;
// a - (a +- 2 * b) -> 2 * b
Minus(SimpleTerm(Ident(a)),Plus(SimpleTerm(Ident(a)),rem)),
Minus(SimpleTerm(Ident(a)),Minus(SimpleTerm(Ident(a)),rem))->
<simplify: rem>;
// a + (a - 2 * b) -> 2 * a - 2 * b
Plus(b=SimpleTerm(Ident(a)),Minus(SimpleTerm(Ident(a)),rem))->
<simplify: Minus(Mul(SimpleTerm(Number(mkinteger(2))),b),rem)>;
// (a + b) + c -> a + (b + c)
Plus( Plus(a, b), c)
-> < canonify: Plus(a, Plus(b, c))>;
// (a - b) + c -> c + (a - b)
Plus( Minus(a, b), c)
-> < canonify: Plus(c, Minus(a, b))>;
// (a + b) - c -> a + (b - c)
Minus( Plus(a, b), c)
-> < canonify: Plus(a, Minus(b, c))>;
// (a * b) * c -> a * (b * c)
Mul( Mul(a, b), c)
-> < canonify: Mul(a, Mul(b, c))>;
// a + 5 -> 5 + a
Plus( a=SimpleTerm(Ident(*)), b=SimpleTerm(Number(*)) )
-> < canonify: Plus(b, a)>;
// a * 5 -> 5 * a
Mul( a=SimpleTerm(Ident(*)), b=SimpleTerm(Number(*)) )
-> < canonify: Mul(b, a)>;
// a + (6 + b) -> 6 + (a + b)
Plus( a=SimpleTerm(Ident(*)), Plus(b=SimpleTerm(Number(*)), rest) )
-> < canonify: Plus(b, Plus(a,rest))>;
// a * (6 * b) -> 6 * (a * b)
Mul( a=SimpleTerm(Ident(*)), Mul(b=SimpleTerm(Number(*)), rest) )
-> < canonify: Mul(b, Mul(a,rest))>;
%{ KC_REWRITE
inline integer plus(integer a, integer b){
return mkinteger(a->value+b->value);
}
inline integer minus(integer a, integer b){
return mkinteger(a->value-b->value);
}
inline integer mul(integer a, integer b){
return mkinteger(a->value*b->value);
}
inline integer div(integer a, integer b){
return mkinteger(b->value==0 ? 0 : a->value / b->value);
}
%}
%uview infix,postfix;
Plus(a,b)->[infix: "(" a "+" b ")"];
Minus(a,b)->[infix: "(" a "-" b ")"];
Mul(a,b)->[infix: "(" a "*" b ")"];
Div(a,b)->[infix: "(" a "/" b ")"];
]]>
</programlisting>
</sect1>
<sect1><title>lexic.l</title>
<programlisting>
<![CDATA[
%{
#include <iostream>
#include "k.h"
#include "yystype.h"
#include "syntax.h"
#include "rpn.h"
%}
%option noyywrap
%%
-?[0-9]+ { yylval.yt_integer = mkinteger(atoi(yytext)); return NUMBER;}
[a-z]+ { yylval.yt_casestring = mkcasestring(yytext); return IDENT; }
[+*-/] { return yytext[0]; }
[\t ]+ { /*empty*/ }
\n { return EOF; }
. { std::cerr << "Unkown character: " << yytext[0] << std::endl; }
%%
extern void yyerror(const char *s) {
std::cerr << "Syntax error: " << s << std::endl;
}
]]>
</programlisting>
</sect1>
<sect1><title>syntax.y</title>
<programlisting>
<![CDATA[
%{
#include "k.h"
#include "yystype.h"
extern void yyerror(const char*);
extern int yylex();
%}
%token <yt_integer> NUMBER
%token <yt_casestring> IDENT
%token NEWLINE
%type <yt_aritherm> aritherm
%type <yt_simpleterm> simpleterm
%%
aritherm:
simpleterm
{ root_term = $$ = SimpleTerm($1); }
| aritherm aritherm '+'
{ root_term = $$ = Plus($1,$2); }
| aritherm aritherm '*'
{ root_term = $$ = Mul($1,$2); }
| aritherm aritherm '-'
{ root_term = $$ = Minus($1,$2); }
| aritherm aritherm '/'
{ root_term = $$ = Div($1,$2); }
;
simpleterm:
NUMBER
{ $$ = Number($1); }
| IDENT
{ $$ = Ident($1); }
;
]]>
</programlisting>
</sect1>
<sect1 id="app:make"><title>Makefile</title>
<programlisting>
<![CDATA[
# Reverse Polish Notation, Makefile
# c 2001, Michael Piefel <piefel@informatik.hu-berlin.de>
.PRECIOUS: lexic.c y.output
# Tools
SHELL = /bin/sh
YACC = bison
LEX = flex
CC = ${CXX}
KC = kc++
#Flages
YFLAGS = -d -y
LFLAGS = -t
CXXFLAGS = -g -Wall -Wno-unused -DYYDEBUG -DYYERROR_VERBOSE
CFLAGS = ${CXXFLAGS}
# Sources
KFILES = rpn.k main.k abstr.k
YFILES = syntax.y
LFILES = lexic.l
# Goals
PARSER = rpn-parser
# Help files
KC_TIME = .kc_time_stamp
KC_OGEN = k.o csgiok.o unpk.o rk.o
KC_OSRC = $(KFILES:.k=.o)
OBJS = $(KC_OGEN) $(KC_OSRC) $(YFILES:.y=.o) $(LFILES:.l=.o) $(CFILES:.cc=.o)
# default rule
$(PARSER)::
# include or make autodependencies
ifeq (.depend,$(wildcard .depend))
include .depend
else
$(PARSER):: depend
endif
# Rules
$(KC_TIME): $(KFILES)
$(KC) $(KFILES)
touch $(KC_TIME)
$(PARSER):: $(KC_TIME) $(OBJS)
$(CXX) $(CFLAGS) $(OBJS) ${LIBS} -o $@
syntax.h : y.tab.h
-cmp -s syntax.h y.tab.h || cp y.tab.h syntax.h
y.tab.h : syntax.c
depend dep:
@echo Make dependencies first
$(MAKE) $(KC_TIME)
$(MAKE) $(YFILES:.y=.c)
$(MAKE) $(LFILES:.l=.c)
$(MAKE) syntax.h
$(CC) -M *.cc > .depend
clean:
-rm -f $(OBJS) core *~ *.bak $(KFILES:.k=.cc) $(KC_OGEN:.o=.cc) $(KC_TIME) .kc* \
$(YFILES:.y=.c) $(LFILES:.l=.c) $(KC_OGEN:.o=.h) $(KFILES:.k=.h) out.* \
y.tab.h syntax.h syntax.output syntax.tab.c yystype.h
]]>
</programlisting>
</sect1>
</appendix>