Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • Home
  • SEARCH
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6253619
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 24, 20262026-05-24T14:02:00+00:00 2026-05-24T14:02:00+00:00

I’ve written an interpreter for a C-like language, using Flex and Bison for the

  • 0

I’ve written an interpreter for a C-like language, using Flex and Bison for the scanner/parser. It’s working fine when executing full program files.

Now I’m trying implement a REPL in the interpreter for interactive use. I want it to work like the command line interpreters in Ruby or ML:

  1. Show a prompt
  2. Accept one or more statements on the line
  3. If the expression is incomplete
    1. display a continuation prompt
    2. allow the user to continue entering lines
  4. When the line ends with a complete expression
    1. echo the result of evaluating the last expression
    2. show the main prompt

My grammar starts with a top_level production, which represents a single statement in the language. The lexer is configured for interactive mode on stdin. I am using the same scanner and grammar in both full-file and REPL modes, because there’s no semantic difference in the two interfaces.

My main evaluation loop is structured like this.

while (!interpreter.done) {
    if (interpreter.repl)
        printf(prompt);
    int status = yyparse(interpreter);
    if (status) {
        if (interpreter.error)
            report_error(interpreter);
    }
    else {
        if (interpreter.repl)
            puts(interpreter.result);
    }
}            

This works fine except for the prompt and echo logic. If the user enters multiple statements on a line, this loop prints out superfluous prompts and expressions. And if the expression continues on multiple lines, this code doesn’t print out continuation prompts. These problems occur because the granularity of the prompt/echo logic is a top_level statement in the grammar, but the line-reading logic is deep in the lexer.

What’s the best way to restructure the evaluation loop to handle the REPL prompting and echoing? That is:

  • how can I display one prompt per line
  • how can I display the continuation prompt at the right time
  • how can I tell when a complete expression is the last one on a line

(I’d rather not change the scanner language to pass newline tokens, since that will severely alter the grammar. Modifying YY_INPUT and adding a few actions to the Bison grammar would be fine. Also, I’m using the stock Flex 2.5.35 and Bison 2.3 that ship with Xcode.)

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-24T14:02:02+00:00Added an answer on May 24, 2026 at 2:02 pm

    After looking at how languages like Python and SML/NJ handle their REPLs, I got a nice one working in my interpreter. Instead of having the prompt/echo logic in the outermost parser driver loop, I put it in the innermost lexer input routine. Actions in the parser and lexer set flags that control the prompting by input routine.

    I’m using a reentrant scanner, so yyextra contains the state passed between the layers of the interpreter. It looks roughly like this:

    typedef struct Interpreter {
        char* ps1; // prompt to start statement
        char* ps2; // prompt to continue statement
        char* echo; // result of last statement to display
        BOOL eof; // set by the EOF action in the parser
        char* error; // set by the error action in the parser
        BOOL completeLine // managed by yyread
        BOOL atStart; // true before scanner sees printable chars on line
        // ... and various other fields needed by the interpreter
    } Interpreter;
    

    The lexer input routine:

    size_t yyread(FILE* file, char* buf, size_t max, Interpreter* interpreter)
    {
        // Interactive input is signaled by yyin==NULL.
        if (file == NULL) {
            if (interpreter->completeLine) {
                if (interpreter->atStart && interpreter->echo != NULL) {
                    fputs(interpreter->echo, stdout);
                    fputs("\n", stdout);
                    free(interpreter->echo);
                    interpreter->echo = NULL;
                }
                fputs(interpreter->atStart ? interpreter->ps1 : interpreter->ps2, stdout);
                fflush(stdout);
            }
    
            char ibuf[max+1]; // fgets needs an extra byte for \0
            size_t len = 0;
            if (fgets(ibuf, max+1, stdin)) {
                len = strlen(ibuf);
                memcpy(buf, ibuf, len);
                // Show the prompt next time if we've read a full line.
                interpreter->completeLine = (ibuf[len-1] == '\n');
            }
            else if (ferror(stdin)) {
                // TODO: propagate error value
            }
            return len;
        }
        else { // not interactive
            size_t len = fread(buf, 1, max, file);
            if (len == 0 && ferror(file)) {
                // TODO: propagate error value
            }
            return len;
        }
    }
    

    The top level interpreter loop becomes:

    while (!interpreter->eof) {
        interpreter->atStart = YES;
        int status = yyparse(interpreter);
        if (status) {
            if (interpreter->error)
                report_error(interpreter);
        }
        else {
            exec_statement(interpreter);
            if (interactive)
                interpreter->echo = result_string(interpreter);
        }
    }
    

    The Flex file gets these new definitions:

    %option extra-type="Interpreter*"
    
    #define YY_INPUT(buf, result, max_size) result = yyread(yyin, buf, max_size, yyextra)
    
    #define YY_USER_ACTION  if (!isspace(*yytext)) { yyextra->atStart = NO; }
    

    The YY_USER_ACTION handles the tricky interplay between tokens in the language grammar and lines of input. My language is like C and ML in that a special character (‘;’) is required to end a statement. In the input stream, that character can either be followed by a newline character to signal end-of-line, or it can be followed by characters that are part of a new statement. The input routine needs to show the main prompt if the only characters scanned since the last end-of-statement are newlines or other whitespace; otherwise it should show the continuation prompt.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
We're building an app, our first using Rails 3, and we're having to build
I have this code: - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock { NSString *someString = [[NSString
I'm making a simple page using Google Maps API 3. My first. One marker
I have some data like this: 1 2 3 4 5 9 2 6
We are using XSLT to translate a RIXML file to XML. Our RIXML contains
I ran into a problem. Wrote the following code snippet: teksti = teksti.Trim() teksti
Seemingly simple, but I cannot find anything relevant on the web. What is the

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.