简体   繁体   中英

flex/bison How can I make it recognize a pattern, whether the final character is a dot or not?

I try to make an analizer/parser of the code of prolog, here is an example of a fact: "dadof(arturo,armando)." It ends with a dot (.) and my parser recognize it and then print ("hecho") But I have another option and if the input it is "dadof(arturo,armando)" it does not recognize it. The only diference is the lack of the dot. But it suppossed that it should recognize it too and then print "(hecho") too. But it does not make it.

Here is my code

lex code:

%{
    #include <stdio.h>
    #include <string.h>
    #include "que.tab.h"

    void showError();

%}

%option noyywrap


LETTER [a-zA-Z]
WORD    {LETTER}+


%%

[[:blank:]] {}
[ \t\r] {} 
{WORD}  { sscanf(yytext, "%s",yylval.cad); return CADENA; }
"%"     { return PERCENT; }
"("     { return OPENB; }
")"     { return CLOSEB; }
","     { return COMA; }
"."     { return POINT; }
":-"    { return POINTSLASH; }
"[papa]"  { return NOFACT; }

.   { showError(); return OTROS; }
%%

void showError(char *OTROS){
    printf("  <<Error lexico: \"%s\">>  ", OTROS);

}

bison code:

%{
    #include <stdio.h>

    int yylex(void);
    void yyerror(char *s);
%}

%token CADENA PERCENT OTROS 
%token OPENB CLOSEB COMA POINT POINTSLASH

%type <cad> CADENA

%union{
    char cad[20];

}

%start INPUT


%%

INPUT
    : INICIO
    | INPUT INICIO
;
    INICIO:
        HECHOS
        {
            printf("(Hecho)");
        }
       
    ;

    HECHOS
        : HECHO POINT
        | HECHO
        
        
    ; 




    HECHO
        :INSTRUCCION OPENB INSTRUCCION COMA INSTRUCCION CLOSEB 
        | INSTRUCCION OPENB INSTRUCCION COMA INSTRUCCION CLOSEB COMA HECHO
        
          
    ;
   
    INSTRUCCION:
        | CADENA
        | OTROS
    ;

%%

int main(){

    return(yyparse());
    return 0;
}

void yyerror(char *s){
    printf("%s", s);
}

As I said before, it should print "(Hecho)" whether if the input ends whith a dot or not.

Although there are a number of issues with your code, it works perfectly with the test input in your question. So I'm assuming that what you did was something like this:

$ bison -d -o que.tab.c que.y
$ flex -o que.lex.c que.l
$ gcc -o que que.tab.c que.lex.c
$ ./que
dadof(arturo,armando)

And then you waited to see what happened. But nothing happened, because your program was still waiting for you to enter more input.

Or perhaps you terminated your program by typing Ctrl-C. As before, your program was still waiting for input, so it hasn't attempted to print anything yet. Control-C immediately kills the running program. Bang, dead. No opportunity to clean up, print any final result, nothing. Dramatic, yes, but sometimes you need to do that. Not in this case.

If you put the line dadof(arturo,armando) into a file and run the program with that file as input, you'll get the more or less expected output:

$ echo "dadof(arturo,armando)" > test.txt
$ ./que < test.txt

(Hecho)$

If you want to type the input from the console, you need to tell the program that the input is finished by typing Ctrl-Z Enter(on Windows) or Ctrl-D (on Linux/Mac). (You must type that at the beginning of a line, by the way.) Then you'll see the same output as above.

That output does show a couple of the problems with your code:

  1. Since none of your patterns recognises a newline character ( \n ), the Flex scanner handles that case with the default rule. The default rule is to write the unrecognised character to standard output and then continue looking for a token. That's why there is an unexpected newline before the ´(Hecho)´. In a parser, you hardly ever want to trigger the default lex action; I suggest disabling the default using option nodefault , which will cause flex to print a warning if you've missed some character. To avoid that happening, use the pattern .|\n instead of . as your final fallback rule, and/or make sure that you explicitly handle newlines. (You could have used [[:space:]] instead of [[:blank:]] , for example.)

  2. You print (Hecho) with printf("(Hecho)"); . That doesn't print a newline and your program then returns control to the shell. Consequently the shell prompt is printed immediately after your message, which is hard to read. You should always remember to end all output lines with a \n .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM