no-context / moo

Optimised tokenizer/lexer generator! 🐄 Uses /y for performance. Moo.
BSD 3-Clause "New" or "Revised" License
830 stars 66 forks source link

Accept objects in moo() function? #7

Closed nathan closed 7 years ago

nathan commented 7 years ago

It seems easier to write this:

const factory = moo({
  ws:      /[ \t]+/,
  comment: /\/\/.*?$/,
  number:  /(0|[1-9][0-9]*)/,
  string:  /"((?:\\["\\]|[^\n"\\])*)"/,
  lparen:  '(',
  rparen:  ')',
  keyword: ['while', 'if', 'else', 'moo', 'cows'],
  nl:      /\n/,
})

than this:

const factory = moo([
  ['ws',      /[ \t]+/],
  ['comment', /\/\/.*?$/],
  ['number',  /(0|[1-9][0-9]*)/],
  ['string',  /"((?:\\["\\]|[^\n"\\])*)"/],
  ['lparen',  '('],
  ['rparen',  ')'],
  ['keyword', ['while', 'if', 'else', 'moo', 'cows']],
  ['nl',      /\n/],
])

(object iteration order is de facto guaranteed for non-integer keys)

tjvr commented 7 years ago

object iteration order is de facto guaranteed

Is it really? I thought that was implementation-defined.

If not, that would indeed be much nicer. :-)

nathan commented 7 years ago

implementation-defined

Technically, yes—the spec doesn't define an iteration order for for-in loops. Realistically, all engines iterate Object keys in creation order, as long as they are not 32-bit-integer-like (which V8 handles specially)—see the rather extensive discussion here.

EDIT: Actually, for ordinary objects [[OwnPropertyKeys]] returns non-integer own property String keys in creation order. So when you call Reflect.ownKeys or Object.getOwnPropertyNames (but not Object.keys) you get the correct order. for-in loops are terrible anyway.