Source: syntaxtree.js

/**
 * This is an object containing semantic actions for the Starling grammar.
 *
 * https://ohmjs.org/docs/api-reference#semantic-actions
 *
 * @constant
 */
const actions = {
  Database (stmts) {
    return stmts.children.map((c) => c.makeAST())
  },

  Import_stmt (one, two, name, three, four) {
    return { field: 'import_stmt', value: name.sourceString }
  },
  Const (one, list, semicolon) {
    const stringConsts = list.asIteration().children.map((c) => c.sourceString)
    return { field: 'constant_stmt', value: stringConsts }
  },
  Variable (one, list, three) {
    const childAST = list.makeAST()
    return childAST
  },
  VariableListItem (variable, two, type) {
    const vari = variable.sourceString
    const typ = type.sourceString
    return { field: 'variable-stmt', variable: vari, type: typ }
  },
  Axiom (one, stmt, three, type, five) {
    const axiomatic = stmt.sourceString
    const typ = type.sourceString

    return { field: 'axiom', statement: axiomatic, type: typ }
  },
  Theorem (statement, three, type, four) {
    const stmt = statement.asIteration().children.map((c) => c.sourceString)
    const ind = stmt.indexOf('axiom')
    const typ = type.sourceString

    let fld = 'axiom'

    if (ind > -1) {
      stmt.splice(ind, 1)
    } else {
      fld = 'theorem'
    }
    return { field: fld, statement: stmt, type: typ }
  },
  Essential_hyp (one, assumed, three, type, five) {
    const assumption = assumed.sourceString
    const typ = type.sourceString
    const objet = { field: 'essential-stmt', statement: assumption, type: typ }
    return objet
  },
  Disjoint (one, list, semicolon) {
    return { field: 'disjoint', value: list.sourceString.split(',') }
  },
  To_sub (label, two, inner) {
    const name = label.sourceString
    const a = inner.makeAST()
    return { label: name, inside: a }
  },
  Inner (inside) {
    return inside.makeAST()
  },
  Proof_block (one, thmName, three, arr, five) {
    const theorem = thmName.sourceString
    const prf = arr.asIteration().children.map((c) => c.makeAST())
    return { field: 'proof', value: theorem, proof: prf }
  },
  Proof_cell (name, semicolon) {
    const nameI = name.sourceString
    return nameI
  },
  Block (one, two, list, four) {
    return {
      field: 'block',
      value: list.asIteration().children.map((c) => c.makeAST())
    }
  },
  Block_inner (c) {
    return c
  },
  Block_content (child) {
    return child.makeAST()
  },
  Block_to_sub (label, two, inner) {
    const name = label.sourceString
    return {
      label: name,
      inside: inner.children.map((c) => c.makeAST())
    }
  },
  Replace (one, two, list, four, five) {
    return {
      field: 'replace',
      value: list.asIteration().children.map((c) => c.makeAST())
    }
  },
  ReplaceListItem (star, colon, mm) {
    return { toReplace: star.sourceString, replacement: mm.sourceString }
  },
  _terminal () {},
  _iter (...children) {},
  NonemptyListOf (one, two, three) {},
  singleLineComment (one, two) {
    return 'single_line_comment'
  },
  multiLineComment (one, two, three) {
    return 'multiline_comment'
  }
}

/**
 * This function resolves references in the abstract syntax tree.
 * @param {Array} ast
 * @returns {Array}
 */
function resolveReferences (ast) {
  const labelMap = {}

  ast.forEach((item) => {
    if (item.label) {
      labelMap[item.label] = item
    }
  })

  ast.forEach((item) => {
    if (item.field === 'proof' && typeof item.value === 'string') {
      const label = item.value
      if (labelMap[label]) {
        item.value = labelMap[label]
      }
    }
  })

  return ast
}

export { actions, resolveReferences }