choco-algorithm
Version:
Algorithm runtime emulator, like a IDE
284 lines (257 loc) • 8.65 kB
JavaScript
import _ from 'lodash'
import store from '../stores'
import { variables as vars } from '../actions'
import { algorithm_word, begin, end, to_word, tokens, variables,
transpiler, open_bracket, close_bracket, write, read, type
} from './i18n'
var algorithm = new class {
constructor () {
this.store = {
var_add : (value, key) => store.dispatch(vars.add(value, key)),
var_reset : () => store.dispatch(vars.reset())
}
}
// transform to javascript
to_js () {
this.store.var_reset()
this.js = ''
const content = array => _.map(array, value => value.content)
const join = array => _.join(array, '')
// get container result in a var
var _code = this.code = _.flow(
_.reverse,
content,
join
)(store.getState().tabs)
// and execute a interpreter
var title = this.title(_code)
var literals = this.literals()
this.scanner()
var diff = this.diff(_code, literals + this.js)
var map = _.split(_code, '\n')
// show the output
var code = this.js
return { title,
literals,
code,
diff,
map }
// the_console.run(title, literals, this.js, diff, map)
}
// search the title of de algorithm
title (code) {
var line = _.split(code, '\n')
var word = _.split(line[0], ' ')
if (word[0] === algorithm_word && word.length === 2) {
var code_to_return = ''
for (var i = 1; i < line.length; i++)
code_to_return += line[i] + '\n'
this.code = code_to_return
return word[1]
}
else
throw 'name is invalid'
}
literals () {
var literals = this.code.replace(
this.code.match(RegExp(begin + '[\\s\\S]*?' + end + '$', 'gm'))[0], '')
var line = literals.split('\n')
var code = ''
if (variables.indexOf(line[0].split(' ')[0]) !== -1) {
var i = 0
while (line[i]) {
var word = line[i].split(' ')
i++
var j = 0
if (line[i].search('//') !== -1) {
var remove = line[i].substr(line[i].search('//'), line[i].length)
line[i] = line[i].replace(remove, '')
}
while (word[j] || word[j] === '') {
// last test
word[j] = word[j]
.replace(/=/g, ' = ')
.replace(/ /g, '')
.replace(/\t/g, '')
.replace(/,/g, '')
.replace(/:/g, '')
.replace(/\[/g, ' = new Vector(')
.replace(/\]/g, ')')
if (j < word.length - 1) {
if (word[j] !== '')
code += 'var ' + word[j] + ';\n'
word[j] = _.replace(word[j], / =[\s\S]{0,}/, '')
switch (word[word.length - 1]) {
case type.int:
this.store.var_add('int', word[j])
break
case type.double:
this.store.var_add('double', word[j])
break
case type.string:
this.store.var_add('string', word[j])
break
case type.bool:
this.store.var_add('bool', word[j])
break
default:
}
}
j++
}
}
}
else
throw 'variables not exist'
return code
}
diff (code, js) {
let alg = code
.split(/\n/)
let begin_index = 1
while (alg[begin_index].match(RegExp(begin)) === null)
begin_index++
begin_index++
js = js
.split(/\n/)
let js_index = 0
while (/var/.test(js[js_index]))
js_index++
return begin_index - js_index
}
// transform between native languaje and javascipt
scanner () {
// good in this space we are going to make a separation between the code
// and the variables
this.code = this.code.match(RegExp(begin + '[\\s\\S]*?' + end + '$', 'gm'))[0]
// each line is separated into a array
var line = this.code.split('\n')
// the word "fin" is deleted
if (line[line.length - 1].search(end) !== -1)
line.pop()
// reverse the line of array
line.reverse()
// the word "inicio" is deleted
if (line[line.length - 1].search(begin) !== -1)
line.pop()
// reverse the line of array
line.reverse()
// now the transpiler work
for (let i in line) {
// ...
if (line[i].search('//') !== -1) {
var remove = line[i].substr(line[i].search('//'), line[i].length)
line[i] = line[i].replace(remove, '')
}
line[i] = line[i]
.replace(/\(/g, ' (')
.replace(/\)/g, ') ')
.replace(/ {2}/g, ' ')
.replace(/\[/g, '.io(')
.replace(/\]/g, ')')
// vector.io(n).add(value)
while (line[i].match(/\.io\([0-9a-zA-Z]+\)\s+<-\s+[a-zA-Z0-9 ]/)) {
line[i] = line[i].replace(/<-/, '')
let exp = line[i].match(/\S+/g)
line[i] = exp[0] + '.add('
if (isNaN(+exp[1]))
line[i] += '"' + exp[1] + '"'
else
line[i] += exp[1]
line[i] += ')'
}
if (line[i].substr(0, 1) === ' ') {
var length = line[i].length - 1
line[i] = line[i].substr(1, length)
}
length = line[i].length - 1
while (line[i].substr(length, 1) === ' ')
line[i] = line[i].substr(0, length)
if (line[i] === '')
continue
// if (x === y)
for (let i in open_bracket)
if (line[i].match(RegExp('=(.)+' + open_bracket[i])))
line[i] = line[i].replace(/=/g, ' === ')
// for (...)
if (line[i].match(RegExp(`([\\s\\S]+${to_word}[\\s\\S]+)`))) {
var conditions_for = line[i].match(RegExp(`([\\s\\S]+${to_word}[\\s\\S]+)`))[0]
conditions_for = conditions_for.split(to_word)
var ref = line[i].match(RegExp(`([\\s\\S]+${to_word}[\\s\\S]+)`))[0]
ref = ref.split(to_word)
conditions_for[0] += ';'
conditions_for[1] = conditions_for[1].replace('=', '<=')
if (conditions_for[1].search('reversed') === -1)
conditions_for[1] = conditions_for[1].replace(')', '; i++)')
else
conditions_for[1] = conditions_for[1].replace(')', '; i--)')
line[i] = line[i].replace(ref[0], conditions_for[0])
line[i] = line[i].replace(ref[1], conditions_for[1])
line[i] = line[i].replace(to_word, '')
}
// do ... while (!...)
if (line[i].match(RegExp(`${to_word}\\s+([\\s\\S]+)`))) {
line[i] = line[i].replace('(', '(!(')
line[i] = line[i].replace(/\)\s{0,}$/, '))')
line[i] = line[i].replace(/=/g, '===')
}
// each word is separated into a array
var word = line[i].split(' ')
// this loop is to search in various dictionaries, and transform that code
for (let i in word)
// word[i] = word[i].replace(/=/g, ' === ')
// dictionaries of words
// open blackets
if (open_bracket.indexOf(word[i]) !== -1)
this.js += '{ '
// close brackets
else if (close_bracket.indexOf(word[i]) !== -1)
this.js += '}'
else if (transpiler[word[i]])
this.js += transpiler[word[i]] + ' '
// dictionaries of tokens
else if (tokens[word[i]])
this.js += tokens[word[i]] + ' '
// and words not in the dictionary
else
this.js += word[i] + ' '
// this fracment of code delete all space in the start of a line
// with a style like stack, first reverse the array
word.reverse()
// then in space_in_start assign the last element in the stack
var space_in_start = word.pop()
var if_no_have_a_space_in_start = space_in_start
// while it is equal at ""
while (space_in_start === '')
// assign at space_in_start the last element in the stack
space_in_start = word.pop()
// the last element never is ""
if (typeof space_in_start === 'undefined')
word.push(if_no_have_a_space_in_start)
else
word.push(space_in_start)
// and reverse the array again to finish
word.reverse()
var last_line = this.js.split('\n')[this.js.split('\n').length - 1]
if (last_line.search('{') !== -1 || last_line.search('}') !== -1)
this.js += '\n'
else if (write.indexOf(word[0]) !== -1) {
this.js = this.js.replace(
write[write.indexOf(word[0])],
'eval(write('
)
this.js += '));\n'
}
else if (read.indexOf(word[0]) !== -1) {
this.js = this.js.replace(
read[read.indexOf(word[0])],
'eval(read("'
)
this.js += '"));\n'
}
else
this.js += ';\n'
}
}
}
export default algorithm