Why scanf in bison grammatical rule not working? - scanf

I have this gramatical rule in my .y file
...
listaIdentificadores :listaIdentificadores ',' ID {leer($3);}
|ID {leer($1);}
;
...
and this is definition of leer()
void leer(char* identificador) {
int valor;
scanf("%d",&valor);
cargarTS(identificador, valor);
}
but when scanf() should be executed it does not ask for the keyboard input and it simply continues with the execution of the following code line.

Related

Usage of CPD(Copy Paste Detector)

test.c
void fun(){
printf("int main char");
}
int main()
{
printf("int main int");
}
->Im giving the command like this run.sh cpd --minimum-tokens 5 --files /opt/test.c --language c and the output is as follows :
Found a 2 line (5 tokens) duplication in the following files:
Starting at line 1 of /opt/test.c
Starting at line 5 of /opt/test.c
void fun(){
printf("int main char ");
Even if there is no duplication, it is telling the code is duplicated because of minimum tokens.
Is there any way to specify the command without minimum tokens flag.
void fun(){
printf("int main int");
}
int main(){
printf("int main int");
}
I specified the command like this "run.sh cpd --minimum-tokens 9 --files /opt/test.c --language c" the output is as follows:
Added /opt/test.c <--- (No line duplication reported by tool)
This is because I specified the token value greater than the required token value which is 8. In the above case even if there is a duplicated code the tool is not returning any duplicated code.
So how to conclude on Min token size in such scenario in order to get correct duplication of code

I'm getting an error from gcc on my lex code: "#endif without #if"

This is my first attempt at writing a compiler using flex and bison. I wrote what look to me like legal lex and yacc code, but when I run it through the compiler I get an error message. This seems to come from gcc, so it's something wrong with the code generated by flex.
ghlex.l:20:2: error: #endif without #if
.map return DOTMAP;
Can anybody tell me what's wrong with the .map pattern and/or action?
(In case it's not obvious or I miscoded it, that's supposed to match the token ".map")
Here's my lex/flex source code:
%{
#include <stdio.h>
#include <string.h>
#include "gh.tab.h"
%}
DIGIT [0-9]
STARTCHAR [_a-zA-Z]
WORDCHAR {DIGIT}|{STARTCHAR}
FILECHAR {WORDCHAR}|[-.+##$%()]
FILECHAR1 {FILECHAR}|[/" ]
FILECHAR2 {FILECHAR}|[/' ]
/* special "start states" for matching
%s DESC FNAME1 FNAME2
%%
{DIGIT}+ yylval.number = atoi(yytext); return INT;
{STARTCHAR}{WORDCHAR}* yylval.string = strdup(yytext); return WORD;
FILECHAR$ yylval.string = strdup(yytext); return FILEPART;
'FILECHAR1+' yylval.string = strdup(yytext); return QUOTE;
"FILECHAR2+" yylval.string = strdup(yytext); return QUOTE;
\.map return DOTMAP;
\.m return DOTM;
\.r return DOTR;
\.c return DOTC;
\.d return DOTD;
\.t return DOTT;
\.o return DOTO;
\.u return DOTU;
\.v return DOTV;
, return COMMA;
\+ return PLUS;
- return MINUS;
\/ return SLASH;
; return SEMI;
\[ return LBRACKET;
\] return RBRACKET;
\%\$ return PCTDOL;
\%\/ return PCTSLASH;
\%t return PCTT;
\%# return PCTAT;
\n /* ignore newlines */
[ \t] /* ignore whitespace */
\/\/ /* ignore c++-style comments */
<DESC>.* yylval.string = strdup(yytext); return STRING;
%%
The problem is your unterminated comment on line 12:
/* special "start states" for matching
since this line begins with whitespace, it is copied verbatim into the lex.yy.c file, where it screws things up, commenting out several following lines generated by flex, including an #ifdef and the #line directives that would make the compiler output better line number information.
If you compile with -Wall (which you ALWAYS should), you'll get a warning: "/*" within comment before the error, which at least hints that the problem is related to comments (though this message too has an incorrect line number.)

Doxygen #code line numbers

Is there a way to display code line numbers inside a #code ... #endcode block? From the screenshots in the doxygen manual it would seem that there is, but I was unable to find an option for doxygen itself, or a tag syntax to accomplish this.
I need this to be able to write something like "In the above code, line 3" after a code block.
Tested also for fenced code blocks, still getting no numbers.
Short Answer
It seems that at least in the current version (1.8.9) line numbers are added:
to C code only when using \includelineno tag
to any Python code
Details
Python code formatter
Python code formatter includes line numbers if g_sourceFileDef evaluates as TRUE:
/*! start a new line of code, inserting a line number if g_sourceFileDef
* is TRUE. If a definition starts at the current line, then the line
* number is linked to the documentation of that definition.
*/
static void startCodeLine()
{
//if (g_currentFontClass) { g_code->endFontClass(); }
if (g_sourceFileDef)
( https://github.com/doxygen/doxygen/blob/Release_1_8_9/src/pycode.l#L356
)
It's initialized from FileDef *fd passed into parseCode/parsePythonCode if it was provided (non-zero) or from new FileDef(<...>) otherwise:
g_sourceFileDef = fd;
<...>
if (fd==0)
{
// create a dummy filedef for the example
g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
cleanupSourceDef = TRUE;
}
( https://github.com/doxygen/doxygen/blob/Release_1_8_9/src/pycode.l#L1458 )
so it seems all Python code is having line numbers included
C code formatter
C code formatter has an additional variable g_lineNumbers and includes line numbers if both g_sourceFileDef and g_lineNumbers evaluate as TRUE:
/*! start a new line of code, inserting a line number if g_sourceFileDef
* is TRUE. If a definition starts at the current line, then the line
* number is linked to the documentation of that definition.
*/
static void startCodeLine()
{
//if (g_currentFontClass) { g_code->endFontClass(); }
if (g_sourceFileDef && g_lineNumbers)
( https://github.com/doxygen/doxygen/blob/Release_1_8_9/src/code.l#L486 )
They are initialized in the following way:
g_sourceFileDef = fd;
g_lineNumbers = fd!=0 && showLineNumbers;
<...>
if (fd==0)
{
// create a dummy filedef for the example
g_sourceFileDef = new FileDef("",(exName?exName:"generated"));
cleanupSourceDef = TRUE;
}
( https://github.com/doxygen/doxygen/blob/Release_1_8_9/src/code.l#L3623 )
Note that g_lineNumbers remains FALSE if provided fd value was 0
HtmlDocVisitor
Among parseCode calls in HtmlDocVisitor::visit there is only one (for DocInclude::IncWithLines, what corresponds to \includelineno) which passes non-zero fd:
https://github.com/doxygen/doxygen/blob/Release_1_8_9/src/htmldocvisitor.cpp#L540
so this seems to be the only command which will result in line numbers included into C code listing

Counting lines of a file in Scala

I am studying Scala nowadays and this is my code snippet to count the number of lines in a text file.
//returns line number of a file
def getLineNumber(fileName: String): Integer = {
val src = io.Source.fromFile(fileName)
try {
src.getLines.size
} catch {
case error: FileNotFoundException => -1
case error: Exception => -1
}
finally {
src.close()
}
}
I am using Source.fromFile method as explained in Programming in Scala book. Here is the problem: If my text file is like this:
baris
ayse
deneme
I get the correct result 6. If I press enter after word deneme I still get number 6, however I exptect 7 in this case. If I press space after pressing enter I get 7 which is correct again. Is this a bug in Scala standard library or more possibly am I missing something?
Finally, my basic main method here If it helps:
def main(args: Array[String]): Unit = {
println(getLineNumber("C:\\Users\\baris\\Desktop\\bar.txt"))
}
It uses java.io.BufferedReader to readLine. Here is the source of that method:
/**
* Reads a line of text. A line is considered to be terminated by any one
* of a line feed ('\n'), a carriage return ('\r'), or a carriage return
* followed immediately by a linefeed.
*
* #return A String containing the contents of the line, not including
* any line-termination characters, or null if the end of the
* stream has been reached
*
* #exception IOException If an I/O error occurs
*
* #see java.nio.file.Files#readAllLines
*/
public String readLine() throws IOException {
return readLine(false);
}
Which calls this:
...
* #param ignoreLF If true, the next '\n' will be skipped
...
String readLine(boolean ignoreLF) ...
...
/* Skip a leftover '\n', if necessary */
if (omitLF && (cb[nextChar] == '\n'))
nextChar++;
skipLF = false;
omitLF = false;
So basically that's how it's implemented. I guess it depends what a line means to you. Are you counting lines that contain something or new line characters? - different things obviously.
If you press enter after word deneme simply you add an end-of-line sequence (CR+LF, in your case) to the 6th line. You see the cursor goes to new line, but you did not create a new line: You simply specify that the sixth line is over. To create a new line you have to put a character after the end-of-line sequence, as you make when you press space.

Lex program rules not working

%{
#include <stdio.h>
int sline=0,mline=0;
%}
%%
"/*"[a-zA-Z0-9 \t\n]*"*/" { mline++; }
"//".* { sline++; }
.|\n { fprintf(yyout,"%s",yytext); }
%%
int main(int argc,char *argv[])
{
if(argc!=3)
{
printf("Invalid number of arguments!\n");
return 1;
}
yyin=fopen(argv[1],"r");
yyout=fopen(argv[2],"w");
yylex();
printf("Single line comments = %d\nMultiline comments=%d\nTotal comments = %d\n",sline,mline,sline+mline);
return 0;
}
I am trying to make a Lex program which would count the number of comment lines (single-line comments and multi-line comments separately).
Using this code, I gave a .c file and a blank text file as input and output arguments.
When I have any special characters in multi-line comments, its not working for that multi-line and mline is not incremented for the comment line.
How do I fix this problem?
Below is a nudge in the right direction. The main differences between what you did and what I have done is that I made only two regex - one for whitespace and one for ident (identifiers). What I mean by identifiers is anything that you want to comment out. This regex can obviously be expanded out to include other characters and symbols. I also just defined the three patterns that begin and end comments and associated them with tokens that we could pass to the syntax analyzer (but that's a whole new topic).
I also changed the way that you feed input to the program. I find it cleaner to redirect input to a program from a file and redirect output to another file - if you need this.
Here is an example of how you might use this program:
flex filename.l
g++ lex.yy.c -o lexer
./lexer < input.txt
You can redirect the output to another file if you need to by using:
./lexer < input.txt > output.txt
Instead of the last command above.
Note: the '.'(dot) character at the end of the pattern matching is used as a catch-all for characters, sequences of characters, symbols, etc. that do not have a match.
There are many nuances to pattern matching using regex to match comment lines. For example, this would still match even if the comment line was part of a string.
Ex. " //This is a comment in a string! "
You will need to do a little more work to get past these nuances - like I said, this is a nudge in the right direction.
You can do something similar to this to accomplish your goal:
%{
#include <stdio.h>
int sline = 0;
int mline = 0;
#define T_SLINE 0001
#define T_BEGIN_MLINE 0002
#define T_END_MLINE 0003
#define T_UNKNOWN 0004
%}
WSPACE [ \t\r]+
IDENT [a-zA-Z0-9]
%%
"//" {
printf("TOKEN: T_SLINE LEXEME: %s\n", yytext);
sline++;
return T_SLINE;
}
"/*" {
printf("TOKEN: T_BEGIN_MLINE LEXEME: %s\n", yytext);
return T_BEGIN_MLINE;
}
"*/" {
printf("TOKEN: T_END_MLINE LEXEME: %s\n", yytext);
mline++;
return T_END_MLINE;
}
{IDENT} {/*Do nothing*/}
{WSPACE} { /*Do Nothing*/}
. {
printf("TOKEN: UNKNOWN LEXEME: %s\n", yytext);
return T_UNKNOWN;
}
%%
int yywrap(void) { return 1; }
int main(void) {
while ( yylex() );
printf("Single-line comments = %d\n Multi-line comments = %d\n Total comments = %d\n", sline, mline, (sline + mline));
return 0;
}
The problem is your regex for multiline comments:
"/*"[a-zA-Z0-9 \t\n]*"*/"
This only matches multiline comments that ONLY contain letters, digits, spaces, tabs, and newlines. If the comment contains anything else it won't match. You want something like:
/"*"([^*]|"*"+[^*/])*"*"+/
This will match anything except a */ between the /* and */.
Below is the full lex code to count the number of comment line and executable line.
%{
int cc=0,cl=0,el=0,flag=0;
%}
%x cmnt
%%
^[ \t]*"//".*\n {cc++;cl++;}
.+"//".*\n {cc++;cl++;el++;}
^[ \t]*"/*" {BEGIN cmnt;}
<cmnt>\n {cl++;}
<cmnt>.\n {cl++;}
<cmnt>"*/"\n {cl++;cc++;BEGIN 0;}
<cmnt>"*/" {cl++;cc++;BEGIN 0;}
.*"/*".*"*/".+\n {cc++;cl++;}
.+"/*".*"*/".*\n {cc++;cl++;el++;}
.+"/*" {BEGIN cmnt;}
.\n {el++;}
%%
main()
{
yyin=fopen("abc.cpp","r");
yyout=fopen("abc.txt","w");
yylex();
fprintf(yyout,"Comment Count: %d \nCommented Lines: %d \nExecutable Lines: %d",cc,cl,el);
}
int yywrap()
{
return 1;
}
The program takes the input as a c++ program that is abc.cpp and appends the output in the file abc.txt