Post Reply 
Social Buttons
 
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Hi Ed - what's new with your PL?
07-26-2018, 08:26 PM
Post: #1
Hi Ed - what's new with your PL?
ED
any new things with your programming?
Find all posts by this user
Quote this message in a reply
07-30-2018, 06:24 AM
Post: #2
RE: Hi Ed - what's new with your PL?
Ed
What you think about Early Jay- parser ?
Do you maybe try this type of parser?
Find all posts by this user
Quote this message in a reply
07-30-2018, 09:39 PM (This post was last modified: 07-30-2018 09:40 PM by Ed Davis.)
Post: #3
RE: Hi Ed - what's new with your PL?
(07-26-2018 08:26 PM)Aurel Wrote:  ED
any new things with your programming?

Works keeping me really busy. Maintaining lots of buggy code (written mostly in India), and it isn't the most fun thing in the world :-) But in my little free time, I've started a project or two:

1) A C-subset interpreter, that is a pure interpreter. This one is almost finished. Just need to add a few more operators, mainly '&' (take the address) and '*' (get value at address).

2) An interpreter, same C-subset, but the lexer pre-builds the tokens, and so code is only tokenized once.

3) An interpreter, same C-subset, but interprets via an AST.

4) An interpreter, same C-subset, but have the AST generate byte code, and interpret that via a VM.

Also, another project I started:

1) A simple editor, using a single large buffer.

2) A simple editor, same set of commands, but uses an array of pointers to text strings.

3) A simple editor, same set of commands, but uses a doubly-linked list of text strings.

4) A simple editor, same set of commands, but uses a doubly-linked list of fixed size blocks.

5) A version of (1) that uses buffer-gap.

6) A version of (4) that uses buffer-gap.

Both code-bases run on Windows and Linux.

So how about you? I see you're playing with Klutho's Basic interpreter. Anything else?
Find all posts by this user
Quote this message in a reply
07-30-2018, 09:51 PM
Post: #4
RE: Hi Ed - what's new with your PL?
Quote:So how about you? I see you're playing with Klutho's Basic interpreter. Anything else?

Not to much ,i am also busy with a lot of work and here is so damn hot.
Yes i have plaxing with JimK3 and tweaking Aurel Edit.
subset of C you say...nice
i am interested for version 1.. Smile
but i dont know why you try to build editor from the ground??
By the way do you try to build editor wth Richedit control
with syntax coloring ?
Find all posts by this user
Quote this message in a reply
07-30-2018, 11:19 PM
Post: #5
RE: Hi Ed - what's new with your PL?
(07-30-2018 09:51 PM)Aurel Wrote:  
Quote:So how about you? I see you're playing with Klutho's Basic interpreter. Anything else?

Not to much ,i am also busy with a lot of work and here is so damn hot.
Yes i have plaxing with JimK3 and tweaking Aurel Edit.
subset of C you say...nice
i am interested for version 1.. Smile

Almost done :-)

Quote:but i dont know why you try to build editor from the ground??

Because I can? And it is fun to experiment with different data structures for the text buffer.

Quote:By the way do you try to build editor wth Richedit control
with syntax coloring ?

Nope, everything from scratch, including color syntax highlighting. I built one a while back (started in 1985 or thereabouts), and it was loads of fun. Started on DOS, then OS/2, then Windows, and now Linux. Also had a built-in programming language :-)
Find all posts by this user
Quote this message in a reply
07-30-2018, 11:53 PM
Post: #6
RE: Hi Ed - what's new with your PL?
Quote:Nope, everything from scratch, including color syntax highlighting

With Richedit control is also from scratch.
Ed..thar old ..do yu have windows version?

And this new interpreter - pure...
Is it very different than toy?
Find all posts by this user
Quote this message in a reply
08-01-2018, 04:37 AM (This post was last modified: 08-01-2018 04:46 AM by Ed Davis.)
Post: #7
RE: Hi Ed - what's new with your PL?
(07-30-2018 11:53 PM)Aurel Wrote:  
Quote:Nope, everything from scratch, including color syntax highlighting

With Richedit control is also from scratch.
Ed..thar old ..do yu have windows version?

