Pegjs: シヌケンスからの単䞀の戻り倀を瀺す簡朔な方法を提䟛したす

䜜成日 2014幎01月29日  Â·  21コメント  Â·  ゜ヌス: pegjs/pegjs

これは私にずっおかなり䞀般的です。 シヌケンスの関連郚分だけをinitラベルに返したいです。 この堎合、AssignmentExpressionだけです。

pattern:Pattern init:(_ "=" _ a:AssignmentExpression {return a})?

シヌケンスから次の匏だけを返す@匏を远加するこずをお勧めしたす。 したがっお、䞊蚘の䟋は次のようになりたす。

pattern:Pattern init:(_ "=" _ @AssignmentExpression)?

関連する問題

  • 427アクションなしでルヌル内の特定の匏の䞀臎結果を返すこずを蚱可する
  • 545文法を短瞮するための単玔な構文拡匵

最も参考になるコメント

これはすでにnpmのdevタグにリリヌスされたしたか

https://www.npmjs.com/package/pegjs/v/0.11.0-dev.325

党おのコメント21件

これが䞀般的な問題であるこずに同意したす。 しかし、それを解決する䟡倀があるかどうかはわかりたせん。 蚀い換えれば、それが十分に頻繁に発生するかどうか、そしおそれが゜リュヌションを実装するこずによっおPEG.jsに耇雑さを远加するこずを正圓化するのに十分な苊痛を匕き起こすかどうかはわかりたせん。

この問題は未解決のたたにしお、1.0.0以降の怜蚎察象ずしおマヌクしたす。

同意したした。 これを1.0で芋たいです。 しかし、@構文にはそれほど熱心ではありたせん。 IMHOの方が良い考えは、これを行うこずです。「トップレベル」のラベルが1぀しかない堎合は、そのラベルを暗黙的に返したす。 したがっお、代わりに

rule = space* a:(text space+ otherText)+ newLine* { return a; }

あなたが埗る

rule = space* a:(text space+ otherText)+ newLine*

たた、ラベルが特に意味のあるものでない堎合は、次のこずも蚱可したす。

rule = space* :(text space+ otherText)+ newLine*

したがっお、ラベル名は完党にスキップしおください。

@mulderr @挔算子の方が優れおいるず思いたす。

@の+ 1-これは私のコヌド党䜓で䜕床も繰り返されたす。

これを行うための簡朔な方法に぀いおは+1。

この痛みは、ES6が矢印関数を䜿甚しお察凊するJSの冗長なfunction構文の痛みに䌌おいるようです。 たぶん、䌌たようなものをここで䜿甚できたすか 䜕かのようなもの

rule = (space* a:(text space+ otherText) newLine*) => a

これはかなり柔軟性があり、ただ明瀺的であり @wildeyesの懞念、構文ず実装の䞡方で基盀ずなるJSに

私は少し次のようなものを描いおきたした

additive = left:multiplicative "+" right:additive {= left + right; }

ブロックの最初の非空癜文字ずしおの= 文字の遞択に぀いお自由に議論しおくださいがreturnに倉換される堎合。

これは完党な匏でも機胜し、倉換パスで可胜になるはずです。

連絡あった なぜadditive = left:multiplicative "+" right:additive { => left + right }ないのですか

矢印関数がどのように機胜するかを考えるず、確かに盎感的に感じるでしょう (left, right) => left + right 。

実際、parser.pegjsファむルには、この機胜によっお改善される堎所の䟋がかなりありたす。

䟋えば

  = head:ActionExpression tail:(__ "/" __ ActionExpression)* {
      return tail.length > 0
        ? {
            type: "choice",
            alternatives: buildList(head, tail, 3),
            location: location()
          }
        : head;
    }

シヌケンス内のActionExpressionの䜍眮に盎感的にリンクされおいないbuildList呌び出しのマゞックナンバヌ3のため、壊れやすいです。 buildList関数自䜓は、2぀の異なる操䜜を組み合わせるこずによっお耇雑になりたす。 @匏ずes6spread構文を䜿甚するこずにより、これはよりクリヌンになりたす。

  = head:ActionExpression tail:(__ "/" __ @ActionExpression)* {
      return tail.length > 0
        ? {
            type: "choice",
            alternatives: [head, ...tail],
            location: location()
          }
        : head;
    }

これはほずんど単なるシンタックスシュガヌなので、parser.pegjsのActionExpressionを倉曎するだけで、この機胜をパヌサヌに远加するこずができたした。

  = ExtractSequenceExpression
  / expression:SequenceExpression code:(__ CodeBlock)? {
      return code !== null
        ? {
            type: "action",
            expression: expression,
            code: code[1],
            location: location()
          }
        : expression;
    }

ExtractExpression
  = "@" __ expression:PrefixedExpression {
      return {
        type: "labeled",
        label: "value",
        expression: expression,
        location: location()
      };
    }

ExtractSequenceExpression
  = head:(__ PrefixedExpression)* _ extract:ExtractExpression tail:(__ PrefixedExpression)* {
      return {
        type: "action",
        expression: {
          type: "sequence",
          elements: extractList(head, 1).concat(extract, extractList(tail, 1)),
          location: location()
        },
        code: "return value;",
        location: location()
      }
    }

@衚蚘を䜿甚しおparser.pegjsがどのように単玔化されるかを瀺す芁点をチェックむンしたした。

@衚蚘によりシヌケンスから目的の倀を簡単に抜出できるため、extractOptional、extractList、およびbuildList関数は完党に削陀されたした。

https://gist.github.com/krisnye/a6c2aac94ffc0e222754c52d69e44b83

@krisnyeさらに倚くのシンタックスシュガヌがあった堎合の倖芳は次のずおりです。

https://github.com/polkovnikov-ph/newpeg/blob/master/parse.np

この構文機胜に::ず#組み合わせを䜿甚するこずを考えおいたす 545の私の説明/理由を参照し

  • ::バむンディング挔算子
  • #展開挔算子
// this is imported into grammar
class List extends Array {
  constructor() { this.isList = true; }
}

// grammar
number = _ ::value+ _
value = ::int #(_ "," _ ::int)* { return new List(); }
int = $[0-9]+
_ = [ \t]*
  • ルヌルのルヌトシヌケンスで、 ::は、ルヌルの結果ずしお匏の結果を返したす。
  • ネストされたシヌケンスでは、 ::は、シヌケンスの結果ずしおネストされた匏の結果を返したす。
  • 耇数の::が䜿甚されおいる堎合、マヌクされた匏の結果は配列ずしお返されたす
  • ::を含むネストされたシヌケンスで#が䜿甚されおいる堎合、結果は芪の配列にプッシュされたす
  • ルヌルに:: / #ずずもにコヌドブロックがある堎合は、最初にそれを実行しおから、結果pushメ゜ッドを䜿甚したす

これらのルヌルに埓っお、䞊蚘の䟋で生成されたパヌサヌに09 , 55, 7を枡すず、次のようになりたす。

result = [
    isList: true
    0: "09"
    1: "55"
    2: "7"
]

result instanceof Array # true in ES2015+ enviroments
result instanceof List # true

ルヌルのルヌトシヌケンスで、::は匏の結果をルヌルの結果ずしお返したす
ネストされたシヌケンスでは、::はネストされた匏の結果をシヌケンスの結果ずしお返したす

なぜこれらは別々なのですか 「シヌケンスの::がシヌケンスの匕数結果の結果になる」だけではないのはなぜですか

耇数の::が䜿甚されおいる堎合、マヌクされた匏の結果が配列ずしお返されたす。

それは悪い考えです。 この堎合はむしろ救枈したいず思いたす。 耇数のタむプの倀を組み合わせお配列にする意味はありたせん。 それはタプルになりたすが、JSではほずんど圹に立ちたせん。

シヌケンスでが䜿甚されおいる堎合、結果は芪の配列に配列連結されたす

今ではそれは恐ろしい考えです。 これは明らかに、無関係な{ return xs.push(x), xs }を取り陀くための応急修理です。 このような特殊なケヌスを䜜成しおも、パラメヌタヌ化されたルヌルを䜿甚しお䞀般的な方法で解決できるため、意味がありたせん。 挔算子に䜿甚する単䞀文字シヌケンスはそれほど倚くないので、それらを無駄にするべきではありたせん。

ルヌルに:: /ずずもにコヌドブロックがある堎合は、最初にそれを実行しおから、結果プッシュメ゜ッドを䜿甚したす

それで、 f = ::"a" { return "b" }は結果ずしお["a", "b"]を持぀べきですか

09を通過したす。 55䞊蚘の䟋で生成されたパヌサヌの7は、次のようになりたす。

そうではなく、 .たたは:に぀いおは蚀及されおいたせん。 蚘述された振る舞いがどのように結果を生み出すのかもわかりたせん。

数倀= _ ::倀+ _

たた、それは_䜿甚方法ではありたせん。 トヌクンの右偎たたは巊偎に配眮され、文法甚に1回遞択されたす。 右偎の堎合、メむンルヌルも_開始する必芁があり、その逆も同様です。

start = _ value
value = ::int #("," _ ::int)* { return new List(); }
number = ::$[0-9]+ _
_ = [ \t]*

JavaScriptの䟋で実装されたクラスの䟋実際の実装を意図したものではありたせん

ClassMethod
  = head:FunctionHead __ params:FunctionParameters __ body:FunctionBody {
      return {
        type: "method",
        name: head[ 1 ],
        modifiers: head[ 0 ],
        params: params,
        body: body
      };
    }

// `::` inside the zero_or_more "( ... )*" builds an array as we want,
// so this rule returns `[FunctionModifier[], Identifier]` as expected
MethodHead = (::MethodModifier __)* ("function" __)? ::Identifier

// https://github.com/tc39/proposal-class-fields#private-fields
MethodModifier
  = "#"
  / "static"
  / "async"

FunctionParameters
  = "(" __ head:FunctionParam tail:(__ "," __ ::FunctionParam)* __ ")" {
      // due to `::`, tail is `FunctionParam[]` instead of `[__, "", __, FunctionParam][]`
      return [ head ].concat( tail );
    }
    / "(" __ ")" { return []; }

FunctionParam
  = name:Identifier value:(__ "=" __ ::Expression)? {
      return { name, value };
    }

FunctionBody = "{" __ ::SourceElements? __ "}"

なぜこれらは別々なのですか シヌケンスの::で、シヌケンスの匕数の結果が埗られないのはなぜですか」

それは同じこずではありたせんか MethodHead 、 FunctionParam 、 FunctionBodyなどのさたざたなナヌスケヌスの結果を簡単に理解できるように、より明確にしただけです。

耇数のタむプの倀を組み合わせお配列にする意味はありたせん。 それはタプルになりたすが、JSではほずんど圹に立ちたせん。

AST生成されたパヌサヌの最も䞀般的な結果を構築する堎合、私の意芋では、次のように曞く代わりに、 MethodHeadようなナヌスケヌスを単玔化したす。

MethodHead
  = modifiers:(::MethodModifier __)* ("function" __)? name:Identifier {
      return [ modifiers, name ];
    }

よく考えおみるず、ナヌスケヌスは単玔化されたすが、開発者が文法の実装方法やアクションによる結果の凊理方法のいずれかで間違いを犯す可胜性もあるので、これを眮くず思いたすmultipleSingleReturns デフォルト false のようなオプションの背埌にあるナヌスケヌスは、ここでの最善の行動ですこの機胜が実装されおいる堎合。

シヌケンスでが䜿甚されおいる堎合、結果は芪の配列に配列連結されたす

今ではそれは恐ろしい考えです。 これは明らかに、無関係な{return xs.pushx、xs}を取り陀くための応急修理です。

たた、 FunctionParametersような、より䞀般的なナヌスケヌスでも圹立ちたす。

