【问题标题】:how to write a simple peg grammar for a liquid-like templating language?如何为类似液体的模板语言编写简单的 peg 语法?
【发布时间】:2019-05-12 13:34:50
【问题描述】:

编辑:您可以在这里关注进度:https://github.com/simple-updates/template

我正在使用peg.js 并尝试编写一些可以解释模板的东西,例如:

hello {{ "world" }}
{% if a %}
  good {{ a }}
{% else %}
  bad
{% endif %}

我尝试了很多东西,但假设这是我的起点:

Template
  = ws markup ws

ws = " "*

open_interpolation = "{{"
close_interpolation = "}}"
open_tag = "{%"
close_tag = "%}"

char = . // ?

markup =
  (open_tag tag:char* close_tag)
  { return { 'tag': tag.join('') } } /
  (open_interpolation interpolation:char* close_interpolation)
  { return { 'interpolation': interpolation.join('') } } /
  chars:char*
  { return { 'chars': chars.join('') } }

例如,当我尝试使用字符串 {{ test }} 时,它只会将其解释为字符而不是插值。

知道我该怎么做吗?

(显然嵌套“标记”会更复杂)

【问题讨论】:

    标签: javascript parsing expression peg pegjs


    【解决方案1】:

    这样的开始怎么样:

    Template
     = Atom*
    
    Atom
     = IfTag
     / Interpolation
     / [^{]
     / !"{%" !"{{" "{"
    
    Interpolation
     = "{{" _ Expression _ "}}"
    
    IfTag
     = If Template ( Else Template )? EndIf
    
    If
     = "{%" _ "if" _ Expression _ "%}"
    
    Else
     = "{%" _ "else" _ "%}"
    
    EndIf
     = "{%" _ "endif" _ "%}"
    
    Expression
     = "\"" [^"]* "\""
     / [a-zA-Z]+
     / [0-9]+
    
    _
     = [ \t\n\r]*
    

    这里的棘手部分是!"{%" !"{{" "{" 替代Atom 生产,其内容如下:

    当当前位置前面看不到“{%”和“{{”时,匹配单个“{”

    【讨论】:

    • 谢谢,我一定会重用你的一些想法(_ 代表空白,特别是 [^{] / !"{%" !"{{" "{")。如果你想跟上进度,解析器几乎完成了:github.com/simple-updates/template ( template.pegjs 文件)
    • 试过了,想了想我真的不知道和(!"{{" !"{%" .)有什么区别
    • !"{{" !"{%" .[^{] / !"{%" !"{{" "{" 之间(可能)没有区别。但是对于后者,我更清楚发生了什么。而且我还怀疑为后者生成的解析器会(有点)性能更好,因为它需要的前瞻比!"{{" !"{%" .
    【解决方案2】:

    好吧,我还没有处于任何嵌套部分,但我的标签/插值工作正常

    关键是那些!not_something value

    当前语法:

    {
        function j(value) {
            return value.join('')
        }
    }
    
    Template
      = ws markup:markup ws { return markup }
    
    ws = " "*
    
    open_interpolation = "{{"
    close_interpolation = "}}"
    open_tag = "{%"
    close_tag = "%}"
    
    value = .
    
    not_close_interpolation =
        ws !close_interpolation value:value ws { return value }
    
    not_close_tag =
        ws !close_tag value:value ws { return value }
    
    not_open_tag_or_interpolation =
        !open_interpolation !open_tag value:value { return value }
    
    markup =
        (
          open_interpolation interpolation:not_close_interpolation+ close_interpolation {
              return { 'interpolation': j(interpolation) }
          } /
          open_tag tag:not_close_tag+ close_tag {
              return { 'tag': j(tag) }
          } /
          value:not_open_tag_or_interpolation+ { return j(value) }
        )+
    

    【讨论】:

      猜你喜欢
      • 2012-07-12
      • 2021-12-16
      • 2010-11-30
      • 1970-01-01
      • 2010-09-07
      • 2022-07-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多