package shuntingyard import "core:container/queue" import "../lex" import syn "../syntax-tree/" shunting_yard :: proc(tokens: []syn.TOKEN) -> []syn.TOKEN { ast := make([dynamic]syn.TOKEN) operator_stack := &queue.Queue(syn.TOKEN){} queue.init(operator_stack) for token in tokens { #partial switch token.type { case syn.TOKEN_TYPE.NUMBER: append(&ast, token) case syn.TOKEN_TYPE.OPERATOR: if queue.len(operator_stack^) == 0 { queue.push_back(operator_stack, token) continue } current_token_importance := get_operator_importance(token) for queue.len(operator_stack^) != 0 { last_token := queue.peek_back(operator_stack) last_token_importance := get_operator_importance(last_token^) // If operators importance is lower than the last ones on the stack (or equal) // and operator is not ^, pop last operator from stack to ast if current_token_importance <= last_token_importance { append(&ast, queue.pop_back(operator_stack)) } else { //append(&ast, token) queue.push_back(operator_stack, token) break } } if queue.len(operator_stack^) == 0 { queue.push_back(operator_stack, token) } case syn.TOKEN_TYPE.OPEN_PARENTHESIS: queue.push_back(operator_stack, token) case syn.TOKEN_TYPE.CLOSE_PARENTHESIS: for queue.peek_back(operator_stack).type != syn.TOKEN_TYPE.OPEN_PARENTHESIS { append(&ast, queue.pop_back(operator_stack)) } queue.pop_back(operator_stack) } } for queue.len(operator_stack^) != 0 { append(&ast, queue.pop_back(operator_stack)) } return ast[:] } get_operator_importance :: proc(operator: syn.TOKEN) -> int { switch operator.value { case syn.OPERATOR_TYPE.DIVIDE, syn.OPERATOR_TYPE.MULTIPLY: // Numbers taken from Wikipedia return 3 case syn.OPERATOR_TYPE.MINUS, syn.OPERATOR_TYPE.PLUS: return 2 } return 0 }