Skip to content

Example Playing with Pug Grammar #5

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: externals/tag_name
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
120 changes: 55 additions & 65 deletions corpus/main.txt
Original file line number Diff line number Diff line change
@@ -1,93 +1,83 @@
===================================
Extends
===================================
//- page-a.pug
extends layout.pug
---
(source_file
(tbd)
(extends_statement
(path)))
========================
Multiline with dot
=========================

===================================
Includes
===================================
doctype html
html
include includes/head.pug
body
h1 My Site
p Welcome to my super lame site.
include includes/foot.pug
---
(source_file
(tbd)
(include_statement
(path))
(tbd)
(include_statement
(path)))

===================================
Link Tag
===================================
doctype html
html
head
title LogRocket Pug Example
link(rel='stylesheet' href='https://getbootstrap.com/docs/4.4/dist/css/bootstrap.min.css')
---
(source_file
(tbd)
(link_tag
(attribute
(attribute_name)
(quoted_attribute_value
(attribute_value)))
(attribute
(attribute_name)
(quoted_attribute_value
(attribute_value)))))
div.
Content here
more
content here,

===================================
Script Tag
===================================
script(src='/javascripts/app.js')
script(src='https://code.jquery.com/jquery-3.4.1.slim.min.js')
---

(source_file
(script_tag
(attribute
(attribute_name)
(quoted_attribute_value
(attribute_value))))
(script_tag
(attribute
(attribute_name)
(quoted_attribute_value
(attribute_value)))))
(tag
(tag_name)
(children
(content)
(content)
(content)
)
))

===================================
Script Tag - raw_text
===================================

script.
if (usingPug)
console.log('you are awesome')
else
console.log('use pug')

---
(source_file
(script_tag
(raw_text)))
(children
(content)
(content)
(content)
(content))))

===================================
Style Tag - raw_text
===================================

style(media='screen', lang='scss').
body {
background-color: {{themeColor}};
}

---
(source_file
(style_tag
(attribute
(attribute_name)
(quoted_attribute_value
(attribute_value)))
(attribute
(attribute_name)
(quoted_attribute_value
(attribute_value)))
(raw_text)))

===================================
Style Tag - html_input
===================================
html
head
title LogRocket Pug Example
style.
.bd-placeholder-img {
font-size: 1.125rem;
text-anchor: middle;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}

body
include includes/header.pug
---
(source_file
(style_tag
Expand Down
128 changes: 106 additions & 22 deletions grammar.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,128 @@ module.exports = grammar({
$._newline,
$._indent,
$._dedent,
$._tag_name,
// $._tag_name,
$._script_tag_name,
$._style_tag_name,
$.raw_text,
],

rules: {
// source_file: ($) =>
// repeat(
// choice(
// $.extends_statement,
// $.include_statement,
// $.link_tag,
// $.script_tag,
// $.style_tag,
// $.tbd
// )
// ),

// Start of changes
source_file: ($) =>
repeat(
choice(
$.extends_statement,
$.include_statement,
$.link_tag,
$.script_tag,
$.style_tag,
$.tbd
repeat(choice($.comment, $.tag, $.script_tag, $.style_tag, $.doctype)),
doctype: ($) =>
seq("doctype", alias(choice("html", "strict", "xml"), $.doctype_name)),
comment: ($) =>
seq(
"//",
optional($._comment_content),
$._newline,
optional(
seq($._indent, repeat(seq($._comment_content, $._newline)), $._dedent)
)
),

extends_statement: ($) => seq("extends", " ", $.path),

include_statement: ($) => seq("include", " ", $.path),

link_tag: ($) => seq("link", optional($._attributes)),

_comment_content: ($) => /[^ ][^\n]*/,
script_tag: ($) =>
seq("script", optional($._attributes), optional(seq(".", $._newline))),

// No ERROR nodes, without external token raw_text
// style_tag: ($) => seq("style", optional($._attributes)),
prec(
2,
seq(
"script",
optional(repeat1(choice($.id, $.class))),
optional($._attributes),
choice(
seq(":", $.tag),
$._content_after_dot,
seq(
optional(seq(" ", $._content_or_javascript)),
$._newline,
optional($.children)
)
)
)
),

// Produces many ERROR nodes
style_tag: ($) =>
prec(
2,
seq(
"style",
optional(repeat1(choice($.id, $.class))),
optional($._attributes),
choice(
seq(":", $.tag),
$._content_after_dot,
seq(
optional(seq(" ", $._content_or_javascript)),
$._newline,
optional($.children)
)
)
)
),
// seq("script", optional($._attributes), optional(seq(".", $._newline))),

tag: ($) =>
seq(
"style",
choice($.tag_name, $.id, $.class),
optional(repeat1(choice($.id, $.class))),
optional($._attributes),
optional(seq(".", $._newline, $.raw_text))
choice(
// NOT SURE WHY THIS DOESN'T MATCH script and style tags
// that are sub tags of tags
seq(":", $.tag),
$._content_after_dot,
seq(
optional(seq(" ", $._content_or_javascript)),
$._newline,
optional($.children)
)
)
),

tag_name: ($) => /\w(?:[-:\w]*\w)?/,
class: ($) => /\.[_a-z0-9\-]*[_a-z][_a-z0-9\-]*/i,
id: ($) => /#[\w-]+/,

// All the content after the dot expectes an indent!
_content_after_dot: ($) =>
seq(
".",
$._newline,
$._indent,
alias(repeat1(seq($._content_or_javascript, $._newline)), $.children),
$._dedent
),
javascript: ($) => /[^\n}]+/,
content: ($) => /[^\n\{]+/,
_content_or_javascript: ($) =>
repeat1(choice(seq("{{", $.javascript, "}}"), $.content)),
children: ($) => seq($._indent, repeat1($._children_choice), $._dedent),
pipe_content: ($) =>
seq("|", optional($._content_or_javascript), $._newline),
_children_choice: ($) => choice($.pipe_content, $.tag),
// attribute_name: defined differently in reference

// End of changes

extends_statement: ($) => seq("extends", " ", $.path),

include_statement: ($) => seq("include", " ", $.path),

link_tag: ($) => seq("link", optional($._attributes)),

path: ($) => seq(repeat1(choice(/\w/, "/")), ".", repeat1(/\w/)),

Expand Down
11 changes: 11 additions & 0 deletions notes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Notes on Pug Grammar Parsing

Pug uses whitespace to denote hierarchy. This can't be totally captured by regex. Some of this must be captured by the indent/dedent methods.


# Reference Projects

- Best! https://github.com/parascent/tree-sitter-pug
- https://github.com/zealot128/tree-sitter-pug

- forks: https://github.com/zealot128/tree-sitter-pug/forks
Loading