diff options
author | Jussi Pakkanen <jpakkane@gmail.com> | 2013-10-16 21:50:07 +0300 |
---|---|---|
committer | Jussi Pakkanen <jpakkane@gmail.com> | 2013-10-16 21:50:07 +0300 |
commit | 4e522ef2158c8ba4bac3f13b31ecd2f746696a84 (patch) | |
tree | 9ee7d6df43eb27ac04872f7ff8b71d9a9bed9498 /optinterpreter.py | |
parent | 0da4537b6962d1cd51a05393f4b0cf250bea1ac4 (diff) | |
download | meson-4e522ef2158c8ba4bac3f13b31ecd2f746696a84.zip meson-4e522ef2158c8ba4bac3f13b31ecd2f746696a84.tar.gz meson-4e522ef2158c8ba4bac3f13b31ecd2f746696a84.tar.bz2 |
Very basic option parser skeleton.
Diffstat (limited to 'optinterpreter.py')
-rw-r--r-- | optinterpreter.py | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/optinterpreter.py b/optinterpreter.py new file mode 100644 index 0000000..01ae441 --- /dev/null +++ b/optinterpreter.py @@ -0,0 +1,115 @@ +# Copyright 2013 Jussi Pakkanen + +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at + +# http://www.apache.org/licenses/LICENSE-2.0 + +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import mparser +import coredata +import nodes +import os + +class OptionException(coredata.MesonException): + pass + +class UserOption: + def __init__(self, kwargs): + super().__init__() + +class UserStringOption(UserOption): + def __init__(self, kwargs): + super().__init__(kwargs) + self.value = kwargs.get('value', '') + if not isinstance(self.value, str): + raise OptionException('Value of string option is not a string') + +option_types = {'string' : UserStringOption, + } + +class OptionInterpreter: + def __init__(self): + self.options = {} + + def process(self, option_file): + try: + ast = mparser.build_ast(open(option_file, 'r').read()) + except coredata.MesonException as me: + me.file = option_file + raise me + if not isinstance(ast, nodes.CodeBlock): + e = OptionException('Option file is malformed.') + e.lineno = ast.lineno() + raise e + statements = ast.get_statements() + i = 0 + while i < len(statements): + cur = statements[i] + try: + self.evaluate_statement(cur) + except Exception as e: + e.lineno = cur.lineno() + e.file = os.path.join('options.txt') + raise e + i += 1 # In THE FUTURE jump over blocks and stuff. + print(self.options) + + def reduce_single(self, arg): + if isinstance(arg, nodes.AtomExpression) or isinstance(arg, nodes.AtomStatement): + return self.get_variable(arg.value) + elif isinstance(arg, str): + return arg + elif isinstance(arg, nodes.StringExpression) or isinstance(arg, nodes.StringStatement): + return arg.get_value() + elif isinstance(arg, nodes.BoolStatement) or isinstance(arg, nodes.BoolExpression): + return arg.get_value() + elif isinstance(arg, nodes.ArrayStatement): + return [self.reduce_single(curarg) for curarg in arg.args.arguments] + elif isinstance(arg, nodes.IntStatement): + return arg.get_value() + else: + raise OptionException('Arguments may only be string, int, bool, or array of those.') + + def reduce_arguments(self, args): + assert(isinstance(args, nodes.Arguments)) + if args.incorrect_order(): + raise OptionException('All keyword arguments must be after positional arguments.') + reduced_pos = [self.reduce_single(arg) for arg in args.arguments] + reduced_kw = {} + for key in args.kwargs.keys(): + if not isinstance(key, str): + raise OptionException('Keyword argument name is not a string.') + a = args.kwargs[key] + reduced_kw[key] = self.reduce_single(a) + return (reduced_pos, reduced_kw) + + def evaluate_statement(self, node): + if not isinstance(node, nodes.FunctionCall): + raise OptionException('Option file may only contain option definitions') + func_name = node.get_function_name() + if func_name != 'option': + raise OptionException('Only calls to option() are allowed in option files.') + (posargs, kwargs) = self.reduce_arguments(node.arguments) + if 'type' not in kwargs: + raise OptionException('Option call missing mandatory "type" keyword argument') + opt_type = kwargs['type'] + if not opt_type in option_types: + raise OptionException('Unknown type %s.' % opt_type) + if len(posargs) != 1: + raise OptionException('Option all must have one (and only one) positional argument') + opt_name = posargs[0] + if not isinstance(opt_name, str): + raise OptionException('Positional argument must be a string.') + self.options[opt_name] = option_types[opt_type](kwargs) + +if __name__ == '__main__': + import sys + oi = OptionInterpreter() + oi.process(sys.argv[1]) |