Yes, but you would not like it. It is old school. Has DOS-like pulldown menus. No tool bar (who needs 'em? Not me). The Windows GUI and the Windows Console and the Dos and the Linux terminal version all look pretty much the same.

No GUI frills. Mainly keyboard driven. While you can use the mouse, it isn't ever necessary.

Has a simple built-in programming language. And of course the old console version of Star Trek (written in the macro language) comes with it :-)

Quote:And this new interpreter - pure...
Is it very different than toy?

Well yes.

The lexer's are pretty similar in both.

However, Toy generates VM code as it parses, and then a VM interprets the generated code.

This new one - can't call it Little C, Small C, Micro C, Pico C, or Tiny C, because all of those names are taken - interprets on the fly, so it is slow.

Toy:

Code:
call parse() 'compiles to VM code as it parses
call run()   'runs the VM interpreter
done

parse()
    next_token()
    switch token
        case if_tok
            gen code for if
        case while_tok
            gen code for if
        ....

run()
    switch opcode
        case op_push
            stack[0] = ....
        ....

New one:

Code:
find offset of all global variables and functions
call call_fun('main')
done

call_fun()
    get offset of function
    handle parameters
    call interpret()

interpret()
    next_token()
    switch token
        case if_tok
            call interpret_if
        case while_tok
            call interpret_while
        ....

A sample "C subset" program:

Code:
/* bubble sort */
void bubblesort(int left, int right, int d[]) {
    int sorted, i, j, new_right, temp;

    for (;;) {
        new_right = 0;

        sorted = 1;
        for (i = left; i < right; ++i) {
            j = i + 1;
            if (d[i] > d[j]) {  /* compare */
                /* swap */
                temp = d[i];
                d[i] = d[j];
                d[j] = temp;
                sorted = 0;
                new_right = i;
            }
        }
        right = new_right;
        /* if no swaps, we're done */
        if (sorted)
            break;
    }
}

int abs(int n) {
    if (n < 0)
        return -n;
    return n;
}

int next = 1;

/* Linear congruential generator - return a pseudo rando number in
   1..range.
  see: https://en.wikipedia.org/wiki/Linear_congruential_generator */
int rnd(int range) {
    next = (next * 1597 + 51749);
    return abs((next % 244944) % range) + 1;
}

/* make sure the array is sorted */
int check(int left, int right, int d[]) {
    for (; left < right; ++left) {
        if (d[left] > d[right]) {
            printf("FAIL: Out of order at %d\n", left);
            return 0;
        }
    }
    printf("Success\n");
    return 1;
}

int main() {
    int a[1000], i;

    /* populate an array with random values */
    for (i = 0; i < 1000; ++i)
        a[i] = rnd(1000);

    bubblesort(0, 999, a);

    check(0, 999, a);
}

(07-30-2018 06:24 AM)Aurel Wrote:  Ed
What you think about Early Jay- parser ?
Do you maybe try this type of parser?

It is appealing, because it can parse all context-free languages.

But it appears to be much more complicated than recursive descent.

So, for me, recursive descent works great, for most stuff. When I get to expressions, I switch to precedence climbing. I spent some time playing with Pratt parsing for expressions, and even for whole programs, but it just didn't click with me, so I went back to recursive descent + precedence climbing.

Results not typical. Your mileage may vary.
Find all posts by this user
Quote this message in a reply
08-01-2018, 08:44 PM
Post: #8
RE: Hi Ed - what's new with your PL?
So ..this new one pure ...
I understand that must be slower than with op_codes but probably
run fast enough for simpler programs.
Find all posts by this user
Quote this message in a reply
08-02-2018, 05:36 AM
Post: #9
RE: Hi Ed - what's new with your PL?
Quote:You've picked a great project - writing interpreters can be lots of fun!

But first, what do we even mean by an interpreter? There are different types of interpreters.

There is the pure interpreter, where you simply interpret each language element as you find it. These are the easiest to write, and the slowest.

A step up, would be to convert each language element into some sort of internal form, and then interpret that. Still pretty easy to write.

