here-be/snapdragon

Prev / next, or offset

tunnckoCore opened this issue ยท 8 comments

app
  .use(function any () {
    var pos = this.position();
    var m = this.match(/^./);
    if (!m) return;
    return pos({
      type: 'any',
      val: m[0]
    });
  })

Idea how from one renderer to get prev and next char? I think offset in position would work for me.

edit: And btw, should mention in readme, that you should be careful with parser plugins order (will show example in other issue).

In the parser, prev would be the last token pushed onto this.nodes. We can't really do next in the parser, but I've thought about refactoring this and adding a lexer so that we can do peek() etc.

In the renderer, I have an idea for how prev and next could be exposed in a useful way (taking child nodes into account, since prev to a "child" node, for example, might not be on the same stack) not sure if that made sense.

is there anything in particular I can help you with?

In the parser, prev would be the last token pushed onto this.nodes.

Yea, in parser that's true. I need them in renderer.

but I've thought about refactoring this and adding a lexer so that we can do peek() etc.

sounds good

is there anything in particular I can help you with?

Just playing to try to parse some json flavor like that

address: street, city,beta, state
or: some, m/ore,    da+ta,here
maybe:
  indented,
  array,
  xxx

foo bar: "ba:z qux"

aa:
  bb: cc dd
  ee: eee wee

nested address:
  obj: foo bar
  location:
    zip: 1437
    city: "sofia, bulgaria"
  state: true

first three lines should be rendered as arrays. Nevermind, when started to thinking it... i need some detection from the renderers.

The thing I personally had the hardest time wrapping my brain around was how to parse/render nested structures. If that's what you're getting at, I can show you that if you want

was how to parse/render nested structures

๐Ÿ‘ when you have time

k, maybe this will help:

function parse(input) {
  var stack = [];
  var ast = [{type: 'root', nodes: []}];

  var len = input.length;
  var idx = -1;
  while (++idx < len) {
    var ch = input[idx];
    var prev = ast[ast.length - 1];

    if (ch === '{') {
      var tok = {
        type: 'brace',
        nodes: [{
          type: 'brace.open',
          val: ch
        }]
      };

      if (stack.length) {
        var last = stack[stack.length - 1];
        last.nodes.push(tok);
      } else {
        prev.nodes.push(tok);
      }

      stack.push(tok);
      continue;
    }

    if (ch === '}') {
      var open = stack.pop();
      if (open.type !== 'brace') {
        throw new Error('missing opening "}"');
      }
      open.nodes.push({
        type: 'brace.close',
        val: ch
      });
      continue;
    }

    if (stack.length) {
      var last = stack[stack.length - 1];
      last.nodes.push({
        type: 'text',
        val: ch
      });
      continue;
    }

    prev.nodes.push({
      type: 'text',
      val: ch
    });
  }

  return ast[0];
}

var ast = parse('foo{bar{baz}qux}fez');
console.log(ast.nodes);

The single most important thing to get out of this is that there are two arrays: ast AND stack. The stack should be empty when parsing is finished. It's main job is to determine two things:

  • if we receive a closing character, was the previous token on the stack an opening character? If not, we know that an opening character is missing.
  • if we receive an opening character, we check to see if the stack has any tokens on it. if it does, that means we're inside a nested structure. So instead of pushing tokens onto the AST, we want to push tokens onto the nodes array of the previous token on the stack.

If you log that out it will make sense pretty quick I think. You learn pretty darn fast lol

Great, thanks!

You learn pretty darn fast lol

Yea.. doh, all in my head last few days is some parsers and tokenizers, and i'm going crazy... hahaha.

I think we have prev and next already with 0.5+?

We only need the offset to position.