簡體   English   中英

如何在flex-lexer中使用GNU readline?

[英]How to use GNU readline with flex-lexer?

我認為使用GNU Readline庫進行命令行提示很好,我想要我正在使用的shell的功能。 現在readline適合我(我的環境是CLion,CMake,Ubuntu,BSD,C,flex-lexer和lemon-parser)但是我還需要flex和yacc同時工作來掃描和解析輸入,但代碼似乎“不相容” - 他們真的嗎?

    params[0] = NULL;
   printf("> ");

    i=1;
    do {
        lexCode = yylex(scanner);

        /*  snprintf(shell_prompt, sizeof(shell_prompt), "%s:%s $ ", getenv("USER"), getcwd(NULL, 1024));
         Display prompt and read input (NB: input must be freed after use)...*/



        text = strdup(yyget_text(scanner));
        /*
        input = readline(text);

        if (!input)
            break;

        add_history(input);

        free(input);*/
        printf("lexcode %i Text %s\n", lexCode, text);
        if (lexCode == 4) {
            params[i++] = mystring;
            if (strcmp(text, "\'\0")) {
                params[i++] = mystring;
            }
        } else
        if (lexCode != EOL) {
                params[i++] = text;
                printf("B%s\n", text);
        }
        Parse(shellParser, lexCode, text);
        if (lexCode == EOL) {
            dump_argv("Before exec_arguments", i, params);
            exec_arguments(i, params);
            corpse_collector();
            Parse(shellParser, 0, NULL);
            i=1;
        }
    } while (lexCode > 0);
    if (-1 == lexCode) {
        fprintf(stderr, "The scanner encountered an error.\n");
    }

上面的代碼有解析和掃描工作,並注釋掉readline功能,如果我想同時使用它們將無法工作。 我可以讓它運作嗎?

閱讀GNU readline的文檔。 閱讀tty揭秘頁面。 只有當你的stdin是tty時你才會想要使用readline ,所以使用isatty(3) isatty(STDIN_FILENO)來檢測它。

使用readline的shell的基本行為就是使用

char *readline (const char *prompt);

功能。 因此,您希望調整解析器以從緩沖區讀取,而不是從stdin讀取。 這是通常的做法。 不要忘記測試(防止失敗)對readline的調用並在完成后free生成的緩沖區。

然后,您想要添加一些完成 那是困難的部分。 看看其他貝殼( zshbashfish ......)正在做什么,至少是為了靈感。 請注意,默認文件名完成可能就足夠了,至少在啟動時是這樣。

順便說一下,我不會同時使用檸檬野牛來解析相同的輸入。 實際上,對於shell(因為它的語法很簡單),我只會使用一些手寫的遞歸下降解析器

flex + readline示例

繼快速柔性“空殼”,它只是可以lsdate

%{
  #include <stdlib.h>
  #include <readline/readline.h>
  #include <readline/history.h>
  #define YY_INPUT(buf,result,max_size) result = mygetinput(buf, max_size);

  static int mygetinput(char *buf, int size) {
    char *line;
    if (feof(yyin))  return YY_NULL;
    line = readline("> ");
    if(!line)        return YY_NULL;
    if(strlen(line) > size-2){
       fprintf(stderr,"input line too long\n"); return YY_NULL; }
    sprintf(buf,"%s\n",line);
    add_history(line);
    free(line);
    return strlen(buf);
  }   
%}

%option noyywrap    
%%
ls.*         system(yytext);
date.*       system(yytext);
.+           fprintf(stderr, "Error: unknown comand\n");
[ \t\n]+     {}
%%

建立它:

flex mysh.fl
cc -o mysh lex.yy.c -lreadline -lfl

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM