Skip to content

HyeonuPark/Lewis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

27 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lewis

Syntax agnostic compiler framework

Build Status

Heavily W.I.P. yet!

Usage

  1. Define your AST spec
// spec.js

import lewis from 'lewis'

const {define, buildSpec} = lewis()

define('Program', [
  {
    name: 'body',
    type: 'Expression',
    isArray: true
  }
])

define('Expression')

define('StringLiteral', [
  {
    name: 'content',
    type: 'string',
    visitable: false
  }
], {
  alias: 'Expression'
})

define('Identifier', [
  {
    name: 'name',
    type: 'string',
    visitable: false
  }
], {
  alias: 'Expression'
})

define('FunctionCall', [
  {
    name: 'callee',
    type: 'Expression'
  },
  {
    name: 'arguments',
    type: 'Expression',
    isArray: true
  }
], {
  alias: 'Expression'
})

export const {types, loadAst} = buildSpec()
  1. Build your AST data
// ast.js

import {types as t} from './spec'

//
// println("hello, world!")
// printf("my name is {}", name)
//

export const data = t.Program([
  t.FunctionCall(t.Identifier('println'), [
    t.StringLiteral('hello, world!')
  ]),
  t.FunctionCall(t.Identifier('printf'), [
    t.StringLiteral('my name is {}'),
    t.Identifier('name')
  ])
])

// ast data made with Lewis is a plain JSON-able object
console.log(JSON.stringify(data, null, 2))
  1. Load node object from AST data, and traverse it
// traverse.js

import {data} from './ast'
import {types as t, loadAst} from './spec'

function isCapitalized (str) {
  const first = str[0]
  return first.toUpperCase() === first
}

const rootNode = loadAst(data)

const capitalized = rootNode.traverse({
  StringLiteral (node) {
    const content = node.get('content').unwrap()

    if (!isCapitalized(content)) {
      return t.StringLiteral(content[0].toUpperCase() + content.slice(1))
    }
  },
  Identifier (node) {
    const name = node.get('name').unwrap()

    if (!isCapitalized(name)) {
      return t.Identifier(name[0].toUpperCase() + name.slice(1))
    }
  }
})

const code = capitalized.convert({
  Program (node) {
    return node.get('body').join('\n')
  },
  StringLiteral (node) {
    return `"${node.get('content')}"`
  },
  Identifier (node) {
    return node.get('name')
  },
  FunctionCall (node) {
    return `${node.get('callee')}(${node.get('arguments').join(', ')})`
  }
})

console.log(code)
// result:
//
// Println("Hello, world!")
// Printf("My name is {}", Name)

Milestone

  • Factory
  • Node
  • Convert
  • Traverse
  • Scope

About

Syntax agnostic compiler framework

Resources

License

Stars

Watchers

Forks

Packages

No packages published