git @ Cat's Eye Technologies yoob.js / master src / yoob / sexp-parser.js
master

Tree @master (Download .tar.gz)

sexp-parser.js @masterraw · history · blame

/*
 * This file is part of yoob.js version 0.9
 * Available from https://github.com/catseye/yoob.js/
 * This file is in the public domain.  See http://unlicense.org/ for details.
 */
if (window.yoob === undefined) yoob = {};

/*
 * A simple S-expression parser.  Note that it produces yoob.Trees rather
 * than cons cells (pairs), so parsing "(a b c)" will yield a single yoob.Tree
 * node with three children.
 *
 * Note also that atomic symbols are restricted to alphanumeric characters.
 *
 * This module requires that you load yoob.Tree and yoob.Scanner first.
 *
 * This module is really intended more for you to copy and modify (and maybe
 * extend into a parser for a more complex language) than to use directly.
 */
yoob.SexpParser = function() {
    this.scanner = undefined;

    this.init = function(text) {
        this.scanner = (new yoob.Scanner()).init({
          table: [
            ['paren',  "^(\\(|\\))"],
            ['atom',   "^([a-zA-Z]\\w*)"]
          ]
        });
        this.scanner.reset(text);
    };

    /*
     * SExp ::= Atom | "(" {SExpr} ")".
     */
    this.parse = function(text) {
        if (this.scanner.onType('atom')) {
            var x = this.scanner.token;
            this.scanner.scan();
            return (new yoob.Tree('atom')).setValue(x);
        } else if (this.scanner.consume('(')) {
            var children = []
            while (!this.scanner.on(')') && !this.scanner.onType('EOF')) {
              children.push(this.parse());
            }
            this.scanner.expect(')');
            return new yoob.Tree('list', children);
        } else {
            /* TODO: register some kind of error */
            this.scanner.scan();
        }
    };
};