import { AbstractSyntaxTree } from '../../ast/ast' ; import { TokenHelper } from '../../token/token.helper' ; import { Token } from '../../token/token' ; import { TreeError } from '../tree.error' ; import { ParserError } from '../../error' ; import { TreeBuilderBase } from '../tree.base' ; import { Node , Operand , Tree , Value , ValueObject } from './type' ; export class TreeBuilder extends TreeBuilderBase < Tree > { public makeTree ( ast ) { if ( ! ast ) throw new ParserError ( TreeError . emptyAst ) ; const tree = this . makeNode ( ast ) ; if ( ! TreeBuilder . isValid ( tree ) ) throw new ParserError ( TreeError . invalidParserTree ) ; return < Tree > tree ; } public makeAst ( tree ) { if ( ! tree ) throw new ParserError ( TreeError . emptyTree ) ; const ast = this . makeAstNode ( tree ) ; if ( ! ast . isValid ( ) ) throw new ParserError ( TreeError . invalidParserTree ) ; return ast ; } private makeNode ( node ) { if ( ! node ) return undefined ; return node . type === Token . Type . Operator ? this . makeOperatorNode ( node ) : this . makeValueNode ( node ) ; } private makeOperatorNode ( sourceNode ) { return { operator : sourceNode . value , operand1 : this . makeNode ( sourceNode . leftNode ) , operand2 : this . makeNode ( sourceNode . rightNode ) } ; } private makeValueNode ( sourceNode ) { return { value : this . makeOperandValue ( sourceNode ) } ; } private makeOperandValue ( sourceNode ) { const type = TokenHelper . isObject ( sourceNode . value ) ? 'item' : 'unit' ; return { type , [ type ] : sourceNode . value } ; } private makeAstNode ( node ) { if ( ! node ) return undefined ; if ( TreeBuilder . isTree ( node ) ) { const tree = node as Tree ; const ast = new AbstractSyntaxTree ( tree . operator ) ; ast . leftNode = this . makeAstNode ( tree . operand1 ) ; ast . rightNode = this . makeAstNode ( tree . operand2 ) ; return ast ; } const operand = < Operand > node ; return new AbstractSyntaxTree ( TreeBuilder . getValue ( operand ) ) ; } private static isTree ( node ) { return ! ! ( < Tree > node ) . operator ; } private static getValue ( operand ) { if ( ! TreeBuilder . isValidOperand ( operand ) ) throw new ParserError ( TreeError . invalidParserTree ) ; return operand . value . type === 'item' ? operand . value . item : operand . value . unit ; } private static isValid ( node ) { const tree = < Tree > node ; const operand = < Operand > node ; return ! ! ( tree . operator && tree . operand1 && tree . operand2 ) || operand . value !== undefined ; } private static isValidOperand ( operand ) { return operand && operand . value && operand . value . type && ( < any > operand . value ) [ operand . value . type ] !== undefined ; } }