Advertisement
Guest User

Untitled

a guest
Apr 20th, 2019
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. module.exports = (tokens) => {
  2.     return parse_scope(tokens, true);
  3. }
  4.  
  5. const parse_scope = (tokens, base) => {
  6.     const processed_tokens = comma_to_semicolon(tokens);
  7.     const lines = get_line_tokens(processed_tokens);
  8.     const actions = lines.map(tokens => parse_line(tokens));
  9.  
  10.     if(actions.length == 1 && !base) return actions[0];
  11.     else return actions;
  12. }
  13.  
  14.  
  15. const parse_line = (tokens) => {
  16.     let input_tokens = tokens;
  17.     if(input_tokens[input_tokens.length - 1] == ';') input_tokens.pop(); // remove semicolon at the end
  18.     return parse_expression(input_tokens);
  19. };
  20.  
  21. const parse_expression = (tokens, depth = 0) => {
  22.     // detect if tokens are surrounded by pair of ()
  23.     // for instance: (...(...)) is valid but (...)...(...) is not
  24.  
  25.     const first_is_valid = tokens[0] == '(';
  26.     let last_is_valid = tokens[tokens.length - 1] == ')', parenthesis_stack = 0;
  27.     for(let i = 0; i < tokens.length; i++){
  28.         let token = tokens[i];
  29.         if(token == '(') parenthesis_stack += 1;
  30.         else if(token == ')') parenthesis_stack -= 1;
  31.  
  32.         if(token == ')' && parenthesis_stack == 0 && i != tokens.length - 1) last_is_valid = false;
  33.     }
  34.     // console.log(!first_is_valid || !last_is_valid);
  35.  
  36.     if(!first_is_valid || !last_is_valid){
  37.         // evaluate expression:
  38.         for(operations of order_of_operations){ // loop through each level of order of operations
  39.             let parenthesis_stack = 0;
  40.             let lhs = [], rhs = [], found_operand = null, just_found = false;
  41.  
  42.             let reverse = operations[0] == '->';
  43.             let maybe_reversed_tokens = tokens.slice(0);
  44.             if(reverse) maybe_reversed_tokens.reverse();
  45.  
  46.             for(let i = 0; i < maybe_reversed_tokens.length; i++){
  47.                 let token = maybe_reversed_tokens[i];
  48.  
  49.                 // ignore stuff in parenthesis
  50.                 if(token == '(') parenthesis_stack += 1;
  51.                 else if(token == ')') parenthesis_stack -= 1;
  52.  
  53.                 // this loop is inside the token loop because we want all operands in operations to have same precedence, left to right
  54.                 for(operand of operations){ // loop through each operand
  55.                     if(parenthesis_stack == 0 && token == operand && found_operand == null){
  56.                         found_operand = operand;
  57.                         just_found = true;
  58.                     }
  59.                 }
  60.  
  61.                 if(just_found) just_found = false;
  62.                 else {
  63.                     if(!reverse){
  64.                         if(found_operand == null) lhs.push(token);
  65.                         else rhs.push(token);
  66.                     } else {
  67.                         if(found_operand == null) rhs.unshift(token);
  68.                         else lhs.unshift(token);
  69.                     }
  70.                 }
  71.             }
  72.  
  73.             if(found_operand != null){
  74.                 // parse both lhs and rhs
  75.                 let parsed_lhs = parse_expression(lhs, depth + 1);
  76.                 let parsed_rhs = parse_expression(rhs, depth + 1);
  77.  
  78.                 let return_object = {
  79.                     operand: found_operand
  80.                 };
  81.  
  82.                 // check for empty sides (unary leaves 1 empty)
  83.                 if(!(Array.isArray(parsed_lhs) && parsed_lhs.length == 0)) return_object['lhs'] = parsed_lhs;
  84.                 if(!(Array.isArray(parsed_rhs) && parsed_rhs.length == 0)) return_object['rhs'] = parsed_rhs;
  85.  
  86.                 return return_object;
  87.             }
  88.         }
  89.  
  90.         return tokens;
  91.     } else {
  92.         // parse it otherwise
  93.         return parse_scope(tokens.slice(1, tokens.length - 1)); // remove surrounding parentheses
  94.     }
  95. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement