javascript - 으로 - mobile top button



Crockfords 맨 위로 조작원 우선 순위 (2)

나는 전체 기사를 읽을 시간이 없으므로 나는 100 % 확실하지 않다. 내 의견으로는 이유는 var 문에서 대입 연산자가 약간 특별하기 때문입니다. 가능한 모든 왼쪽 값을 허용하지 않습니다 . 객체의 멤버는 허용되지 않습니다 (no 또는 [ 연산자]). 일반 변수 이름 만 허용됩니다.

따라서 모든 왼쪽 값을 허용하기 때문에 일반 assignment 함수를 사용할 수 없습니다.

나는 이것에 대해 꽤 확신하지만 다음은 단지 추측이다 :

assignment 함수를 선택적으로 호출 assignment 하고 할당 연산자를 사용했는지 확인한 후에야합니다.

  advance();
  if (token.id === "=") {
      // OK, Now we know that there is an assignment.

그러나 함수 assignment 은 현재 토큰이 operator = 아닌 왼쪽 값이라고 가정합니다.

assignment 멤버가 true 설정되지 않은 이유는 알 수 없습니다. 생성 된 트리를 사용하여 수행 할 작업에 따라 다릅니다. 다시 말하지만, var 문에서의 할당은 약간 특별하며 설정하기가 불가능할 수도 있습니다.

관심 밖의, 나는 간단한 언어에 대한 파서를 작성하는 방법을 배우고 궁극적으로 내 자신의 작은 코드 - 골프 언어에 대한 통역사를 작성하는 방법을 이해하자마자 그런 것들이 일반적으로 작동합니다.

그래서 더글라스 크로크 포드 (Douglas Crockfords)의 기사 탑 다운 운영자 우선 순위 (Top Down Operator Precedence)를 읽기 시작했습니다.

참고 : 아래 코드 스 니펫의 컨텍스트에 대해 더 자세히 이해하려면이 기사를 읽어야합니다.

var 문과 대입 연산자가 함께 작동하는 방법을 이해하는 데 어려움이 있습니다.

DC는 다음과 같은 할당 연산자를 정의합니다.

var assignment = function (id) {
    return infixr(id, 10, function (left) {
        if (left.id !== "." && left.id !== "[" &&
                left.arity !== "name") {
            left.error("Bad lvalue.");
        }
        this.first = left;
        this.second = expression(9);
        this.assignment = true;
        this.arity = "binary";
        return this;
    });
};
assignment("=");  

참고 : [[value]]는 값으로 단순화 된 토큰을 참조합니다.

표현 함수가 [[t]],[[=]],[[2]] 도달하면 [[=]].led 는 다음과 같습니다.

{
    "arity": "binary",
    "value": "=",
    "assignment": true, //<-
    "first": {
        "arity": "name",
        "value": "t"
    },
    "second": {
        "arity": "literal",
        "value": "2"
    }
}

DC는 assignment 기능을 만듭니다. 왜냐하면

우리는 두 가지 여분의 비즈니스를 수행하기를 원합니다. 왼쪽 피연산자를 검사하여 그것이 적절한 lvalue인지 확인하고 나중에 할당 문을 신속하게 식별 할 수 있도록 할당 멤버를 설정합니다 .

다음과 같이 정의되는 var 문을 소개하는 시점까지 나에게 의미가 있습니다.

var 문은 현재 블록에 하나 이상의 변수를 정의합니다. 각 이름 뒤에 = 및 선택적으로 수식을 붙일 수 있습니다.

stmt("var", function () {
    var a = [], n, t;
    while (true) {
        n = token;
        if (n.arity !== "name") {
            n.error("Expected a new variable name.");
        }
        scope.define(n);
        advance();
        if (token.id === "=") {
            t = token;
            advance("=");
            t.first = n;
            t.second = expression(0);
            t.arity = "binary";
            a.push(t);
        }
        if (token.id !== ",") {
            break;
        }
        advance(",");
    }
    advance(";");
    return a.length === 0 ? null : a.length === 1 ? a[0] : a;
});

이제 구문 분석기가 [[var]],[[t]],[[=]],[[1]] 과 같은 토큰 집합에 도달하면 생성 된 트리는 비슷한 모양을 갖습니다.

{
    "arity": "binary",
    "value": "=",
    "first": {
        "arity": "name",
        "value": "t"
    },
    "second": {
        "arity": "literal",
        "value": "1"
    }
}

내 질문의 핵심 부분은 if (token.id === "=") {...} 부분입니다.

왜 전화하는지 이해가 안돼.

    t = token;
    advance("=");
    t.first = n;
    t.second = expression(0);
    t.arity = "binary";
    a.push(t);

오히려

    t = token;
    advance("=");
    t.led (n);
    a.push(t);  

... 부분에.

이것은 우리의 [[=]] 연산자 led 함수 (할당 함수)를 호출 할 것입니다.

적절한 lvalue인지 확인 하고 할당 멤버를 설정하여 나중에 할당 문을 신속하게 식별 할 수 있습니다.

{
    "arity": "binary",
    "value": "=",
    "assignment": true,
    "first": {
        "arity": "name",
        "value": "t"
    },
    "second": {
        "arity": "literal",
        "value": "1"
    }
}

expression(0) vs. expression (9) 호출은 0과 10 사이의 lbp 를 가진 연산자가 없으므로 아무런 차이가 없습니다. ( !(0<0) && !(9<0) && 0<10 && 9<10) )

그리고 token.id === "=" 조건은 token.id'[' 또는 '.' t.led 는 호출되지 않을 것입니다.

내 짧은 질문은 :

왜 우리는 선택적으로 변수 선언 다음에 대입 연산자를 사용할 수있는 led 함수를 호출하지 않습니다. 하지만 대신 수동으로 성명의 firstsecond 구성원을 설정하지만 assignment 멤버가 아닌가요?

다음은 간단한 문자열을 파싱하는 두 가지 간단한 방법입니다. original 코드를 사용하고 하나는 assignment 연산자를 사용했습니다.


언어를 파싱 할 때 의미와 구문의 두 가지가 중요합니다.

의미 상으로 , var x=5;var x;x=5 같지 않으면 매우 가까운 것 같습니다 var x;x=5 (두 경우 모두 먼저 변수가 선언 된 다음 그 변수에 선언 된 값이 할당됩니다.) 이것은 사용자가 관찰 한 것이며 대부분의 경우 올바릅니다.

그러나 구문 론적 으로는 두 가지가 다릅니다 (명확하게 볼 수 있습니다).

자연어에서 아날로그는 다음과 같습니다.

  • 그 아이는 사과를 가지고있다.
  • 사과가있다. 소년은 그것을 가지고있다.

이제 간결하게! 두 가지 예를 살펴 보겠습니다.

두 사람 (거의)이 같은 것을 의미하는 반면, 그들은 분명히 같은 문장이 아닙니다. 자바 스크립트로 돌아 가기!

첫 번째 : var x=5다음과 같이 읽습니다 .

var                      x              =                  5
-----------------------VariableStatement--------------------
var -------------------        VariableDeclarationList 
var -------------------        VariableDeclaration
var            Identifier -------   Initialiser(opt)
var ------------------- x              = AssignmentExpression
var ------------------- x ------------ = LogicalORExpression
var ------------------- x ------------ = LogicalANDExpression
var ------------------- x ------------ = BitwiseORExpression
var ------------------- x ------------ = BitwiseXORExpression
var ------------------- x ------------ = BitwiseANDExpression 
var ------------------- x ------------ = EqualityExpression
var ------------------- x ------------ = ShiftExpression
var ------------------- x ------------ = AdditiveExpression
var ------------------- x ------------ = MultiplicativeExpression
var ------------------- x ------------ = UnaryExpression
var ------------------- x ------------ = PostfixExpression 
var ------------------- x ------------ = NewExpression
var ------------------- x ------------ = MemberExpression
var ------------------- x ------------ = PrimaryExpression
var ------------------- x ------------ = Literal
var ------------------- x ------------ = NumericLiteral
var ------------------- x ------------ = DecimalLiteral
var ------------------- x ------------ = DecimalDigit 
var ------------------- x ------------ = 5

휴! 이 모든 것은 문법적으로 var x = 5 를 구문 분석해야했습니다. 물론 많은 경우 표현식을 처리하고 있습니다.하지만 그게 무엇인지, 다른 버전을 확인해 봅시다.

이것은 두 문장으로 나뉩니다. var x; x = 5 var x; x = 5 첫 번째 것은 다음과 같습니다.

var                      x 
--------VariableStatement---
var ---- VariableDeclarationList 
var ---- VariableDeclaration
var                 Idenfifier (optional initializer not present)
var                      x

두 번째 부분은 x=5 이며 이는 할당 문입니다. 나는 똑같은 표현의 광기와 함께 할 수있다. 그러나 그것은 거의 똑같다.

결론적으로 두 언어가 공식 언어 문법에서와 같이 구문 론적으로 동일한 결과를 의미 론적으로 내놓는 반면, 두 언어는 의미가 다릅니다. 이 경우 결과는 실제로 동일합니다.





parsing