| CODE |
$ tar xvzf calc.tar.gz tar: Dit ziet er niet uit als een tar-archief tar: Overslaan tot volgende kop tar: Afsluitcode uitgesteld na eerdere fouten |
| CODE |
| #if defined (__GNUC_MINOR__) && 2093 <= (__GNUC__ * 1000 + __GNUC_MINOR__) __attribute__ ((__unused__)) #endif |
| CODE |
| g++ main.cpp calc.tab.c lex.yy.c -o calc calc.tab.c: In function `int yyparse()': calc.tab.c:1164: error: expected primary-expression before "__attribute__" calc.tab.c:1164: error: expected `;' before "__attribute__" make: *** [calc] Error 1 |
| QUOTE (Consumed @ Jun 8 2005, 08:34 PM) | ||
Thanks alot myork. :) One prob I'd like to point out though: Before I can build it properly I have to edit calc.tab.c and comment out
|
| CODE |
calc.l: Defines the tokens. calc.y: Defines the syntax main.cpp: The main() and some utilities. calc.h: Some headers. Makefile: |
| CODE |
| %{ #include "calc.h" #include "calc.tab.h" #include <sstream> #include <string> #include <iomanip> #include <iostream> static double decodeNumber(int radex,const char* begin,int length); %} BinDigit [0-1] OctDigit [0-7] DecDigit [0-9] HexDigit [0-9A-Fa-f] BinNumber 0b{BinDigit}+ OctNumber 0{OctDigit}+ DecNumber [1-9]{DecDigit}* HexNumber 0x{HexDigit}+ FloatNumber {DecNumber}?"."{DecNumber} WhiteSpace [ \t]+ %% "+" {return('+');} "-" {return('-');} "*" {return('*');} "/" {return('/');} "%" {return('%');} "^" {return('^');} "(" {return('(');} ")" {return(')');} "\n" {return('\n');} {BinNumber} {value = decodeNumber( 2,yytext+2,yyleng-2);return(NUMBER);} {OctNumber} {value = decodeNumber( 8,yytext,yyleng);return(NUMBER);} {DecNumber} {value = decodeNumber(10,yytext,yyleng);return(NUMBER);} {HexNumber} {value = decodeNumber(16,yytext+2,yyleng-2);return(NUMBER);} {FloatNumber} {value = decodeNumber(10,yytext,yyleng);return(NUMBER);} {WhiteSpace} {/*Ignore*/} . { /*Unexpected Text that does not match anything above*/ std::cout << "ERROR: bad input (" << std::string(yytext,yytext+yyleng) << ")" << std::endl; } %% static double decodeNumber(int radex,const char* begin,int length) { std::stringstream str(std::string(begin,begin+length)); double result; str >> std::setbase(radex) >> result; return(result); } |
| CODE |
DEFININITIONS %% TOKEN DEFINITION %% <Normal C/C++ source> |
| CODE |
Name Definition (This are very similar to Regular expressions) EBNF: [ <STUFF> ] Means match any character between the '[' and ']' . Match any 1 character. + Means match the previous symbol 1 or more times. * Means match the previous symbol 0 or more times. ? Means match the previous symbol 0 or 1 time. {NAME} Means use a previously defined name. So: DecDigit [0-9] DecDigit will match 1 character that has a value in the range '0' -> '9' DecNumber [1-9]{DecDigit}* DecNumber will match a sequence of 1 or more digits that does not start with 0. [1-9] -> Match 1 character that has a value in the range '1' -> '9' {DecDigit}* Match 0 or more DecDigits. |
| CODE |
| '+' {return('+');} |
| CODE |
| {DecNumber} {value = decodeNumber(10,yytext,yyleng);return(NUMBER);} |
| CODE |
| if {return (STATMENT_IF);} else {return (STATMENT_ELSE);} for {return (STATMENT_FOR);} while {return (STATMENT_WHILE);} |
| CODE |
| {WhiteSpace} {/*Ignore*/} |
| CODE |
| . { /*Unexpected Text that does not match anything above*/ std::cout << "ERROR: bad input (" << std::string(yytext,yytext+yyleng) << ")" << std::endl; } |
| CODE |
%{ #include "calc.h" #include "calc.tab.h" #include <iostream> %} %token NUMBER %% input: expr '\n' {std::cout << "RESULT: " << $1 << std::endl;return(0);}; ; expr: expr '+' term {$$ = $1 + $3;} | expr '-' term {$$ = $1 - $3;} | term {$$ = $1;} ; term: term '*' factor {$$ = $1 * $3;} | term '/' factor {$$ = $1 / $3;} | term '%' factor {$$ = static_cast<double>(static_cast<int>($1) % static_cast<int>($3));} | factor {$$ = $1;} ; factor: '(' expr ')' {$$ = $2;} | '-' factor {$$ = -$2;} | '+' factor {$$ = +$2;} | NUMBER {$$ = value;} ; %% |
| CODE |
DECLARATIONS %% SYNTAX DEFINITION %% C/C++ source |
| CODE |
| %{ %} |
| CODE |
| %token NUMBER |
| CODE |
| Terminal: A value returned by the lexer (or defined by %token above). NonTerminal: A definition that is defined in the SYNTAX DEFINITION section. Token: A Terminal or a NonTerminal. Token List: A list of tokens. |
| CODE |
| <NonTerminal>: <Token List> {C/C++ Source} [ | <Token List> {C/C++ Source}]*; |
| CODE |
| input: expr '\n' {return(0);}; |
| CODE |
| expr: expr '+' term {$$ = $1 + $3;} | expr '-' term {$$ = $1 - $3;} | term {$$ = $1;} ; |
| CODE |
| expr '+' term |
| CODE |
| expr '-' term |
| CODE |
| term |
| CODE |
| $$ : The value of the defined NonTerminal. $<X>: Is the value of the <X> token. For Terminals this is undefined. For NonTerminals it is the value set to $$ in that NonTerminals definition. |
| CODE |
functionDef: type funcName '(' paramList ')' functionBody {return(new func($1,$2,$4,$6));} functionBody: '{' statmentList '}' {return($2);} funcName: identifier {return($1);} paramList: {return(new ParameterList());} | params {return($1);} params: parameterDef {return(new ParameterList($1));} | params ',' parameterDef {$1->push_back($3);} |
| CODE |
#include "calc.h" #include <iostream> double value; int main(int argc,char* argv[]) { std::cout << "Welcome to Expression Calculator (c) 2005 By myork ^^;;;" << std::endl << "You can use CTRL+C to quit" << std::endl << std::endl; for(;;) { std::cout << "Enter Expression: "; yyparse(); } return 0; } /* * yyerror() * Generated diagnostic error message. */ void yyerror(const char* errorMsg) { std::cout << "ERROR: " << errorMsg << std::endl; } /* * yywrap() * Let the lexer know if there is more input after it has reached the end of the input stream. */ int yywrap() { /* * When the input stream is empty this function is called. * * If you return 1 (non zero) then we have finished parsing and yyparse() will exit. * * If you return 0. * Then you must set yyin to an open FILE where more input can be read from. */ return(1); } |
| CODE |
#ifndef CALC_H #define CALC_H #define YYSTYPE double extern double value; extern "C" int yywrap(); extern "C" int yylex(); extern "C" void yyerror(const char* errorMsg); extern "C" int yyparse(); #endif |
| CODE |
YACC = bison LEX = flex calc: main.cpp calc.tab.c lex.yy.c g++ main.cpp calc.tab.c lex.yy.c -o calc calc.tab.c: calc.y $(YACC) -d calc.y lex.yy.c: calc.l $(LEX) calc.l |
| QUOTE |
| Name EBNF Definition (This is very similar to Regular expressions) EBNF: [ <STUFF> ] Means match any character between the '[' and ']' . Match any 1 character. + Means match the previous symbol 1 or more times. * Means match the previous symbol 0 or more times. ? Means match the previous symbol 0 or 1 time. {NAME} Means use a previously defined name. So: DecDigit [0-9] DecDigit will match 1 character that has a value in the range '0' -> '9' DecNumber [1-9]{DecDigit}* DecNumber will match a sequence of 1 or more digits that does not start with 0. [1-9] -> Match 1 character that has a value in the range '1' -> '9' {DecDigit}* Match 0 or more DecDigits. |