PDA

View Full Version : [SOLVED] Help with Flex and Bison grammars



trilobite2
February 16th, 2018, 07:56 AM
Hi all -

I'm trying to use Flex and Bison to put together a small programming language (I've called it miniFPL for "mini functional programming language").
I'm trying to make the syntax somewhat Haskell-ish (although unlike Haskell it doesn't use indentation, it does use semicolons and it isn't a "lazy evaluation" language).

Anyway, I'm getting these errors from Bison at present -

~/miniFPL $ bison -d miniFPL.y
miniFPL.y:55.17-20: error: symbol BOOL is used, but is not defined as a token and has no rules
| BOOL
^^^^
miniFPL.y:53.17-20: error: symbol CHAR is used, but is not defined as a token and has no rules
| CHAR
^^^^
miniFPL.y:52.17-21: error: symbol FLOAT is used, but is not defined as a token and has no rules
| FLOAT
^^^^^
miniFPL.y:51.17-19: error: symbol INT is used, but is not defined as a token and has no rules
type: INT
^^^
miniFPL.y:56.17-20: error: symbol LIST is used, but is not defined as a token and has no rules
| LIST
^^^^
miniFPL.y:57.17-20: error: symbol NONE is used, but is not defined as a token and has no rules
| NONE
^^^^
miniFPL.y:54.17-22: error: symbol STRING is used, but is not defined as a token and has no rules
| STRING
^^^^^^
miniFPL.y:21.15-18: error: symbol bool is used, but is not defined as a token and has no rules
| bool
^^^^
miniFPL.y:19.15-18: error: symbol char is used, but is not defined as a token and has no rules
| char
^^^^
miniFPL.y:18.15-19: error: symbol float is used, but is not defined as a token and has no rules
| float
^^^^^
miniFPL.y:17.15-21: error: symbol integer is used, but is not defined as a token and has no rules
| integer
^^^^^^^
miniFPL.y:20.15-20: error: symbol string is used, but is not defined as a token and has no rules
| string
^^^^^^
miniFPL.y:7.8-23: warning: symbol translation_unit is used, but is not defined as a token and has no rules [-Wother]
%start translation_unit
^^^^^^^^^^^^^^^^
miniFPL.y:93.17-23: error: symbol varname is used, but is not defined as a token and has no rules
func_vars: varname
^^^^^^^

This is my Flex file - miniFPL.l -



/* miniFPL.l */

digit [0-9]
letter [a-zA-Z_]


%{

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "y.tab.h"

void count(void);
%}

%%

[0-9]+ {
yylval = atoi(yytext);
return INTEGER;
}


[a-zA-Z_][a-zA-Z_][0-9] { return IDENTIFIER; }

\"([^\\\"]|\\.)*\" { return STRING_LITERAL; }


"/*" { comment(); }
"//"[^\n]* { /* double-slash comment */ }

"case" { count(); return(CASE); }
"of" { count(); return(OF); }
"otherwise" { count(); return(OTHERWISE); }
"print" { count(); return(PRINT); }

"<=" { count(); return(LE); }
">=" { count(); return(GE); }
"==" { count(); return(EQ); }
"!=" { count(); return(NE); }
";" { count(); return(';'); }
"=" { count(); return('='); }
"<" { count(); return('<'); }
">" { count(); return('>'); }
"+" { count(); return('+'); }
"-" { count(); return('-'); }
"*" { count(); return('*'); }
"/" { count(); return('/'); }
"^" { count(); return('^'); }

[ \t\v\n\f] { count(); }

%%

int yywrap(void)
{
return 1;
}


void comment(void)
{
char c, prev = 0;

while ((c = input()) != 0) /* (EOF maps to 0) */
{
if (c == '/' && prev == '*')
return;
prev = c;
}
error("unterminated comment");
}


int column = 0;

void count(void)
{
int i;

for (i = 0; yytext[i] != '\0'; i++)
if (yytext[i] == '\n')
column = 0;
else if (yytext[i] == '\t')
column += 8 - (column % 8);
else
column++;

ECHO;
}




This is my Bison file - miniFPL.y -





%token IDENT CONSTANT STRING_LITERAL
%token CASE OF OTHERWISE PRINT

%start translation_unit
%%

expr: simple_expr
| complex_expr
| ";" simple_expr
| ";" complex_expr
;

terminal: var_name
| integer
| float
| char
| string
| bool
| list
;

list: empty_list
| filled_list
;

empty_list: "[" "]"
;

filled_list: "[" terminal
| filled_list "," terminal "]"
;

simple_expr: terminal
| "(" expr ")"
| var_name "=" simple_expr
| condition
| print_expr
| func_call
| simple_expr "*" simple_expr
| simple_expr "/" simple_expr
| simple_expr "+" simple_expr
| simple_expr "-" simple_expr
;

print_expr: PRINT expr ";"
;

type: INT
| FLOAT
| CHAR
| STRING
| BOOL
| LIST
| NONE
;

complex_expr: case_expr
| func_expr
;

case_expr: case_head case_body
;

case_head: CASE var_name OF "\n"
;

case_body: case_line
| case_body "\n" case_line
;

case_line: in_value "->" out_value ";"
;

in_value: integer
| float
| char
| string
| bool
| list
| OTHERWISE
;

out_value: in_value
| simple_expr
;

func_call: func_name func_vars ";"
;

func_vars: varname
| func_vars varname
;

func_expr: func_decl func_body
;

func_decl: func_name "::" arg_types "->" return_type ";"
;

arg_types: type
| arg_types "->" type
;

return_type: type
;

func_body: simple_expr ";"
| func_body simple_expr
| case_expr
;

condition: simple_expr
| condition "and" condition
| condition "or" condition
| "not" condition
| simple_expr ">" simple_expr
| simple_expr ">=" simple_expr
| simple_expr "<" simple_expr
| simple_expr "<=" simple_expr
| simple_expr "==" simple_expr
| simple_expr "!=" simple_expr
;

var_name: identifier
;

func_name: identifier
;

identifier: IDENT
;




A few small examples of code that the tools should parse - this will give an idea of the "flavour" that I'm after -



area r = pi * r ^ 2 ;

areaRect l w = l * w ;

sq :: num -> num ;
sq n = n * n ;

mylist = ["foo", "bar", "baz"] ;

list2 = [ 1 , 2 , 3 ] ;

case a of
1 -> "One" ;
2 -> "Two" ;
3 -> "Three" ;
otherwise -> "Something else" ;

print "foo bar baz" ;



So - any help with these is very gratefully received!

Many thanks -
- trilobite