// should always return `FunctionParam[]`
FunctionParameters
  = "(" __ ::FunctionParam #(__ "," __ ::FunctionParam)* __ ")"
  / "(" __ ")" { return []; }

パラメヌタ化されたルヌルを䜿甚しお䞀般的な方法で解決できたす

埌でどのように進めるかただわからないので、パラメヌタヌ化されたルヌルの前に単䞀の戻り倀を実装する必芁があるず考えおいたすテンプレヌトを䜿甚するのは奜きですが、 rule < .., .. > = ..を䜿甚するず倚くのノむズが远加されるようですPEG.jsの文法なので、構文を少し倉曎しおより適切に適合させるこずを考えおいたすが、それは別の問題です。

挔算子に䜿甚する単䞀文字シヌケンスはそれほど倚くないので、それらを無駄にするべきではありたせん。

それは本圓ですが、機䌚がこのようになっおいるずきにそれらを䜿甚しない堎合、それは同じように悪いこずです。

#は、前凊理ディレクティブを実装する䞀郚の蚀語で展開挔算子ずしお䜿甚されおいるこずを思い出した埌、このナヌスケヌスに䜿甚するこずを考えたした。これは、基本的にこのナヌスケヌスがここでカバヌしおいるこずです。

それで、 f = ::"a" { return "b" }は結果ずしお["a", "b"]を持぀べきですか

いいえ、コヌドブロックはパヌサヌによっおpushメ゜ッドを含む配列のようなオブゞェクトを返すこずが期埅されおいるためしたがっお、 f = ::"a" { return [ "b" ] } [ "b", "a" ]は結果ずしおpushSingleReturnsようなオプションの背埌にあるかどうかを理解する方が良いでしょうか このオプションがfalse デフォルトの堎合、単䞀の戻り倀を含むシヌケンスの埌にコヌドブロックがあるず、゚ラヌがスロヌされたす。

09を通過したす。 55䞊蚘の䟋で生成されたパヌサヌの7は、次のようになりたす。

そうではなく、 .たたは:に぀いおは蚀及されおいたせん。

申し蚳ありたせんが、それは私が䞎えられた䟋を曞き盎したずきに残された間違いでした。

たた、それは_䜿甚方法ではありたせん。 トヌクンの右偎たたは巊偎に配眮され、文法甚に1回遞択されたす。 右偎の堎合、メむンルヌルも_開始する必芁があり、その逆も同様です。

これは本圓に奜みの問題だず思いたすsmile 、この䟋を理解する方が簡単だったず思いたすが

number = _ ::value+ EOS
...
EOS = !.

蚘述された振る舞いがどのように結果を生み出すのかもわかりたせん。

この曎新されたコメントは、私が蚀おうずしおいるこずを理解するのに圹立ちたすかそうでない堎合は、あなたは䜕を理解しおいたせんか。

私は@ polkovnikov-phに同意したす。堎所によっお提䟛される倉曎は非垞に明癜ではなく、远加の゚ラヌの原因にすぎないずいうこずです。

シヌケンスでが䜿甚されおいる堎合、結果は芪の配列に配列連結されたす

文法start = #('a')䜕を返す必芁がありたすか 私が理解しおいる限り、圌は配列をフラット化するためのシンタックスシュガヌをどのように考えたしたか この挔算子は必芁ないず思いたす。 最も明癜な䜿甚法区切り文字を䜿甚したメンバヌリストの匏に぀いおは、特別な構文を䜜成するこずをお勧めしたす30ず私のフォヌクhttps://github.com/Mingun/pegjs/commit/db4b2b102982a53dbed1f579477c85c06f8b92e6を参照。

ルヌルに:: /ずずもにコヌドブロックがある堎合は、最初にそれを実行しおから、結果プッシュメ゜ッドを䜿甚したす

非垞に明癜でない行動。 文法゜ヌスのアクションは匏の埌に配眮され、通垞は匏の解析埌に呌び出されたす。 そしお突然、どういうわけかそれらは解析の前に呌び出され始めたす。 ラベルはどのように動䜜したすか

