이전글에 다 못쓴 내용을 적을려한다
read tokens
case syntax
case 'message'
case 'enum'
case 'option'
enum에서와 token을 읽고, 세미콜론으로 라인을 잡지만, option의 값은 Map일수있기에 onoptionMap을 호출해주는방식으로 Map을 다룬다.
case 'import'
var onimport = function (tokens) {
tokens.shift()
var file = tokens.shift().replace(/^"+|"+$/gm, '')
...
return file
}
파일 경로에서 파일명을 반환
case 'extend'
var onextend = function (tokens) {
var out = {
name: tokens[1],
message: onmessage(tokens)
}
return out
}
확장하려는 타입명을 포함시키고, 필드들에 대해서 얻기위해 onmessage를 사용.
case 'service'
service에는 RPC (Remote Procedure Call) system을 정의하기에
var onservice = function (tokens) {
tokens.shift()
var service = {
name: tokens.shift(),
methods: [],
options: {}
}
if (tokens[0] !== '{') throw new Error('Expected { but found ' + tokens[0])
tokens.shift()
while (tokens.length) {
if (tokens[0] === '}') {
tokens.shift()
// there goes optional semicolon after the enclosing "}"
if (tokens[0] === ';') tokens.shift()
return service
}
switch (tokens[0]) {
case 'option':
var opt = onoption(tokens)
if (service.options[opt.name] !== undefined) throw new Error('Duplicate option ' + opt.name)
service.options[opt.name] = opt.value
break
case 'rpc':
service.methods.push(onrpc(tokens))
break
default:
throw new Error('Unexpected token in service: ' + tokens[0])
}
}
throw new Error('No closing tag for service')
}
읽어내리는 토큰이 rpc인 경우 methods에 rpc 를 추가해주는데 이과정은 onrpc 함수에서 이루어진다.
var rpc = {
name: tokens.shift(),
input_type: null,
output_type: null,
client_streaming: false,
server_streaming: false,
options: {}
}
rpc선언에는 위와 같은 선언요소들이 필요하다.
var onrpc = function (tokens) {
tokens.shift()
var rpc = {
name: tokens.shift(),
input_type: null,
output_type: null,
client_streaming: false,
server_streaming: false,
options: {}
}
if (tokens[0] !== '(') throw new Error('Expected ( but found ' + tokens[0])
tokens.shift()
if (tokens[0] === 'stream') {
tokens.shift()
rpc.client_streaming = true
}
rpc.input_type = tokens.shift()
if (tokens[0] !== ')') throw new Error('Expected ) but found ' + tokens[0])
tokens.shift()
if (tokens[0] !== 'returns') throw new Error('Expected returns but found ' + tokens[0])
tokens.shift()
if (tokens[0] !== '(') throw new Error('Expected ( but found ' + tokens[0])
tokens.shift()
if (tokens[0] === 'stream') {
tokens.shift()
rpc.server_streaming = true
}
rpc.output_type = tokens.shift()
if (tokens[0] !== ')') throw new Error('Expected ) but found ' + tokens[0])
tokens.shift()
if (tokens[0] === ';') {
tokens.shift()
return rpc
}
if (tokens[0] !== '{') throw new Error('Expected { but found ' + tokens[0])
tokens.shift()
while (tokens.length) {
if (tokens[0] === '}') {
tokens.shift()
// there goes optional semicolon after the enclosing "}"
if (tokens[0] === ';') tokens.shift()
return rpc
}
if (tokens[0] === 'option') {
var opt = onoption(tokens)
if (rpc.options[opt.name] !== undefined) throw new Error('Duplicate option ' + opt.name)
rpc.options[opt.name] = opt.value
} else {
throw new Error('Unexpected token in rpc options: ' + tokens[0])
}
}
throw new Error('No closing tag for rpc')
}
지금까지 본과정들을 거치게되면, schema에 .proto의 내용들이 jsonObject형식으로 제공을 받을 수 있다.
protocol-buffers-schema의 parse의 핵심은 tokenize후. tokens를 하나씩인출하며 operaction에 대한 내용에 대해서 파악하는 방식으로, 의미와 무관한 { } [ ] ; 에 제거(무시)하며 읽어가는 과정으로 사람이 순차적으로 읽어나갈떄와 비슷한 과정이라 이해가 어렵진는 않았다.
'개발' 카테고리의 다른 글
userinyerface를 통한 고통 맛보기 Page 2 (3) (2) | 2022.04.20 |
---|---|
userinyerface를 통한 고통 맛보기 Page 2 (2) (0) | 2022.04.19 |
userinyerface를 통한 고통 맛보기 Page 2 (1) (0) | 2022.04.18 |
userinyerface를 통한 고통 맛보기 Page 1 (1) | 2022.04.17 |
protocol-buffers-schema 로 보는 proto 구조 이해하기(1) (0) | 2022.04.15 |