#! /your/favourite/path/to/ruby # -*- mode: ruby; coding: utf-8; indent-tabs-mode: nil; ruby-indent-level: 2 -*- # -*- frozen_string_literal: true; -*- # -*- warn_indent: true; -*- # # Copyright (c) 2017 Urabe, Shyouhei. All rights reserved. # # This file is a part of the programming language Ruby. Permission is hereby # granted, to either redistribute and/or modify this file, provided that the # conditions mentioned in the file COPYING are met. Consult the file for # details. require_relative '../helpers/scanner' json = [] scanner = RubyVM::Scanner.new '../../../insns.def' path = scanner.__FILE__ grammar = %r' (? /[*] [^*]* [*]+ (?: [^*/] [^*]* [*]+ )* / ){0} (? typedef | extern | static | auto | register | struct | union | enum ){0} (? (?: \g | [^{}]+ )* ){0} (? \{ \g* ^ \g $ \g* \} ){0} (? \g | \s ){0} (? [_a-zA-Z] [0-9_a-zA-Z]* ){0} (? (?: \g \g+ )* \g ){0} (? \g \g+ \g | \.\.\. ){0} (? (?# empty ) | void | \g (?: \g* , \g* \g \g* )* ){0} (? \g* // \s* attr \g+ (? \g ) \g+ (? \g ) \g* = \g* (? .+?; ) \g* ){0} (? DEFINE_INSN \g+ (? \g ) \g* [(] \g* (? \g ) \g* [)] \g* [(] \g* (? \g ) \g* [)] \g* [(] \g* (? \g ) \g* [)] \g* ){0} 'x until scanner.eos? do next if scanner.scan(/#{grammar}\g+/o) split = -> (v) { case v when /\Avoid\z/ then [] else v.split(/, */) end } l1 = scanner.scan!(/#{grammar}\g/o) name = scanner["insn:name"] ope = split.(scanner["insn:opes"]) pop = split.(scanner["insn:pops"]) ret = split.(scanner["insn:rets"]) attrs = [] while l2 = scanner.scan(/#{grammar}\g/o) do attrs << { location: [path, l2], name: scanner["pragma:name"], type: scanner["pragma:type"], expr: scanner["pragma:expr"], } end l3 = scanner.scan!(/#{grammar}\g/o) json << { name: name, location: [path, l1], signature: { name: name, ope: ope, pop: pop, ret: ret, }, attributes: attrs, expr: { location: [path, l3], expr: scanner["block"], }, } end RubyVM::InsnsDef = json if __FILE__ == $0 then require 'json' JSON.dump RubyVM::InsnsDef, STDOUT end