The next step, would be to actually parse the language, and generate a syntax tree, and then interpret that. This is somewhat harder to write, but once you've done it a few times, it becomes pretty easy.

Once you have a syntax tree, you can fairly easily generate code for a custom stack virtual machine. A much harder project is to generate code for an existing virtual machine, such as the JVM or CLR.

In programming, like most engineering endeavors, careful planning greatly helps, especially with complicated projects.

So the first step is to decide which type of interpreter you wish to write. If you have not read any of a number of compiler books (e.g., I always recommend Niklaus Wirth's "Compiler Construction" as one of the best introductions to the subject, and is now freely available on the web in PDF form), I would recommend that you go with the pure interpreter.

But you still need to do some additional planning. You need to rigorously define what it is you are going to be interpreting. EBNF is great for this. For a gentile introduction EBNF, read the first three parts of a Simple Compiler at http://www.semware.com/html/compiler.html It is written at the high school level, and should be easy to digest. Yes, I tried it on my kids first :-)

Once you have defined what it is you want to be interpreting, you are ready to write your interpreter.

Abstractly, you're simple interpreter will be divided into a scanner (technically, a lexical analyzer), a parser, and an evaluator. In the simple pure interpolator case, the parser and evaluator will be combined.



You've picked a great project - writing interpreters can be lots of fun!

But first, what do we even mean by an interpreter? There are different types of interpreters.

There is the pure interpreter, where you simply interpret each language element as you find it. These are the easiest to write, and the slowest.

A step up, would be to convert each language element into some sort of internal form, and then interpret that. Still pretty easy to write.

The next step, would be to actually parse the language, and generate a syntax tree, and then interpret that. This is somewhat harder to write, but once you've done it a few times, it becomes pretty easy.

Once you have a syntax tree, you can fairly easily generate code for a custom stack virtual machine. A much harder project is to generate code for an existing virtual machine, such as the JVM or CLR.

In programming, like most engineering endeavors, careful planning greatly helps, especially with complicated projects.

So the first step is to decide which type of interpreter you wish to write. If you have not read any of a number of compiler books (e.g., I always recommend Niklaus Wirth's "Compiler Construction" as one of the best introductions to the subject, and is now freely available on the web in PDF form), I would recommend that you go with the pure interpreter.

But you still need to do some additional planning. You need to rigorously define what it is you are going to be interpreting. EBNF is great for this. For a gentile introduction EBNF, read the first three parts of a Simple Compiler at http://www.semware.com/html/compiler.html It is written at the high school level, and should be easy to digest. Yes, I tried it on my kids first :-)

Once you have defined what it is you want to be interpreting, you are ready to write your interpreter.

Abstractly, you're simple interpreter will be divided into a scanner (technically, a lexical analyzer), a parser, and an evaluator. In the simple pure interpolator case, the parser and evaluator will be combined.

Scanners are easy to write, and easy to test, so we won't spend any time on them. See the aforementioned link for info on crafting a simple scanner.

Lets (for example) define your goto statement:

gotostmt -> 'goto' integer

integer -> [0-9]+

This tells us that when we see the token 'goto' (as delivered by the scanner), the only thing that can follow is an integer. And an integer is simply a string a digits.

In pseudo code, we might handle this as so:

(token - is the current token, which is the current element just returned via the scanner)

loop
if token == "goto"
goto_stmt()
elseif token == "gosub"
gosub_stmt()
elseif token == .....
endloop

proc goto_stmt()
expect("goto") -- redundant, but used to skip over goto
if is_numeric(token)
--now, somehow set the instruction pointer at the requested line
else
error("expecting a line number, found '%s'\n", token)
end
end

proc expect(s)
if s == token
getsym()
return true
end

error("Expecting '%s', found: '%s'\n", curr_token, s)
end

See how simple it is? Really, the only hard thing to figure out in a simple interpreter is the handling of expressions. A good recipe for handling those is at: http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm Combined with the aforementioned references, you should have enough to handle the sort of expressions you would encounter in BASIC.

Ok, time for a concrete example. This is from a larger 'pure interpreter', that handles a enhanced version of Tiny BASIC (but big enough to run Tiny Star Trek :-) )

This text us published on stackoverflow by sammy mitchel

Code:
/*------------------------------------------------------------------------
  Simple example, pure interpreter, only supports 'goto'
------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <setjmp.h>
#include <ctype.h>

enum {False=0, True=1, Max_Lines=300, Max_Len=130};

char *text[Max_Lines+1];    /* array of program lines */
int textp;                  /* used by scanner - ptr in current line */
char tok[Max_Len+1];        /* the current token */
int cur_line;               /* the current line number */
int ch;                     /* current character */
int num;                    /* populated if token is an integer */
jmp_buf restart;

int error(const char *fmt, ...) {
    va_list ap;
    char buf[200];

    va_start(ap, fmt);
    vsprintf(buf, fmt, ap);
    va_end(ap);
    printf("%s\n", buf);
    longjmp(restart, 1);
    return 0;
}

int is_eol(void) {
    return ch == '\0' || ch == '\n';
}

void get_ch(void) {
    ch = text[cur_line][textp];
    if (!is_eol())
        textp++;
}

void getsym(void) {
    char *cp = tok;

    while (ch <= ' ') {
        if (is_eol()) {
            *cp = '\0';
            return;
        }
        get_ch();
    }
    if (isalpha(ch)) {
        for (; !is_eol() && isalpha(ch); get_ch()) {
            *cp++ = (char)ch;
        }
        *cp = '\0';
    } else if (isdigit(ch)) {
        for (; !is_eol() && isdigit(ch); get_ch()) {
            *cp++ = (char)ch;
        }
        *cp = '\0';
        num = atoi(tok);
    } else
          error("What? '%c'", ch);
}

void init_getsym(const int n) {
    cur_line = n;
    textp = 0;
    ch = ' ';
    getsym();
}

void skip_to_eol(void) {
    tok[0] = '\0';
    while (!is_eol())
        get_ch();
}

int accept(const char s[]) {
    if (strcmp(tok, s) == 0) {
        getsym();
        return True;
    }
    return False;
}

int expect(const char s[]) {
    return accept(s) ? True : error("Expecting '%s', found: %s", s, tok);
}

int valid_line_num(void) {
    if (num > 0 && num <= Max_Lines)
        return True;
    return error("Line number must be between 1 and %d", Max_Lines);
}

void goto_line(void) {
    if (valid_line_num())
        init_getsym(num);
}

void goto_stmt(void) {
    if (isdigit(tok[0]))
        goto_line();
    else
        error("Expecting line number, found: '%s'", tok);
}

void do_cmd(void) {
    for (;;) {
        while (tok[0] == '\0') {
            if (cur_line == 0 || cur_line >= Max_Lines)
                return;
            init_getsym(cur_line + 1);
        }
        if (accept("bye")) {
            printf("That's all folks!\n");
            exit(0);
        } else if (accept("run")) {
            init_getsym(1);
        } else if (accept("goto")) {
            goto_stmt();
        } else {
            error("Unknown token '%s' at line %d", tok, cur_line); return;
        }
    }
}

int main() {
    int i;

    for (i = 0; i <= Max_Lines; i++) {
        text[i] = calloc(sizeof(char), (Max_Len + 1));
    }

    setjmp(restart);
    for (;;) {
        printf("> ");
        while (fgets(text[0], Max_Len, stdin) == NULL)
            ;

        if (text[0][0] != '\0') {
            init_getsym(0);
            if (isdigit(tok[0])) {
                if (valid_line_num())
                    strcpy(text[num], &text[0][textp]);
            } else
                do_cmd();
        }
    }
}
Quote:Hopefully, that will be enough to get you started. Have fun!

This looks to me like good example"
Find all posts by this user
Quote this message in a reply
08-02-2018, 12:43 PM
Post: #10
RE: Hi Ed - what's new with your PL?
(08-02-2018 05:36 AM)Aurel Wrote:  This text us published on stackoverflow by sammy mitchel
This looks to me like good example"

It is actually Mitchell. I know that guy pretty well. And yes, it is an ok example.
Find all posts by this user
Quote this message in a reply
Post Reply 


Forum Jump:


User(s) browsing this thread: