diff --git a/src/index.civet b/src/index.civet index 1787c12..285ccc1 100644 --- a/src/index.civet +++ b/src/index.civet @@ -1,6 +1,7 @@ moo from ../deps/moo.js +import type {Lexer, Token} from ../deps/moo.d.ts -type Tree = {[key:string]: string | Tree} +type Tree = {[key:string]: (string | Tree)[]} lexer := moo.compile comment: /#.*?$/ @@ -20,27 +21,66 @@ lexer := moo.compile oparen: '(' cparen: ')' -export function tree97(vrml1: string): Tree - tree: Tree := {} - for tok, index of lexer.reset vrml1 - if tok.type and tok.type !== 'whitespace' and tok.type !== 'comment' - tree[`${index}`] = {tok.type, tok.value} +export function tree97(vrml1: string) + parse lexer.reset vrml1 + +// separatorIgnore := +// 'TextureCoordinate Normal Coordinate Texture Material'.split(' ') + +function filtered(stream: Lexer): Token | undefined + result .= stream.next() + while result and (result.type === 'whitespace' or result.type === 'comment') + result = stream.next() + result + +function parse(stream: Lexer, tree: Tree = {}): Tree + deferred: Token[] := [] + held .= filtered stream // for lookahead + + while next := filtered stream + unless held break + switch data := + {nt: next.type, nv: next.value, ht: held.type, hv: held.value} + {ht: 'word', nt: 'obrace'} + switch held.value + /(?:Transform)?Separator/ + {children, ...context} := tree + subTree := parse(stream, context) +// separatorIgnore.map((prop) => subTree.delete prop) // unneeded? + if newKids := subTree.children + if 'children' not in tree then tree.children = [] + tree.children.push(` + Transform { children [ + ${renderList newKids} + ] }`) + /Group|Switch|WWWAnchor/ + {children, ...context} := tree + subTree := parse(stream, context) + if newKids := subTree.children + if 'children' not in tree then tree.children = [] + tree.children.push(` + Group { children [ + ${renderList newKids} + ] }`) + held = filtered stream + {ht: 'word', hv: 'vertexOrdering', nt: 'word', nv: 'COUNTERCLOCKWISE'} + tree.vertexOrdering = ['ccw'] + held = filtered stream + else + console.log 'How did I end up with held', held, 'and next', next + unless held and held.type === 'cbrace' + console.log 'Oddly ended up with held', held tree function render(t: string | Tree): string if typeof t is 'string' return t - result .= '' - for item of Object.values t - if typeof item is 'string' then result += item + ' ' - else - typ := item.type - result += render(typ) - if typeof typ === 'string' and - ['cbrace', 'cbracket', 'cparen'].includes(typ) - result += "\n" - else result += ' ' - result + return .= '' + for prop in t + return.value += ` ${prop}: ${renderList t[prop]}\n` + +function renderList(l: (string | Tree)[]): string + l.map(render).join(' ') export function convert(vrml1: string): string render tree97 vrml1