javascript URL parser구현(tokenizer, laxer, parser)

2019. 11. 21. 23:21Programming/JavaScript

URL 파서

  1. Protocol
    ^(https?):\/\/
  • ^(문자열) : 문자열의 시작과 일치 할 때
  • ? : 바로앞에오는 문자가 존재할수도, 존재하지 않을 수도 있음. (https, http를 모두 가져오기 위함)
  • \/ : \가 메타문자를 문자열에서 찾고싶을 때 사용! \/ == \
  1. Domain
    ([^:\/\s]+) // 그냥 모든 문자열을 찾음
  • ., -을 비롯한 문자들로만 구성된다.
  • ^ : 대괄호 안에 존재할때는 부정, 대괄호 밖에서는 문자의 시작을 표현. 여기서는 대괄호 안에 존재하므로 http(protocol) 다음을 보니까, port 번호가 나오기 전까지를 체크한다.
  • + : 앞에 존재하는 문자가 1번 이상 반복될 때!
  • \s : 공백문자 또는 영문
  1. PORT

    (:([^\/]*))?
  2. pathFile

    ((\/[^\s/\/]+)*)?
  3. Parameter

    \/([^#\s\?]*)
  4. Anchor

    (#(\w*))?
  5. 그리고 문자열의 마지막에 끝표시인 $을 붙여준다.
    자바스크립트에서 쓰고싶다면, 정규식 리터럴을 써준다. / /
    global으로 설정하고싶다면 g를 추가.

    ^(https?):\/\/([^:\/\s]+)(:([^\/]*))?((\/[^\s\/]+)*)?(\?.*)(\#.*)

최종 test code

let obj = { result: "", protocol: "", domainName: "", port:"", pathFile:"", parameter:"", anchor:"" };

function Parse(url) {
    // tokenizer 
    var regex = /^(https?)?:\/\/([^:\/\s]+)?:([^\/]*)?((\/[^\s\/]+)*)?(\?.*)(\#.*)/g;
    let match = regex.exec(url);

    // lexer : tokenizer 한 결과를 객체에 넣기 + parser : 그 결과를 갖는 객체 바로 생성
    // 예외처리 하지 못했읍니다 ... 
    this.result = match[0];
    this.protocol = match[1]; // http://
    this.domainName = match[2]; // www.example.com
    this.port = match[3]; // :80
    this.pathFile = match[4]; // /path/to/myfile.html
    // this.file = match[5];
    this.parameter = match[6]; // ?key1=value1&key2=value2
    this.anchor = match[7]; // #SomewhereInTheDocument
}


let example = new Parse('http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument');
let naver = new Parse('https://naver.com:8000/aaa/bbb/ccc.html?key1=value1&key2=value2#anchor');
console.log(naver);
console.log(example);

parse

문자열의 구문을 분석

tokenizer, laxer, parser

"[123, 45, 'hello']"

tokenizer : 의미있는 단위로 쪼갠다

[‘[‘, ‘123’, ’45’, “’hello’”, ‘]’]

laxer : 쪼개진 데이터에 의미 부여

[{type: 'LBracket', value: '['},
 {type: 'number', value: 123},
 {type: 'number', value: 45},
 {type: 'string', value: 'hello'},
 {type: 'RBracket', value: ']'}]

parser : 의미 부여한 데이터를 구조화

{ type: 'array',
  child: 
   [ { type: 'number', value: 123, child: [] },
     { type: 'number', value: 45, child: [] },
     { type: 'string', value: 'hello', child: [] } 
    ] 
}