あなたがなんずか説明した残りの3぀のポむントは、圌らの明確な感芚が逃げ始めたした。 @ polkovnikov-phが、最初のケヌスず2番目のケヌスを区別するために説明に含たれおいる理由をどの皋床正確に蚘録したしたか 2぀の単玔なルヌルのみが実行されたす。

  1. :: 率盎に蚀っお、私はこの文字の遞択が奜きではない、ノむズが倚すぎる匏がsequenceこの文字でマヌクされたノヌド芁玠が戻るずいう事実に぀ながる前に
  2. シヌケンス内でそのような芁玠が1぀だけの堎合はその結果が返され、そうでない堎合は結果の配列が返されたす。

䟋

start =   'a' 'b'   'c'; // => ['a', 'b', 'c']
start = ::'a' 'b'   'c'; // => 'a'
start = ::'a' 'b' ::'c'; // => ['a', 'c']

倧きな䟋では、 ::から予想される内容を正確に説明しおおり、疑わしいナヌスケヌス # 、いく぀かの:: に぀いおは説明しおいたせん。

それは同じこずではありたせんか

それが私が求めおきたものです。 䞀般的な方法での説明は、読者にそれが本圓に同じものであるこずを確信させるので、通垞はより有甚です。 ご説明ありがずうございたす。 :)

私の意芋では、MethodHeadのようなナヌスケヌスを簡玠化するでしょう

しかし、代わりにオブゞェクトを䜜成しおみたせんか 衚蚘にはmodifiers:ずname:があり、結果のJSオブゞェクトのたたにしおおくず、すばらしいでしょう。

たた、開発者が間違いを犯す可胜性もありたす文法の実装方法、たたはアクションによる結果の凊理方法のいずれか。

圓初、私はこれに぀いお曞く぀もりでしたが、その埌、私には十分な難しい議論がないず刀断したした。 同じレベルのシヌケンスで耇数の::を蚱可したくありたせんフラグがあっおも。

たた、FunctionParametersのような、より䞀般的なナヌスケヌスで次のように蚘述したほうがよい堎合にも圹立ちたす。

しかし、それは同じこずです。 本圓に玠晎らしい構文はinter(FunctionParam, "," __)で、

inter a b = x:a xs:(b ::a)* { return xs.unshift(x), xs; }

ルヌル<..、..> = ..PEG.jsの文法に倚くのノむズを远加するようです

人々は<...>が型に䜿甚されるこずを期埅しおいたすが、この堎合、匕数は型ではありたせん。 最良の方法は、䜙分な文字をたったく含たないHaskellの方法です䞊蚘のinter参照。 ;を省略したPEG.js文法でこれがどのように盞互䜜甚するかはわかりたせん。 f a b = ...が郚分的に前の行に含たれる堎合がありたす。

前凊理ディレクティブを実装する䞀郚の蚀語で展開挔算子ずしお䜿甚されたす

はい、でも私はそれを賢く䜿いたいです。 配列に察しお提案されたpushアクションの代わりに、オブゞェクトに察するObject.assignアクションずしお、たたは空の文字列 eps に䞀臎するものずしお䜿甚したすが、その議論。 たずえば、

f = type:#"ident" name:$([a-z]i [a-z0-9_]i+)

入力"abc"に察しお{type: "ident", name: "abc"}を返したす。

いいえ、コヌドブロックは、プッシュメ゜ッドを含む配列のようなオブゞェクトを返すこずがパヌサヌによっお期埅されおいるためですしたがっお、f = :: "a" {return ["b"]} return ["b"、 " a "]結果ずしお、

O_O

これは本圓に奜みの問題だず思いたす

それだけでなく、パフォヌマンスも。 すべおのトヌクンの䞡偎に_がある堎合、空癜文字シヌケンスは末尟の文字シヌケンスずのみ䞀臎し、先行する_は䜕も䞀臎したせん。 parse$_ぞの远加の呌び出しに_が2倍倚いため、コヌドは長くなりたす。

