Skip to content

Commit

Permalink
COTOHA APIのレスポンスを利用した実行の追加
Browse files Browse the repository at this point in the history
  • Loading branch information
k-muney committed Mar 14, 2020
1 parent 5d02187 commit 287c74e
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 4 deletions.
1 change: 1 addition & 0 deletions package.json
Expand Up @@ -140,6 +140,7 @@
"node-fetch": "^2.5.0",
"opener": "^1.5.1",
"readline-sync": "^1.4.9",
"request": "^2.88.2",
"sendkeys-js": "0.0.4",
"caniuse-db": "^1.0.30001027"
}
Expand Down
6 changes: 4 additions & 2 deletions src/cnako3.js
Expand Up @@ -39,6 +39,7 @@ class CNako3 extends NakoCompiler {
.option('-s, --silent', 'サイレントモードの指定')
.option('-l, --repl', '対話シェル(REPL)の実行')
.option('-m, --man [command]', 'マニュアルを表示する')
.option('-C, --cotoha', 'ことはのレスポンスを使用する')
// .option('-h, --help', '使い方を表示する')
// .option('-v, --version', 'バージョンを表示する')
.parse(process.argv)
Expand All @@ -47,7 +48,7 @@ class CNako3 extends NakoCompiler {

/**
* コマンドライン引数を解析
* @returns {{debug: boolean, compile: any | boolean, test: any | boolean, one_liner: any | boolean, debugAll: any, run: any | boolean, repl: any | boolean, source: any | string}}
* @returns {{debug: boolean, compile: any | boolean, test: any | boolean, one_liner: any | boolean, debugAll: any, run: any | boolean, repl: any | boolean, source: any | string, cotoha: boolean}}
*/
checkArguments () {
const app = this.registerCommands()
Expand All @@ -58,6 +59,7 @@ class CNako3 extends NakoCompiler {
this.debugParser = true
this.debugJSCode = true
}
this.cotoha = app.cotoha || false
let args = {
'compile': app.compile || false,
'run': app.run || false,
Expand All @@ -71,7 +73,7 @@ class CNako3 extends NakoCompiler {
}
args.mainfile = app.args[0]
args.output = app.output
if (/\.(nako|nako3|txt|bak)$/.test(args.mainfile)) {
if (/\.(nako|nako3|txt|bak|json)$/.test(args.mainfile)) {
if (!args.output) {
if (args.test) {
args.output = args.mainfile.replace(/\.(nako|nako3)$/, '.spec.js')
Expand Down
86 changes: 86 additions & 0 deletions src/cotoha_request.js
@@ -0,0 +1,86 @@
const request = require('request');
const fs = require('fs-extra');

const DEVELOPER_API_BASE_URL = "https://api.ce-cotoha.com/api/dev/";
const ACCESS_TOKEN_PUBLISH_URL = "https://api.ce-cotoha.com/v1/oauth/accesstokens";
const CLIENT_ID = "gkMVspYQsAh4MZSyMOBoDtZrioZGq4qZ";
const CLIENT_SECRET = "7OIpNdd93FTP8gdW";

This comment has been minimized.

Copy link
@massongit

massongit Mar 16, 2020

クレデンシャルがコミットされているようです。
アカウントの悪用を防ぐため、消されることをお勧めします。


const main = async () => {
let accessToken = await getAccessToken();
document = fs.readFileSync(process.argv[2], 'utf-8');
let ret = [];
let sentences = document.split('。').map(s => s.trim()).filter(s => s);
for (let i = 0; i < sentences.length; i++) {
let parse = await getParse(accessToken, sentences[i]);
ret.push({ id: i, chunks: parse });
await sleep(1000);
};
fs.writeFileSync(`${process.argv[2]}.kotoha.json`, JSON.stringify(ret, null, ' '));
}

const sleep = delay => new Promise(resolve => setTimeout(resolve, delay));

const getAccessToken = () => {
return new Promise((resolve, reject) => {
request(
{
url: ACCESS_TOKEN_PUBLISH_URL,
method: 'POST',
headers: { 'Content-Type': 'application/json' },
json: {
grantType: "client_credentials",
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
},
},
(error, response, body) => {
if (!error && (response.statusCode === 200 || response.statusCode === 201)) {
if (typeof body !== 'object') body = JSON.parse(body);
resolve(body.access_token);
} else {
if (error) {
console.log(`request fail. error: ${error}`);
} else {
console.log(`request fail. response.statusCode: ${response.statusCode}, ${body}`);
}
reject(body);
}
},
);
});
}

const getParse = (accessToken, sentence) => {
return new Promise((resolve, reject) => {
request(
{
url: `${DEVELOPER_API_BASE_URL}nlp/v1/parse`,
method: 'POST',
headers: { 'Content-Type': 'application/json;charset=UTF-8', Authorization: `Bearer ${accessToken}`},
json: { sentence: sentence },
},
(error, response, body) => {
if (!error && (response.statusCode === 200 || response.statusCode === 201)) {
if (typeof body !== 'object') body = JSON.parse(body);
if (body.status === 0) {
resolve(body.result);
} else {
console.log(`request fail. error: ${body.message}`);
reject(body);
}
} else {
if (error) {
console.log(`request fail. error: ${error}`);
} else {
msg = (typeof body !== 'object') ? body : JSON.stringify(body);
console.log(`request fail. response.statusCode: ${response.statusCode}, ${msg}`);
}
reject(body);
}
}
);
});
}

main();
8 changes: 6 additions & 2 deletions src/nako3.js
Expand Up @@ -59,7 +59,11 @@ class NakoCompiler {
*/
tokenize (code, isFirst, line = 0) {
const code2 = this.prepare.convert(code)
return this.lexer.setInput(code2, isFirst, line)
if (this.cotoha) {
return this.lexer.setInputCotoha(code2, isFirst, line)
} else {
return this.lexer.setInput(code2, isFirst, line)
}
}

/**
Expand Down Expand Up @@ -126,7 +130,7 @@ class NakoCompiler {
console.log(JSON.stringify(tokens, null, 2))
}
// 構文木を作成
const ast = parser.parse(tokens)
const ast = this.cotoha ? parser.parseCotoha(tokens) : parser.parse(tokens)
if (this.debug && this.debugParser) {
console.log('--- ast ---')
console.log(JSON.stringify(ast, null, 2))
Expand Down
81 changes: 81 additions & 0 deletions src/nako_lexer.js
Expand Up @@ -62,6 +62,87 @@ class NakoLexer {
return this.result
}

// 不要なtokenの削除と、chunk/token間の結合を行う
setInputCotoha (code, isFirst, line) {
// 暫定でlineは全て0を入れる
const json = JSON.parse(code)
for (const sentence of json) {
let resultSentence = [];
for (const chunk of sentence.chunks) {
if (chunk.tokens.find ( token => token.features.includes('開括弧'))) {
// 開括弧から閉括弧までを文字列リテラルとする。
const values = []
let stringFlg = false
for (const token of chunk.tokens) {
if (stringFlg) {
if (token.features.includes('閉括弧')) {
break
} else {
values.push(token.form)
}
} else {
if (token.features.includes('開括弧')) {
stringFlg = true
}
}
}
resultSentence.push({ id: chunk.chunk_info.id, type: "string", value: values.join(''), links: chunk.chunk_info.links, line: 0 })
} else {
let token = chunk.tokens.find ( token => token.pos === '動詞語幹');
if (token) {
resultSentence.push({ id: chunk.chunk_info.id, type: "func", value: token.lemma, links: chunk.chunk_info.links, line: 0 })
continue
}
token = chunk.tokens.find ( token => token.features.includes('動作'));
if (token) {
if (token.dependency_labels && token.dependency_labels.some( d => {
const dependency_token = chunk.tokens.find( token => token.id === d.token_id)
return dependency_token && dependency_token.pos === '動詞接尾辞'
})) {
resultSentence.push({ id: chunk.chunk_info.id, type: "func", value: token.lemma, links: chunk.chunk_info.links, line: 0 })
continue
}
}
token = chunk.tokens.find ( token => ['名詞', '独立詞'].includes(token.pos))
if (token) {
if (chunk.chunk_info.head >= 0) {
const head_chunk = sentence.chunks.find(tmp_chunk => tmp_chunk.chunk_info.id === chunk.chunk_info.head)
if (head_chunk) {
let link = head_chunk.chunk_info.links.find(link => link.link === chunk.chunk_info.id)
if (link && link.label === "adjectivals") {
continue
}
}
}
let value = ''
chunk.chunk_info.links.filter( link => link.label === 'adjectivals').forEach( link => {
const joinChunk = sentence.chunks.find( chunk => chunk.chunk_info.id === link.link)
value += joinChunk.tokens.map( token => token.form ).join('')
})
for (const token of chunk.tokens) {
if (['名詞', '独立詞','名詞接尾辞'].includes(token.pos)) {
value += token.form
} else {
if (value) {
break;
}
}
}
resultSentence.push({ id: chunk.chunk_info.id, type: "word", value: value, links: chunk.chunk_info.links, line: 0 })
continue
}
token = chunk.tokens.find ( token => ['Number'].includes(token.pos))
if (token) {
resultSentence.push({ id: chunk.chunk_info.id, type: "number", value: Number(token.lemma), links: chunk.chunk_info.links, line: 0 })
continue
}
}
}
this.result.push(resultSentence)
}
return this.result
}

preDefineFunc (tokens) {
// 関数を先読みして定義
let i = 0
Expand Down
36 changes: 36 additions & 0 deletions src/nako_parser3.js
Expand Up @@ -7,6 +7,42 @@ const operatorList = []
for (const key in opPriority) {operatorList.push(key)}

class NakoParser extends NakoParserBase {
parseCotoha (tokens) {
this.reset()
this.tokens = tokens
let ret = {
type: "block",
block: [],
}
for (const token of tokens) {
for (const chunk of token) {
if (["string", "word", "number"].includes(chunk.type)) {
if (chunk.links) {
let link = chunk.links.find( link => link.label === "agent")
if (link) {
let arg = token.find(chunk => chunk.id === link.link)
if (arg) {
ret.block.push({
type: "let",
name: { type: arg.type, value: arg.value, josi: "", line: 0 },
value: { type: chunk.type, value: chunk.value, josi: "", line: 0 }
})
}
}
}
} else if (chunk.type === "func") {
ret.block.push({
type: "func", name: chunk.value, line: 0, args: chunk.links.map(link => {
let arg = token.find(chunk => chunk.id === link.link)
return { type: arg.type, value: arg.value, label: link.label }
})
})
}
}
}
return ret
}

/**
* @param tokens 字句解析済みのトークンの配列
* @return {{type, block, line}} AST(構文木)
Expand Down

0 comments on commit 287c74e

Please sign in to comment.