Subversion Repositories Kolibri OS

Rev

Rev 9357 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. # Copyright Magomed Kostoev
  2. # Published under MIT license
  3.  
  4. class Rule:
  5.     pass
  6.  
  7. def get_config(config_name):
  8.     if config_name == "KPACK_CMD":
  9.         # Just never pack the file for now
  10.         return ""
  11.     else:
  12.         print(f"Unknown config name: {config_name}")
  13.         exit(-1)
  14.  
  15. def skip_whitespaces(src, ptr):
  16.     while len(src) > ptr and src[ptr] == " ":
  17.         ptr += 1
  18.     return ptr
  19.  
  20. # Returns True if @src has @string starting from @ptr index
  21. def match_string(src, ptr, string):
  22.     if len(src) <= ptr + len(string):
  23.         return False
  24.     for i in range(len(string)):
  25.         if src[ptr + i] != string[i]:
  26.             return False
  27.     return True
  28.  
  29. def parse_tup_getconfig(src, ptr):
  30.     # Skip get straight to the argument
  31.     ptr += len("tup.getconfig(")
  32.     ptr = skip_whitespaces(src, ptr)
  33.     if src[ptr] != "\"":
  34.         print("Expected \"config name\" as tup.getconfig parameter")
  35.         exit()
  36.     (config_name, ptr) = parse_string(src, ptr)
  37.     ptr = skip_whitespaces(src, ptr)
  38.     # Skip closing parenthese of the tup.getconfig call
  39.     assert(src[ptr] == ")")
  40.     ptr += 1
  41.     return (get_config(config_name), ptr)
  42.  
  43. def parse_string(src, ptr):
  44.     ptr += 1
  45.     string = ""
  46.     while src[ptr] != "\"":
  47.         string += src[ptr]
  48.         ptr += 1
  49.     # Skip the closing "\""
  50.     ptr += 1
  51.     ptr = skip_whitespaces(src, ptr)
  52.     # Check if we have concatination here
  53.     if match_string(src, ptr, ".."):
  54.         # Skip the ".."
  55.         ptr += 2
  56.         # The expression parsing should result in a string
  57.         (string_to_add, ptr) = parse_expression(src, ptr)
  58.         # Concat our string to the resulting string
  59.         string += string_to_add
  60.     return (string, ptr)
  61.  
  62. def parse_expression(src, ptr):
  63.     ptr = skip_whitespaces(src, ptr)
  64.     result = "WAT?!"
  65.     if src[ptr] == "\"":
  66.         (result, ptr) = parse_string(src, ptr)
  67.     elif match_string(src, ptr, "tup.getconfig("):
  68.         (result, ptr) = parse_tup_getconfig(src, ptr)
  69.     else:
  70.         print(f"Can't handle anything starting with '{src[ptr]}'")
  71.         exit(-1)
  72.     ptr = skip_whitespaces(src, ptr)
  73.     return (result, ptr)
  74.  
  75. def expect_comma(src, ptr):
  76.     comma_skept = False
  77.     ptr = skip_whitespaces(src, ptr)
  78.     if src[ptr] == ",":
  79.         ptr += 1
  80.         return (True, ptr)
  81.     else:
  82.         return (False, ptr)
  83.  
  84. def parse_arguments(src, ptr):
  85.     result = []
  86.     # Parse first argument
  87.     (argument, ptr) = parse_expression(src, ptr)
  88.     result.append(argument)
  89.     (comma_encoutered, ptr) = expect_comma(src, ptr)
  90.     # Parse the second argument if it's there
  91.     if comma_encoutered:
  92.         (argument, ptr) = parse_expression(src, ptr)
  93.         result.append(argument)
  94.         (comma_encoutered, ptr) = expect_comma(src, ptr)
  95.     # Parse third argument if it's there
  96.     if comma_encoutered:
  97.         (argument, ptr) = parse_expression(src, ptr)
  98.         result.append(argument)
  99.     return result
  100.  
  101. def parse_rule(src, ptr):
  102.     # Get straight to the first argument
  103.     ptr += len("tup.rule(")
  104.     # Parse the arguments
  105.     args = parse_arguments(src, ptr)
  106.     # Build the rule object
  107.     result = Rule()
  108.     if len(args) == 3:
  109.         result.input = args[0]
  110.         result.command = args[1]
  111.         result.output = args[2]
  112.         # Replace %f with input file in rule's command
  113.         if type(result.input == str):
  114.             result.command = result.command.replace("%f", result.input)
  115.         else:
  116.             print("Command building with non-string tup.rule's first argument"
  117.                 + " isn't implemented")
  118.             exit()
  119.         # Replace %o with output file in rule's command
  120.         if type(result.output == str):
  121.             result.command = result.command.replace("%o", result.output)
  122.         else:
  123.             print("Command building with non-string tup.rule's first argument"
  124.                 + " isn't implemented")
  125.             exit()
  126.     elif len(args) == 2:
  127.         result.input = []
  128.         result.command = args[0]
  129.         result.output = args[1]
  130.     else:
  131.         print(f"tup.rule can only take 2 or 3 arguments, not {len(args)}")
  132.         exit(-1)
  133.     # Unify the API - return arrays as input and output
  134.     if type(result.input) == str:
  135.         result.input = [ result.input ]
  136.     else:
  137.         assert(type(result.input) == list)
  138.     if type(result.output) == str:
  139.         result.output = [ result.output ]
  140.     else:
  141.         assert(type(result.output) == list)
  142.     return result
  143.  
  144. def parse(file_name):
  145.     rules = []
  146.     with open(file_name) as f:
  147.         tupfile = f.read()
  148.     rule_begin_index = tupfile.find("tup.rule(")
  149.     while (rule_begin_index != -1):
  150.         rules.append(parse_rule(tupfile, rule_begin_index))
  151.         # Find the next tup.rule call
  152.         rule_begin_index = tupfile.find("tup.rule(", rule_begin_index + len("tup.rule("))
  153.     return rules
  154.