@Mingun私は@futagozaは、蚭蚈空間を探求するず思いたす。 それは良いこずです、特にそれが公開されおいお、私たちが反察する機䌚がある堎合は:)

䞻なこずは、「なぜ」ず蚀うのではなく、「いいえそんなこずはありたせん」ず蚀うこずです。

image

f = type:#"ident" name:$([a-z]i [a-z0-9_]i+)は、入力"abc"に察しお{type: "ident", name: "abc"}を返したす。

いいえ、ハハ。 その構文は_wayyy_あたりにも魔法です。

最初に提案された@挔算子は、珟状のたたで

sequence
    = first:element rest:(whitespace next:element {return next;})*
    {
        return [first].concat(rest);
    }
    ;

特にそれよりも耇雑な堎合は、䜕床も䜕床も入力するのが面倒です。

ただし、 @挔算子を䜿甚するず、䞊蚘は単玔になりたす。

sequence = first:element rest:(whitespace @element)* { return [first].concat(rest); };

https://github.com/pegjs/pegjs/issues/235#issuecomment -66915879たたはhttps://github.com/pegjs/pegjs/issues/235#issuecomment -67544080のいずれかを䜿甚するず、さらに次のようになり

sequence = first:element rest:(whitespace @element)* => [first].concat(rest);
/* or */
sequence = first:element rest:(whitespace @element)* {=[first].concat(rest)};

...最初のものは私が非垞に郚分的です。

これは、簡単に達成できる䞋䜍互換性のある倉曎のようです誰かがすでにそれを行っおいるようです。

実際、私が間違っおいなければ、それは単なる小さなバンプである可胜性がありたす。 0.11.0@futagozaに぀いお考えるこずがあるかもしれたせん。

これをマスタヌに远加したした。 マルチプラッキングに::を䜿甚し、シングルプラッキングに@を䜿甚するこずを蚈画しおいたしたが、ラベル付きの::を䜿甚するず、非垞に芋苊しく混乱するように芋えたので、そのアむデアをぶら䞋げたした🙄

私はしばらく前にこれを自分で実装し始めたしたが、今たでそれを削陀し代わりに579を実行する必芁がありたす😆、バむトコヌドゞェネレヌタヌをMingunの実装に基づいおいたすhttps://github.com/Mingun/pegjs/commit/1c1c852bae91868eaa90d9bd9f7e4f722aa6435e 

ここで詊しおみるこずができたす https //pegjs.org/development/tryオンラむン゚ディタヌですが、PEG 0.11.0-devを䜿甚しおいたす

聖なるタヌンアラりンドタむム、バットマン。 玠晎らしい仕事@futagoza 、これは完璧に機胜したした-非垞に感謝しおいたす。 これはすでにnpmのdevタグにリリヌスされたしたか 私はそれでテストを始めたいです。

基本的な文法で詊しおみたい人は、この子犬をそこに入れお、 "abcd"ような入力をしおください。

foo
    = '"' @$bar '"'
    ;

bar
    = [abcd]*
    ;

これはすでにnpmのdevタグにリリヌスされたしたか

https://www.npmjs.com/package/pegjs/v/0.11.0-dev.325

こんにちは、これはes6があれば消える問題のひず぀であり、それ以降es6に远加された他のものにはこれらの文字が必芁です。 すでに実行できるこずに察しお挔算子を远加するこずは、非垞に逆効果です。

このチケットはマヌゞされたした

pattern:Pattern init:(_ "=" _ <strong i="7">@a</strong>:AssignmentExpression)?

誰もが本質的に理解し、パヌサヌの他の郚分が終了するず無料で提䟛されるes6の同じこずは次のずおりです。

pattern:Pattern init:(_ "=" _ a:AssignmentExpression)? => a

問題なのは、テストするず、このpluck実装はバグがあるように芋えたす。もちろん、これは決しおリリヌスされないブランチで修正されおいるため、これはクロヌズずマヌクされおいたす。

これがリリヌスされたバヌゞョンで修正されるたで、この問題、 @ futagozaを再床開いおください

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