2016-07-28 2 views
-1

Обычно Python вызывает функции поКак написать небольшой токенизатор в Python?

func(arg0, arg1) 

Но я хотел бы, чтобы изменить

func arg0 arg1 

Например,

#Something... 
cmd = input() 
interpret(cmd) 
#Something... 

Если я вход 'func arg0 arg1', то я ожидаю Python для выполнения func(arg0, arg1).

Args будет содержать строку, чтобы мы не могли просто разделить слова.

На самом деле, я хотел бы написать несколько сценариев для использования на своем мобильном устройстве. Поэтому было бы немного раздражать, чтобы печатать круглые скобки.

+3

Итак, вы хотите переписать парсер Python, чтобы создать свой собственный язык ...? Я думаю, что это немного вне сферы действия. – deceze

+0

@deceze No.Потому что я хотел бы использовать его на терминале на своем телефоне. Это раздражает, чтобы печатать круглые скобки на моем телефоне. –

+0

Итак, вы просто хотите разбить первое слово на вход, найти функцию с помощью этого имени и вызвать его с остальными аргументами, такими как 'f (* args)' ...? – deceze

ответ

0

, если ни один из аргументов не содержит пробельные вы могли бы сделать

fn_args=cmd.split() 
python_code="%s(%s)" % (fn[0], ", ".join(fn_args[1:])) 
eval(python_code) 

Edit:

Если это не так просто, вы должны взглянуть на https://docs.python.org/3/library/cmd.html и https://docs.python.org/3/library/argparse.html но они требуют некоторой подготовки, прежде чем вы можете выполнить произвольный код

edit2:

Если вам не нужны ваши аргументы, чтобы быть точным питон, можно разобрать их как JSON with the standard library

вы могли бы сделать это как

import json 
cmd='fname "a" "b" 1' 
fn,sep,args=cmd.strip().partition(" ") 
end=0 
largs=[] 
d=json.JSONDecoder() 
while end < len(args): 
    args=args[end:].strip() 
    arg,end=d.raw_decode(args) 
    largs.append(arg) 
exec(fn)(*largs) # better look into exec docs 
+0

На самом деле будут пробелы и запятые. –

+0

@ ZhipengYANG Добавлены ссылки для не-простых случаев – janbrohl

+0

@ ZhipengYANG Добавлен JSON hack – janbrohl

0

Вы можете сделать это:

class tryClass: 
    def callFunction(self, arg, arg2): 
     print("In call") 
     print(arg) 
     print(arg2) 

input = str(input()) 
input = input.split(" ") 
funcName = input[0] 
my_cls = tryClass() 

method = getattr(my_cls, funcName) 
method(input[1], input[2]) 

Если я ставлю на входе CallFunction привет мир это работает :)

0

Все, что я хочу, это простой токенизатор. И я хотел бы запускать функции, позвонив по номеру eval(). Так вот что я сделал для своего проекта.

Вот результат:

>>> tokenizer('func 123 abc') 
[('func', 'func'), ('arg', '123'), ('arg', 'abc')] 
>>> tokenizer('func 123.5 abc') 
[('func', 'func'), ('arg', '123.5'), ('arg', 'abc')] 
>>> tokenizer('func 123.5 abc "Hello, World!"') 
[('func', 'func'), ('arg', '123.5'), ('arg', 'abc'), ('arg', 'Hello, World!')] 
>>> tokenizer("func 123.5 abc 'Hello, World!'") 
[('func', 'func'), ('arg', '123.5'), ('arg', 'abc'), ('arg', 'Hello, World!')] 

Attentsion: Это не может подходить для всех, это не полный синтаксический анализатор или токенизатор.

Код:

def isNumber(cmd): 
    try: 
     int(cmd) 
     return True 
    except ValueError: 
     try: 
      float(cmd) 
      return True 
     except ValueError: 
      return False 
    return False 

def isWord(cmd): 
    if len(cmd) == 0: 
     return False 
    if cmd[0].isalpha(): 
     for i in cmd[1:]: 
      if not i.isalpha() and i != '_' and i != '-': 
       return False 
     return True 
    return False 
def spaceParser(cmd): 
    i = 0 
    for i in range(len(cmd)): 
     if cmd[i] == ' ': 
      continue 
     break 
    return cmd[i:] 

def funcNameParser(cmd): 
    cmd = spaceParser(cmd) 
    i = 0 
    word = '' 
    for i in range(len(cmd)): 
     if cmd[i] != ' ': 
      word += cmd[i] 
     else: 
      break 
    if i + 1 > len(word): 
     return (word, cmd[i:]) 
    return (word, cmd[i+1:]) 

def argumentParser(cmd): 
    cmd = spaceParser(cmd) 
    if cmd[0] == '\'': 
     word = '' 
     i = 0 
     for i in range(1, len(cmd)): 
      if cmd[i] != '\'': 
       word += cmd[i] 
      else: 
       return (word, cmd[i+1:]) 
     assert False, 'Fatal exception: String not finished.' 
    if cmd[0] == '"': 
     word = '' 
     i = 0 
     for i in range(1, len(cmd)): 
      if cmd[i] != '"': 
       word += cmd[i] 
      else: 
       return (word, cmd[i+1:]) 
     assert False, 'Fatal exception: String not finished.'    
    i = 0 
    word = '' 
    for i in range(len(cmd)): 
     if cmd[i] != ' ': 
      word += cmd[i] 
     else: 
      break 
    assert isWord(word) or isNumber(word), 'Fatal exception: Not a valid name.' 
    if i + 1 > len(word): 
     return (word, cmd[i:]) 
    return (word, cmd[i+1:]) 

def tokenizer(cmd): 
    token = [] 
    result = funcNameParser(cmd) 
    token += [('func', result[0])] 
    while len(result[1]) != 0: 
     result = argumentParser(result[1]) 
     token += [('arg', result[0])] 
    return token 
0

Встроенная команда shlex модуль, вероятно, что вы хотите:

>>> import shlex 
>>> cmd = "func arg0 arg1 'arg2 has spaces'" 
>>> list(shlex.shlex(cmd)) 
['func', 'arg0', 'arg1', "'arg2 has spaces'"] 

Если вы можете доверять вход, то на самом деле называют это будет выглядеть следующим образом:

>>> tokens = list(shlex.shlex(cmd)) 
>>> # here is a stupid func function that reverses its input args 
>>> func = lambda *args: print(*reversed(args)) 
>>> eval(tokens[0])(*tokens[1:]) 
'arg2 has spaces' arg1 arg0 
Смежные вопросы