2016-11-08 6 views
1

명령을 사용하여 스택을 조작하는 간단한 스택 기반 언어를 만들고 있습니다. 소스에서 명령을 찾으면이 정규식을 사용하여 sum과 같은 실제 명령 이름과 명령 인수를 구분합니다. 인수는 삼각형 대괄호로 묶이고 쉼표로 구분됩니다. 여기 정규식에서 정의되지 않은 양의 캡처 방법

는 내가 현재 사용하고 정규식입니다 :

(?<command>[^<>\s]+)(\<(?<args>(\d+)+(?>,\s*\d+)*)\>)? 

이제이 잘 작동하고, 여기의 몇 가지 예 작업 :

+    => command: '+', args: nil 
sum<5>   => command: 'sum', args: '5' 
print<1, 2, 3> => command: 'print', args: '1, 2, 3' 

이 각각에 대해 내가 원하는대로 정확하게 작동 그러나 마지막. 내 질문은, 각 인수를 별도로 캡처하는 방법이 있습니까? 나는이 같은 의미 : 그런데

print<1, 2, 3> => command: 'print', args: ['1', '2', '3'] 

, 나는 최신 루비 정규식 엔진을 사용하고 있습니다.

+1

아니, 반복 캡처 그룹과 간단한 정규식을 사용하여 그런 식으로 작동하지 않습니다. 후 처리 단계로','를 사용하여 두 번째 캡처를 분할해야합니다. 루비 정규식 엔진은 캡처 스택을 유지하지 않습니다. –

+0

그건 부끄러운 일입니다. 어쨌든 – Zac

+1

그룹 스택을 지원하는 정규 표현식이 거의 없습니다. .NET과 Python PyPi 정규 표현식 모듈 만 기본적으로 지원합니다. 가까운 패턴은 [/ (? : \ G (?! \ A), \ s * | ( [^ <> \ s] +) <)(? \ d +) /'] com/r/BDocFayOkZ)하지만 여러 일치를 사용하며 입력에 둘 이상의 발생이있는 경우이를 구분하는 데 어려움이있을 수 있습니다. –

답변

1

엔진이 캡처 스택을 유지하지 않으므로 Ruby regex에서 반복 캡처 그룹이있는 간단한 정규식을 사용하여 출력을 얻을 수 없습니다.

후 처리 단계로 ,을 사용하여 두 번째 캡처를 분할해야합니다.

Ruby demo를 참조하십시오

def cmd_split(s) 
    rx = /(?<command>[^<>\s]+)(<(?<args>(\d+)+(?:,\s*\d+)*)>)?/ 
    res = [] 
    s.scan(rx) { 
     res << ($~[:args] != nil ? 
      Hash["command", $~[:command], "args", $~[:args].split(/,\s*/)] : 
      Hash[$~[:command], ""]) } 
    return res 
end 

puts cmd_split("print<1, 2, 3>") # => {"command"=>"print", "args"=>["1", "2", "3"]} 
puts cmd_split("disp<1>")  # => {"command"=>"disp", "args"=>["1"]} 
puts cmd_split("+")    # => {"+"=>""}