During the past few weeks, I've been working on prettier, which is a JavaScript pretty printer. We are approaching the phase where we can actually use it so this is a good time to explain how it works.

We're going to go through an example

if (!pretty) { makePretty() }

String -> AST

The first step is to take this string that represents some JavaScript and to parse it in order to get an AST out of it. An AST is a tree that represents the program. Using either Babylon or Flow we can parse this example and we get the following tree.

Program
  IfStatement
    UnaryExpression(!)
      Identifier(pretty)
    BlockStatement({})
      ExpressionStatement
        CallExpression
          Identifier(makePretty)

You can explore the full AST using astexplorer.net.

AST -> IR

Now that we have this tree, we want to print it. For each type of node like IfStatement, UnaryExpression... we're going to output something. In the case of prettier, this something is an intermediate representation called a document as described by the paper a prettier printer by Philip Wadler.

[
  group([
    "if (",
    group([ indent(2, [ softline, "!", "pretty" ]), softline ]),
    ")",
    " ",
    "{",
    indent(2, [ hardline, "makePretty", "()", ";" ]),
    hardline,
    "}"
  ]),
  hardline
];

You can play around with this representation on the prettier explorer.

IR -> String

The interesting thing about this representation is that it is the same no matter what the line-length is. The basic idea is that the primitives such as group, indent, softline encode the way they should look if they fit in the line or if they don't.

The most important primitive is group. The algorithm will first try to recursively print a group on a single line. If it doesn't fit the desired width, then it's going to break the outer group and keep going.

Then, we have primitives that behave differently if they are in a group that fits a single line or not: softline that does not print anything if the group it is contained in fits and a line otherwise. indent adds a level of indentation if it doesn't fit. If you are curious, you can look at the short list of available commands.

So, we just need to take this IR, send it through a solver along with the desired line width and we get the result!

HN6WzI9wFW

Conclusion

Hopefully this gives you a better idea of how a pretty printer that takes into account the desired width work.

If you liked this article, you might be interested in my Twitter feed as well.
 
  • http://www.syl.356688.com/ 三五豪侠传

    拜读大侠博客,感悟人生道理!

  • http://www.lin152.zengda.xin/ 增达网

    就是喜欢看你博客!

  • http://www.1688.zengda.xin/ 增达网

    增达网:

    群发软件免费下,无限广告免费发,

    百万流量免费享,十级提成免费拿。

    增达网注册网址:

    http://www.1688.zengda.xin/

  • http://www.zhengqi.zengda.xin/ 增达网

    从百度进来的,拜读一下贵站博文先
    丁酉年(鸡)二月十五 2017-3-12

  • http://www.a111888.zengda.xin/ 增达网

    群发软件免费下,无限广告免费发,

    百万流量免费享,十级提成免费拿。

    增达网免费注册网址:

    http://www.a111888.zengda.xin/

    QQ:2042970736

  • http://www.cxb.zengda.xin/ 增达网QQ-33092290

    真是时光荏苒!

  • http://www.1688.zengda.xin/ 增达网

    增达网:

    群发软件免费下,无限广告免费发,

    百万流量免费享,十级提成免费拿。

    ①:手机营销软件,QQ营销软件,博客营销软件,论坛营销软件,邮件营销软件,终生免费下载

    ②:独立二级域名,可建八个栏目,可以无限制发布自己的产品、项目、广告

    ③:您发布的广告在官网首页和全体免费会员网站显示,终生免费共享全站百万流量

    ④:逆向网赚,上线替下线发展,自动下滑,五五倍增,十级提成,不用推广也赚钱。

    注册网址:

    http://www.1688.zengda.xin/

    丁酉年(鸡)二月廿七 2017-3-24

  • http://www.52071789.zengda.ren/ 增达网QQ-52071789

    感觉不错哦,认真拜读咯!

  • http://www.870816071.356688.com/ QQ870816071

    富强、民主、文明、和谐,自由、平等、公正、法治, 爱国、敬业、诚信、友善。

  • http://www.yihuanghou.com/ 衣皇后

    学习使人进步,到此拜读!

  • http://www.a111888.zengda.xin/ 增达网

    增达网,终生只需99元:

    群发软件免费下,无限广告免费发,

    全站流量免费享,十级提成免费拿。

    逆向网赚,不用推广,照样赚钱!

    注册网址:

    http://www.a111888.zengda.xin/

    QQ:2042970736

    QQ群:274583838

    丁酉年(鸡)三月初五 2017-4-1

  • http://www.yihuanghou.com/?ic=wen 衣皇后

    从百度进来的,博客不错哦!

  • http://www.chun.yihuanghou.com/ 衣皇后

    对你爱爱爱不完,我可以天天月月年年看你博客到永远!

  • http://www.yihuanghou.com/ 衣皇后

    很荣幸来访您的博客,留言只是证明我来过!

  • http://www.hanjian.yihuanghou.com/ hanjian

    支持,只有支持才是访问博客的正确方式!

  • http://www.yihuanghou.com/ yihuanghou

    世事无常,但这个博客定能永保辉煌!

  • http://www.yihuanghou.com/ www.yihuanghou.com

    时间飞快,转眼年中就要到来,祝你天天愉快!

  • http://www.xuan.yihuanghou.com/ xuan

    我只想默默的拜读您的博客!

 

Related Posts

  • September 24, 2011 Javascript: Cyclic Object Detection (10)
    URLON.stringify() suffer from a problem, when passed an object that contains a cycle, it will never stop. This article shows 3 techniques in order to detect if an object is cyclical. Edit the object: Mark In order to detect a cycle in an object, the method we learn at school is to […]
  • November 4, 2013 Bitwise Truthiness (0)
    In this blog post, I explore another form of truthiness in Javascript. What happens if you use a bitwise operator on a value like 0|value or ~~value. Context We recently turned on the JSHint bitwise rule by default and the following code was caught. var isValid = false; for […]
  • November 25, 2015 Dirty-up and execute top-down (1)
    One common pattern when implementing user interface optimizations is to compute some value for a node where the computation involves looking at neighbor nodes and want to keep this value updated when the tree is mutated. On this article, I'm going to explain the pattern we implement […]
  • August 25, 2009 Test – Are you a Javascript Guru? (0)
    Javascript is a very flexible language, I made a compilation of some edge cases that you may have encountered while programming. The main goal is to point out some interesting specific behaviors. Concatenation 1] var result = [10] + 1; [10, 1] "101" 11 Explanation: The Array […]
  • November 4, 2013 Scroll Position with React (21)
    Dealing with scroll position when you insert content is usually a difficult problem to solve. We'll see how to use React life cycle methods to solve it elegantly. Insertion at the bottom The first example is to maintain the scroll position at the bottom when an element is inserted […]