Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- module.exports = (tokens) => {
- return parse_scope(tokens, true);
- }
- const parse_scope = (tokens, base) => {
- const processed_tokens = comma_to_semicolon(tokens);
- const lines = get_line_tokens(processed_tokens);
- const actions = lines.map(tokens => parse_line(tokens));
- if(actions.length == 1 && !base) return actions[0];
- else return actions;
- }
- const parse_line = (tokens) => {
- let input_tokens = tokens;
- if(input_tokens[input_tokens.length - 1] == ';') input_tokens.pop(); // remove semicolon at the end
- return parse_expression(input_tokens);
- };
- const parse_expression = (tokens, depth = 0) => {
- // detect if tokens are surrounded by pair of ()
- // for instance: (...(...)) is valid but (...)...(...) is not
- const first_is_valid = tokens[0] == '(';
- let last_is_valid = tokens[tokens.length - 1] == ')', parenthesis_stack = 0;
- for(let i = 0; i < tokens.length; i++){
- let token = tokens[i];
- if(token == '(') parenthesis_stack += 1;
- else if(token == ')') parenthesis_stack -= 1;
- if(token == ')' && parenthesis_stack == 0 && i != tokens.length - 1) last_is_valid = false;
- }
- // console.log(!first_is_valid || !last_is_valid);
- if(!first_is_valid || !last_is_valid){
- // evaluate expression:
- for(operations of order_of_operations){ // loop through each level of order of operations
- let parenthesis_stack = 0;
- let lhs = [], rhs = [], found_operand = null, just_found = false;
- let reverse = operations[0] == '->';
- let maybe_reversed_tokens = tokens.slice(0);
- if(reverse) maybe_reversed_tokens.reverse();
- for(let i = 0; i < maybe_reversed_tokens.length; i++){
- let token = maybe_reversed_tokens[i];
- // ignore stuff in parenthesis
- if(token == '(') parenthesis_stack += 1;
- else if(token == ')') parenthesis_stack -= 1;
- // this loop is inside the token loop because we want all operands in operations to have same precedence, left to right
- for(operand of operations){ // loop through each operand
- if(parenthesis_stack == 0 && token == operand && found_operand == null){
- found_operand = operand;
- just_found = true;
- }
- }
- if(just_found) just_found = false;
- else {
- if(!reverse){
- if(found_operand == null) lhs.push(token);
- else rhs.push(token);
- } else {
- if(found_operand == null) rhs.unshift(token);
- else lhs.unshift(token);
- }
- }
- }
- if(found_operand != null){
- // parse both lhs and rhs
- let parsed_lhs = parse_expression(lhs, depth + 1);
- let parsed_rhs = parse_expression(rhs, depth + 1);
- let return_object = {
- operand: found_operand
- };
- // check for empty sides (unary leaves 1 empty)
- if(!(Array.isArray(parsed_lhs) && parsed_lhs.length == 0)) return_object['lhs'] = parsed_lhs;
- if(!(Array.isArray(parsed_rhs) && parsed_rhs.length == 0)) return_object['rhs'] = parsed_rhs;
- return return_object;
- }
- }
- return tokens;
- } else {
- // parse it otherwise
- return parse_scope(tokens.slice(1, tokens.length - 1)); // remove surrounding parentheses
- }
- };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement