I have to make a calculator in flex/bison for a lab in class and I have to add functionality to compute square roots or absolute values in they put in sqrt(x) or abs(x). I imported the math library and I got the caculator to work if the COMMAND FOR IT CONSIST OF ONE CHARACTER. Here's what I mean:
expr:
......
| '(' expr ')' { $$ = fabs($2); } //for abs
| '[' expr ']' {$$ = sqrt($2); } //for sqrt
.......
now, this works fine and if i put in (-2) i get 2, or [4] = 2. The problem is clearly, i need to make it so the command is abs(x) and sqrt(x). If I switch the code to say
| "abs(" expr ')' { $$ = fabs($2); } //for abs
| "sqrt" expr ']' {$$ = sqrt($2); } //for sqrt
this doesn't work because it sees the a then b, and tries to do something with that. This is likely because my calculator also supports assigning variable values (like x=2), so it thinks there should be an operator between a and b. I unfortunately have no idea how to fix this. I would appreciate any help.
Here's my code if that helps:
hexcalc.y
%{
#include <stdio.h>
#include <math.h>
#include <stdlib.h> // often required
// A simple error message to move things along
void yyerror(const char *msg)
{
printf("ERROR(PARSER): %s\n", msg);
}
// Storage for variables: yes Virginia, only 26 variables possible in this langu$
long variables[26];
%}
%union {
float nvalue;
int ivalue;
int varindex;
}
%token <nvalue> NUMBER
%token <ivalue> INT
%token <varindex> NAME
%type <nvalue> expr
%type <nvalue> term
%type <nvalue> varOrNum
%%
statementList : statement '\n'
| statement '\n' statementList
;
statement : NAME '=' expr { variables[$1] = $3; }
| expr { printf("RESULT: %f\n", $1); }
;
expr: expr '+' term { $$ = $1 + $3; }
| expr '-' term { $$ = $1 - $3; }
| '-' term { $$ = 0 - $2; }
| "abs(" expr ')' { $$ = $2; }
| "sqrt(" expr ')' { $$ = sqrt($2); }
| expr '/' term { $$ = $1 / $3; }
| term { $$ = $1; }
;
term : term '*' varOrNum { $$ = $1 * $3; }
| varOrNum { $$ = $1; }
;
varOrNum : NUMBER { $$ = $1; }
| NAME { $$ = variables[$1]; }
;
%%
main() {
int i;
for (i=0; i<26; i++) variables[i] = 0;
yyparse();
}
hexcalc.l
%{
#include <stdlib.h>
#include <math.h>
#include "hexcalc.h"
#define BASE 10
char* endptr;
%}
%%
[a-z] { yylval.varindex = yytext[0] - 'a'; $
}
[0-9]+ { yylval.nvalue = atof(yytext);
return NUMBER;
}
[0-9]+"."[0-9]+?|"."[0-9]+? {yylval.nvalue = atof(yytext);
return NUMBER;
}
[ \t] ;
\n|. { return yytext[0];
}
%%
int yywrap() {
return 1;
}
You need to recognize multicharacter names in the lexer as single tokens and then use them in your grammar. The easy way is to just add them to your lexer:
abs { return ABS; }
sqrt { return SQRT; }
Then you can add to your parser:
%token ABS SQRT
%%
expr: ABS '(' expr ')' { $$ = fabs($3); }
| SQRT '(' expr ')' { $$ = sqrt($3); }
You need to create rules in your .l file for "abs" and "sqrt"; declare the tokens they will each return via %token; and use those token names in the grammar rules: ABS "(" expr ")" : ...
You should have a look at Bison's documentation where a more scalable solution for predefined functions is given (using a symbol table).
http://www.gnu.org/software/bison/manual/html_node/Multi_002dfunction-Calc.html
Related
I'm trying to figure out how to divide a character with a string and get a float as the quota. I've done the following in my code:
Procedure extwo is
function "-"(Strang: in String;
Char: in Character) return Float is
F: Float := Float'Value(Strang);
begin
return Float(Character'Pos(Char)-48) - Float'Value(Strang);
end "-";
Differensen: Float;
Char: Character;
Strang: String(1.
Begin
Put("Mata in ett tecken: ");
Get(Char);
Put("Mata in en sträng med exakt 3 tecken: ");
Get(Strang);
Differensen:= Char-Strang;
Put("Du matade in tecknet: ");
Put(Char);
Put(" och strängen: ");
Put(Strang);
Put(" och differensen blev ");
Put(Differensen, Fore=> 0);
end extwo;
With this I get the error messages: " invalid operand types for operator "-" ", " left operand has type "Standard.Character" " and " right operand has subtype of "Standard.String" defined at line 59 "
all on line 95:22 which is the line where it says "Differensen:= Char-Strang;"
It’s easier with operators to use the names L for the parameter that goes on the left of the operator, R for the parameter that goes on the right.
Which, in order to match your usage (Char - Strang) and your implementation would be
function "-" (L : Character; R : String) return Float;
Given the concrete syntax of a language, I would like to define a function "instance" with signature str (type[&T]) that could be called with the reified type of the syntax and return a valid instance of the language.
For example, with this syntax:
lexical IntegerLiteral = [0-9]+;
start syntax Exp
= IntegerLiteral
| bracket "(" Exp ")"
> left Exp "*" Exp
> left Exp "+" Exp
;
A valid return of instance(#Exp) could be "1+(2*3)".
The reified type of a concrete syntax definition does contain information about the productions, but I am not sure if this approach is better than a dedicated data structure. Any pointers of how could I implement it?
The most natural thing is to use the Tree data-type from the ParseTree module in the standard library. It is the format that the parser produces, but you can also use it yourself. To get a string from the tree, simply print it in a string like so:
str s = "<myTree>";
A relatively complete random tree generator can be found here: https://github.com/cwi-swat/drambiguity/blob/master/src/GenerateTrees.rsc
The core of the implementation is this:
Tree randomChar(range(int min, int max)) = char(arbInt(max + 1 - min) + min);
Tree randomTree(type[Tree] gr)
= randomTree(gr.symbol, 0, toMap({ <s, p> | s <- gr.definitions, /Production p:prod(_,_,_) <- gr.definitions[s]}));
Tree randomTree(\char-class(list[CharRange] ranges), int rec, map[Symbol, set[Production]] _)
= randomChar(ranges[arbInt(size(ranges))]);
default Tree randomTree(Symbol sort, int rec, map[Symbol, set[Production]] gr) {
p = randomAlt(sort, gr[sort], rec);
return appl(p, [randomTree(delabel(s), rec + 1, gr) | s <- p.symbols]);
}
default Production randomAlt(Symbol sort, set[Production] alts, int rec) {
int w(Production p) = rec > 100 ? p.weight * p.weight : p.weight;
int total(set[Production] ps) = (1 | it + w(p) | Production p <- ps);
r = arbInt(total(alts));
count = 0;
for (Production p <- alts) {
count += w(p);
if (count >= r) {
return p;
}
}
throw "could not select a production for <sort> from <alts>";
}
Tree randomChar(range(int min, int max)) = char(arbInt(max + 1 - min) + min);
It is a simple recursive function which randomly selects productions from a reified grammar.
The trick towards termination lies in the weight of each rule. This is computed a priori, such that every rule has its own weight in the random selection. We take care to give the set of rules that lead to termination at least 50% chance of being selected (as opposed to the recursive rules) (code here: https://github.com/cwi-swat/drambiguity/blob/master/src/Termination.rsc)
Grammar terminationWeights(Grammar g) {
deps = dependencies(g.rules);
weights = ();
recProds = {p | /p:prod(s,[*_,t,*_],_) := g, <delabel(t), delabel(s)> in deps};
for (nt <- g.rules) {
prods = {p | /p:prod(_,_,_) := g.rules[nt]};
count = size(prods);
recCount = size(prods & recProds);
notRecCount = size(prods - recProds);
// at least 50% of the weight should go to non-recursive rules if they exist
notRecWeight = notRecCount != 0 ? (count * 10) / (2 * notRecCount) : 0;
recWeight = recCount != 0 ? (count * 10) / (2 * recCount) : 0;
weights += (p : p in recProds ? recWeight : notRecWeight | p <- prods);
}
return visit (g) {
case p:prod(_, _, _) => p[weight=weights[p]]
}
}
#memo
rel[Symbol,Symbol] dependencies(map[Symbol, Production] gr)
= {<delabel(from),delabel(to)> | /prod(Symbol from,[_*,Symbol to,_*],_) := gr}+;
Note that this randomTree algorithm will not terminate on grammars that are not "productive" (i.e. they have only a rule like syntax E = E;
Also it can generate trees that are filtered by disambiguation rules. So you can check this by running the parser on a generated string and check for parse errors. Also it can generated ambiguous strings.
By the way, this code was inspired by the PhD thesis of Naveneetha Vasudevan of King's College, London.
As a Homework we got a basic calculator which can only do + operations and we have to implement more functions. We had to implement the bracket operator, sign operators and min max functions. One of the last tasks is to expand the min/max function to calculate min/max with more than only two parameters and thats the task where I'm currently stuck.
My current calc.l lex file:
%{
extern int yylval;
extern int sym[];
extern int yyerror(char *s);
#include "y.tab.h"
%}
%%
[a-z] {
yylval = *yytext - 'a';
return VARIABLE;
}
[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}
[(),] { return *yytext; }
":=" return ASSIGN;
"+" return PLUS;
"-" return MINUS;
"/" return DIVIDE;
"%" return MODULO;
"*" return TIMES;
"<" return SMAS;
"<=" return SMGAS;
"==" return IS;
"!=" return NOTIS;
">=" return BGGAS;
">" return BGAS;
"min" return MIN;
"max" return MAX;
"\n" return NEWLINE;
[ \t] ;
. yyerror("Invalid character");
%%
int yywrap() {
return 1;
}
My current calc.y yacc file:
%{
#include <stdio.h>
int sym[26];
int yylex();
int yyerror(char *s);
%}
%token VARIABLE ASSIGN INTEGER NEWLINE
%left PLUS
%left TIMES
%left MINUS
%left DIVIDE
%left MODULO
%left UMINUS
%left UPLUS
%left SMAS SMGAS IS NOTIS BGAS BGGAS
%left MIN MAX
%%
program: program statement
|
;
statement: expr NEWLINE
{ printf("%d\n", $1); }
| VARIABLE ASSIGN expr NEWLINE
{ sym[$1] = $3; }
;
expr: INTEGER { $$ = $1; }
| VARIABLE { $$ = sym[$1]; }
| expr PLUS expr { $$ = $1 + $3; }
| expr TIMES expr { $$ = $1 * $3; }
| expr MINUS expr { $$ = $1 - $3; }
| expr DIVIDE expr { $$ = $1 / $3; }
| expr MODULO expr { $$ = $1 % $3; }
| '(' expr ')' { $$ = $2; }
| MINUS expr %prec UMINUS { $$ = -$2; }
| PLUS expr %prec UPLUS { $$ = $2; }
| expr SMAS expr { $$ = $1 < $3; }
| expr SMGAS expr { $$ = $1 <= $3; }
| expr IS expr { $$ = $1 == $3; }
| expr NOTIS expr { $$ = $1 != $3; }
| expr BGGAS expr { $$ = $1 >= $3; }
| expr BGAS expr { $$ = $1 > $3; }
| MIN '(' expr ',' expr ')' { if ($3 < $5){ $$ = $3; } else if ($3 > $5){ $$ = $5; }; }
| MAX '(' expr ',' expr ')' { if ($3 > $5){ $$ = $3; } else if ($3 < $5){ $$ = $5; }; }
;
%%
int yyerror(char *s) {
fprintf(stderr, "%s\n", s);
return 0;
}
int main() {
yyparse();
return 0;
}
I think one solution would be to seperate each value with an , in the min/max function and calculate it and then give it back to the min/max function, but I'm not sure how to implement it. The only solution I could think of is rather complex. Since the project shouldn't be that complex I think I'm missing an easy way to do it.
min(5, 6) returns 5 as it should, and the expected way how it should work is (min 6, 7, 3) and return 3 and you can expend it to an infinite number of parameters.
Does any of you have an Idea?
Thanks!
You need max(x,y) and max(x,y,z,q..).
One possible solution is (... x , z ...) repeatable so you will need few rules for that. Note var, it is use to determine what operation we need.
expr ',' expr { if(var==1){$$=$1>$3?$1:$3;}else{$$=$1<$3?$1:$3;}; }
'(' expr ')' { $$ = $2;}
MAX expr { $$ = $2;}
MAX expr { $$ = $2;}
In your *.l file you need external variable (let's call it var)
extern int var.
Add also a redex rule for max and min, which will set our variable to 1 or 0:
min { op =0;}
max { op =1;}
Where 1 is MAX and MIN is 0.
This is done in .l file because we want to set the var first before me make the operations.
If you do it in .y file, the var will be set after the operations.
Add the variable to your *.y file too (int var =0).
In .y file you MAX and MIN should be %tokens. Plus, add , with %right on first/second place (you can use COMMA instead ,). Otherwise if you have ..4,5*5,.. if will first compare and then it will multiply it.
AIUI you should handle an arbitrary number of arguments to min/max. The standard way to do that would be
first to move the argument list into a separate rule, e.g. arg_list: expr ',' expr ; and make that return a list(-like object). The (sub)rules for min/max then calculate upon that returned list.
Second, make that arg_list rule handle 1 to n entries by making it recursive, analogous to the expr rule itself. The min/max rules then still have to calculate upon a list, just have to assume an arbitrary length >= 1, instead of length == 2.
I've checked other similar posts but I think I just need a second set of eyes. This file is for the lex Unix utility.
I created a makefile and this is the error I receive:
gcc -g -c lex.yy.c
cxref.l:57: error: expected ‘;’, ‘,’ or ‘)’ before numeric constant
make: *** [lex.yy.o] Error 1
Line 57 is just inside the void inserID() function near the top.
Here is the code:
%{
#include <stdio.h>
#include <string.h>
char identifier[1000][82];
char linesFound[100][100];
void insertId(char*, int);
int i = 0;
int lineNum = 1;
%}
%x comment
%s str
%%
"/*" BEGIN(comment);
<comment>[^*\n]* /* eat anything that's not a '*' */
<comment>"*"+[^*/\n]* /* eat up '*'s not followed by '/'s */
<comment>\n ++lineNum;
<comment>"*"+"/" BEGIN(INITIAL);
"\n" ++lineNum;
auto ;
break ;
case ;
char ;
continue ;
default ;
do ;
double ;
else ;
extern ;
float ;
for ;
goto ;
if ;
int ;
long ;
register ;
return ;
short ;
sizeof ;
static ;
struct ;
switch ;
typedef ;
union ;
unsigned ;
void ;
while ;
[*]?[a-zA-Z][a-zA-Z0-9_]* insertId(yytext, lineNum);
[^a-zA-Z0-9_]+ ;
[0-9]+ ;
%%
void insertId(char* str, int nLine)
{
char num[2];
sprintf ( num, "%d", nLine);
int iter;
for(iter = 0; iter <= i; iter++)
{
if ( strcmp(identifier[iter], str) == 0 )
{
strcat( linesFound[iter], ", " );
strcat( linesFound[iter], num );
return;
}
}
strcpy( identifier[i], str );
strcat( identifier[i], ": " );
strcpy( linesFound[i], num );
i++;
}
Your problem is:
%s str
There is a reason that it's normal to write condition names in CAPS: it makes them look like macros, which is exactly what they are.
So
void insertId(char* str, int nLine)
get macro expanded to something like:
void insertId(char* 2, int nLine)
and the compiler complains that 2 is not really expected at that point in the declaration.
I'm trying to draw a line, broken out into segments dependent on values. For example, if there are 5 fields, and all 5 fields were true, then my Line would look like
-----
If say the first and last fields were true, and everything else would be false, then it would be
- -
I thought I could do this with a bit mask of some sort. First of all, I've never done a bit mask before, but I think I've seen them here and there. I was wondering how I could go about this, and use enumerations instead of 1/0 for readability. As far as I can see from my data, I would only need values of either 1 or 0 for the different properties. However, it would be good to know how to have one of the values be a three level or higher enumeration for future reference. Thanks!
Trying to do something like:
enum CodingRegions {
Coding = 0x01,
NonCoding = 0x02
};
enum Substitution {
Synonymous = 0x04,
NonSynonmous = 0x05
};
Then based on the value of the object, I could do
bitmask???? = object.CodingRegion | object.Substitution;
Then later, check the value of the bitmask somehow, and then draw the line accordingly based on what the values are.
Not sure exactly what your requirements are, but here is one way it might be written in C:
#include <stdio.h>
typedef enum MyField_ {
hasWombat = 1 << 0,
hasTrinket = 1 << 1,
hasTinRoof = 1 << 2,
hasThreeWheels = 1 << 3,
myFieldEnd = 1 << 4,
} MyField;
void printMyField(MyField data) {
MyField field = 1;
while (field != myFieldEnd) {
printf("%c", data & field ? '-' : ' ');
field <<= 1;
}
printf("\n");
}
int main() {
MyField data = hasTrinket | hasThreeWheels;
printMyField(data);
data |= hasWombat; // set a field
data &= ~hasTrinket; // clear a field
printMyField(data);
return 0;
}
Not sure this is what you want, but:
// assumed Coding/NonCoding, Synonomous/NonSynonymous are opposites of each other. If not, add more bit fields
enum CodingRegions
{
Coding = 1 << 0
} ;
enum Substitution
{
Synonymous = 1 << 1
}
void PrintBitmask( NSUInteger bitmask )
{
printf( "%s", bitmask & Coding != 0 ? "-" : " " ) ;
printf( "%s", bitmask & Substitution != 0 ? "-" : " " ) ;
printf( "\n" ) ;
}
Your PrintBitmask() could also look like this:
void PrintBitmask( NSUInteger bitmask )
{
printf( "%s", bitmask & Coding != 0 ? "Coding" : "Noncoding" ) ;
printf( "|" ) ;
printf( "%s", bitmask & Substitution != 0 ? "Synonymous-" : "Nonsynonymous" ) ;
printf( "\n" ) ;
}
/* I prefer macros over enums (at least for something this simple) */
#define SPACE 0x0
#define DASH 0x1
/* input fields */
int fields[5] = {DASH,SPACE,SPACE,SPACE,DASH};
/* create bitmask */
for (int i=0; i<5; i++) {
mask |= (fields[i] << i);
}
/* interpret bitmask and print the line */
for (int i=0; i<5; i++) {
if (mask & (fields[i] << i)) {
printf("%c", '-');
} else {
printf("%c", ' ');
}
}