I have a simple flex source code which skips the comments in /* */ and should get the count of comments found:
%{
int in_comment = 0;
int count = 0;
%}
%%
\/\* { in_comment = 1; count++; }
\*\/ { in_comment = 0; }
. { if (!in_comment) ECHO; }
%%
int main(void)
{
yylex();
printf("Comments found %d\n", count); // never executed
return 0;
}
First half works fine - it really skips the comments, but they are not counted... what can I do to execute printf line?
I just tried it myself. So I copied your source code to "x.l" and did a make x
ld then complained about the missing yywrap() function. After adding
%option noyywrap
The compile succeeded and a test showed:
ronald#cheetah:~/tmp$ ./x < cribbage.c
... lots of output ...
Comments found 15
UPDATE:
If the text is not loaded from a file (just ./x), you have to end your manual input by CTRL + D
Related
This is for a homework assignment. The only code I've edited myself are the definitions, rules, and tokens. What I have so far compiles successfully but gives me a segmentation fault when I try to run it on the markdown file (.md), and the HTML output is just a blank file because of that.
%{
#define YYSTYPE char *
#include <string.h>
#include "miniMD2html.tab.h"
extern YYSTYPE yylval;
%}
%option yylineno
/* Flex definitions */
whitespace [ \t]+
newline [\n]+|{whitespace}[\n]+
textword [a-zA-Z:/.\-,\']+
integer [0-9]+
header #|##|###|####|#####
%%
{header} { return T_HEADER; }
{integer} { return T_INTEGER; }
{textword} { return T_TEXTWORD; }
{whitespace} { return T_BLANK; }
{newline} { return T_NEWLINE; }
%%
The generate functions are given in another file. Most of them just accept char*, the generate_header function takes an int and char*, and the generate_image function takes two char* and two int. The grammar may look weird but this is what was given in the assignment.
%{
#include "global.h"
#include "stdlib.h"
#include "stdio.h"
#define YYSTYPE char *
extern int yylex();
int yywrap();
int yyerror(const char*);
int yyparse();
extern FILE *yyin;
Html_Doc *html_doc;
%}
/* Define tokens here */
%token T_BLANK T_NEWLINE
%token T_HEADER T_INTEGER T_TEXTWORD
%% /* Grammar rules and actions follow */
s: mddoc;
mddoc: /*empty*/ | mddoc paragraph;
paragraph: T_NEWLINE {add_linebreak(html_doc);}
| pcontent T_NEWLINE {add_element(html_doc, $1); free($1);} ;
pcontent: header
| rftext {generate_paragraph($1);}
header: T_HEADER T_BLANK rftext {generate_header(strlen($1), $3);}
rftext: rftext T_BLANK rftextword {strappend($1, $3);}
| rftext rftextword {strappend($1, $2);}
| rftextword
rftextword: textnum | image | format
image: "![" text "](" text '=' T_INTEGER '#' T_INTEGER ')' {generate_image($2, $4, atoi($6), atoi($8));}
format: "**" text "**" {generate_bold($2);}
| '_' text '_' {generate_italic($2);}
| "**" format "**" {generate_bold($2);}
| '_' format '_' {generate_italic($2);}
text: text T_BLANK textnum {strappend($1, $3);}
| text textnum {strappend($1, $2);}
| textnum
textnum: T_TEXTWORD | T_INTEGER
%%
int main(int argc, char *argv[]) {
// yydebug = 1;
FILE *fconfig = fopen(argv[1], "r");
// make sure it is valid
if (!fconfig) {
printf("Error reading file!\n");
return -1;
}
html_doc = new_html_doc();
// set lex to read from file
yyin = fconfig;
int ret = yyparse();
output_result(html_doc);
del_html_doc(html_doc);
return ret;
}
int yywrap(){
return 1;
}
int yyerror(const char* s){
extern int yylineno;
extern char *yytext;
printf("error while parsing line %d: %s at '%s', ASCII code: %d\n", yylineno, s, yytext, (int)(*yytext));
return 1;
}
None of your flex rules ever set the value of yylval, so it will be NULL throughout. And so will all the references to semantic values ($n) in your grammar. Since most functions which take a char* assume that it is a valid string, it's pretty likely that one of them will soon try to examine the string value, and the fact that the pointer is NULL will certainly lead to a segfault.
In addition, there are both single character and quoted string tokens in your grammar, none of which can be produced by your scanner. So it's quite likely that the parser will stop with a syntax error as soon as one of the non-word characters is encountered in the input.
In the bison file, every token should be separated by ;
s: mddoc;
mddoc: /*empty*/ | mddoc paragraph;
paragraph: ...
Notice the
;
after mmdoc paragraph.
This is correct but the following tokens are not separated well.
Also, as #Rockcat as said, in the flex file, you should add
yylval = strdup(yytext);
before returning your token to the bison file.
I am trying to create a lex scanner that reads through a header file and then finds lexical errors and writes them to a text output but I keep running into a undefined error on the lines that contain the tokens {line} and {punc}. I'm completely new to lex so I have not been able to identify quite what is missing. Here is part of my code so far that has the errors:
%{
#include <stdio.h>
#include <ctype.h>
#include "tokens.h"
%}
%{ option noyywrap
%}
ws [ \t\r]+
%%
[ \t\n] ;
. printf("Unexpected Character\n");
: return COLON;
{ws} { ECHO; }
{line} { ECHO; Listing::nextLine();}
"<" { ECHO; return(RELOP); }
begin { ECHO; return(BEGIN_); }
{punc} { ECHO; return yytext[0]; }
. { ECHO; Listing::appendError(LEXICAL, yytext); }
%%
int main()
{
yylex();
}
You have to define line and punc in the initial section, just as you did with ws. The error is telling you that it couldn't expand {line} and {punc} because there was no definition for those two identifiers.
I have written Flex stuff in a previous class but none of my previously working code is solving the issue I am having.
I have searched around StackOverflow for a solution but none of them have solved it.
I have:
Checked I have no errant spaces in the %{ ... %} area
Tried using #include <'iostream>
Tried %option noyywrap
Here is my code (I removed all the tokens and such because there is a lot of them):
%{
...
int numLines = 0;
void printTokenInfo(char* tokenType, char* lexeme);
void handleComments(char* text);
%}
WSPACE [ \t\r]+
NEWLINE \n
DIGIT [0-9]
LETTER [a-zA-Z]
IDENT ({LETTER}|_)({LETTER}|{DIGIT}|_)*
INTCONST {DIGIT}+
CHARCONST "'"{LETTER}+"'"
%%
...
%%
// User-written code goes here
void printTokenInfo(char* tokenType, char* lexeme)
{
printf("A");
printf("TOKEN: %s LEXEME: %s\n", tokenType, lexeme);
}
void handleComments(char* text)
{
printf("%s\n", text);
}
int yywrap() { return 1; }
int main()
{
do {
yylex();
} while (!feof(yyin));
return 0;
}
Here is how I am compiling and running it:
flex FILENAME.l
g++ lex.yy.c -o lexer
lexer < INPUT.txt
And the instructor provided us with input files but none of them have worked. They all fail with 'premature EOF' or 'bad character'
Any ideas?
Well, I think I finally discovered the answer... Try running it with the complete path rather than just the name of your compiled lexer. I discovered the 'actual' path by running it under gdb (Which admittedly should have been my first instinct).
gdb lexer
(gdb) run < INPUT.txt
Originally, I was trying to run it with:
lexer < INPUT.txt
But I discovered by running it with gdb that this worked:
/nethome/users/mjc7w6/Classes/lexer < INPUT.txt
Edit: Someone chimed in on my Facebook with a further improvement. If the above solution fixes it for you, you might need to edit your ~/.bashrc with the following:
export PATH=/nethome/users/mjc7w6/Classes:$PATH
Or however you find that path to be set-up.
I have a problem with a program that I'm writing. It is a command line parser that parses bencode (used in torrent files). The program accepts a filename as it's command line. When I build and run the program in Microsoft Visual Studio 10.0 using the debugging Commmand Line arguments setting to input a command line the program tells me that it failed parsing.
If I open a command prompt and run the program from the command prompt with the same command line, the program works perfectly! What's going on? Is this a common problem with Visual Studio?
I used the debugger in Visual Studio to trace where the program fails and it appears that a call to the stat function ( http://msdn.microsoft.com/en-us/library/14h5k7ff.aspx ) used to get the length of the file returns an error in Visual Studio but works fine when run outside of Visual Studio.
The Code uses a Bencode parser which can be found here: http://funzix.git.sourceforge.net/git/gitweb.cgi?p=funzix/funzix;a=blob;f=bencode/bencode.c
And here is the code for the program:
#include <stdio.h>
#include "../Parse/bencode.h"
int main(int argc, char *argv[]){
if(argc != 2){
printf("Usage: whirlwind filename\n");
return 1;
}
char *buf;
long long len;
be_node *n;
//read the torrent file into a buffer and store at &buf
buf = read_file(argv[1], &len);
if(!buf){
buf = argv[1];
len = strlen(argv[1]);
}
printf("Decoding: %s\n", argv[1]);
n = be_decoden(buf, len);
if(!n){
printf("Parsing failed!\n");
return 1;
}
if(n->type != BE_DICT){
printf("This file is not a valid Bencoded Dictionary.\n");
return 1;
}
int i;
char* keyName;
for(i = 0; i < 10; i++){
keyName = n->val.d[i].key;
if(keyName == "announce"){
printf("\n\n");
}
printf("%s\n", keyName);
if(keyName == "announce"){
printf("\n\n");
}
}
return 0;
}
If you pass a relative path from Visual Studio you should be sure that it resolves correctly when your app runs inside the IDE. This problem arises because, when debugging, the current directory is usually \bin\debug.
To be on the safe side put a full pathname or read the location of your file from a configuration file.
After successfully compiling a Python/C binding with SIP I wanted to do the same thing with Python/C++. For some reason this doesn't work.
Here's the files:
fib.cpp
#include "fib.h"
int fib1(int n)
{
if (n <= 0) {
return 0;
} else if (n <= 2) {
return 1;
} else {
return fib1(n-1) + fib1(n-2);
}
}
fib.h
int fib1(int n);
fib.sip
%Module fib
%Include fib.h
I run the following command to build the intermediate files:
sip -c . fib.sip
So far everything works.
Now I want to build the .pyd file using distutils.
setup.py
from distutils.core import setup, Extension
import sipdistutils
setup(
name = 'fib',
versione = '1.0',
ext_modules=[
Extension("fib", ["fib.sip", "fib.cpp"]),
],
cmdclass = {'build_ext': sipdistutils.build_ext}
)
I run the following command:
python setup.py build
This fails with the following error:
build\temp.win32-2.7\Release\sipfibcmodule.cpp:29:29: error: 'fib1' was not declared in this scope
error: command 'gcc' failed with exit status 1
What could the problem be? Shouldn't c++ be used as a compiler instead of gcc, by the way?
Any help appreciated!
Kind regards
David
I've found a solution that is good enough: namespaces. Next time I'll read the documentation better. I should also mention that a solution with a Fibonacci class could solve the problem, but I didn't find that to be satisfying.
Below the content of the files can be found.
fib.cpp
#include "fib.h"
namespace test
{
int fib1(int n)
{
if (n <= 0) {
return 0;
} else if (n <= 2) {
return 1;
} else {
return fib1(n-1) + fib1(n-2);
}
}
}
fib.h
namespace test
{
int fib1(int n);
}
fib.sip
%Module fib
namespace test {
%TypeHeaderCode
#include "fib.h"
%End
int fib1(int n);
};
setup.py - nothing was changed
Exactly the same commands as mentioned before were used.