2014-10-03 2 views
0

Я возился с Lua, пытаясь создать собственный «скриптовый язык».Можно ли исправить этот шаблон gsub?

На самом деле это просто строка, которая переводится в код Lua, а затем выполняется с помощью loadstring. У меня проблемы с моими строками. При ветвлении (например, определение переменной внутри объявления переменной) это ошибки. Например, следующий код ошибки:

local code = [[ 
    define x as private: function() 
     define y as private: 5; 
    end; 
]] 
--defining y inside of another variable declaration, causes error 

Это происходит потому, что шаблон объявить переменную первый ищет ключевое слово «определение», и фиксирует все до тех пор, точка с запятой не найдено. Следовательно, х будет определяться как:

function() 
    define y as private: 5 --found a semicolon, set x to capture 

Я думаю, мой вопрос, можно ли игнорировать до тех пор, точку с запятой правильный не будет достигнут? Вот мой код до сих пор:

local lang = { 
    ["define(.-)as(.-):(.-);"] = function(m1, m2, m3) 
     return (
      m2 == "private" and " local " .. m1 .. " = " .. m3 .. " " or 
      m2 == "global" and " " .. m1 .. " = " .. m3 .. " " or 
      "ERROR IN DEFINING " .. m1 
     ) 
    end, 
} 

function translate(code) 
    for pattern, replace in pairs(lang) do 
     code = code:gsub(pattern, replace) 
    end 
    return code 
end 

local code = [[ 

    define y as private: function() 
     define x as private: 10; 
    end; 

]] 

loadstring(translate(code:gsub("%s*", "")))() 
--remove the spaces from code, translate it to Lua code through the 'translate' function, then execute it with loadstring 
+1

Обычно для обработки этих вложенных определений вам нужен рекурсивный алгоритм. В вашем случае простая справка по шаблону не будет простой в использовании. Я бы рекомендовал читать в кодовом слове слово и решать, как обрабатывать следующее слово. Это будет выглядеть как пользовательский парсер для вашего собственного языка. – Moop

ответ

1

Самым простым решением является, чтобы изменить свою последнюю группу захвата из

(.-) -- 0 or more lazy repetitions 

в

(.*) -- 0 or more repetitions 

т.е.

pattern = 'define(.-)as(.-):(.*);' 

- модификатор согласно PiL соответствует самой короткой последовательности.

Однако, как отмечено в моем комментарии, я бы не советовал писать парсер для вашего языка с использованием сопоставления с образцом. Он либо потребует действительно сложных шаблонов (для предотвращения краев), и, вероятно, будет непонятным для других.

Смежные вопросы