feat: init block tokenier
This commit is contained in:
commit
ea46c548eb
53
README.incd
Normal file
53
README.incd
Normal file
|
@ -0,0 +1,53 @@
|
|||
=== IncDown Parser ===
|
||||
|
||||
Turn IncDown into HTML.
|
||||
First attempt at a parser, written in [Fennel](https://fennel-lang.org/)
|
||||
|
||||
Input -> Block Tokenizer (Lexxing?) -> Inline Lexer -> Rendered?
|
||||
|
||||
I think that's how this will work
|
||||
|
||||
= Status =
|
||||
Block Tokenizer currently working, except for the code fences
|
||||
|
||||
The code fence regex is wrong, since it looks for the entire block, instead of just the first line. Not quite sure how to use a different regex or "swap modes" into code fence mode such that everything until `}}}` is part of the codeblock.
|
||||
|
||||
-----
|
||||
|
||||
= Blocks =
|
||||
Each block is generally seperated by \n
|
||||
This means we require lookahead?
|
||||
|
||||
Block parser breaks the text up into blocks:
|
||||
- Metadata
|
||||
- %attribute
|
||||
- Paragraphs
|
||||
- Any character not claimed by the others?
|
||||
- Lists
|
||||
- # or - started lines (any number of spaces)
|
||||
- Headings
|
||||
- = start and ending
|
||||
- Quotes
|
||||
- > start (any number of spaces)
|
||||
- Images
|
||||
- ![Alt](Link)
|
||||
- Foot notes
|
||||
- _[#] and then %footnote ??? need to think about this one
|
||||
- Code blocks
|
||||
- {{{code hint\n code}}}
|
||||
- Section breaks
|
||||
- 5 continuous - on a single line
|
||||
|
||||
= Inline =
|
||||
- Decorations
|
||||
- Links
|
||||
- Images? Maybe images can't be inlined?
|
||||
- Footnotes
|
||||
|
||||
== Future Work ==
|
||||
|
||||
If this goes well may attempt to write:
|
||||
- Blog engine in Fennel on top of this
|
||||
- TreeSitter Grammar
|
||||
- NVim Theme (does this come free with treesitter?)
|
||||
- Pandoc Grammer? (Seems unlikely)
|
26
flake.lock
Normal file
26
flake.lock
Normal file
|
@ -0,0 +1,26 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1700959420,
|
||||
"narHash": "sha256-mzRwNDwt8A4Q1PPDPBk0wbv24kX7FqbSFFj3Mh4ykk4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "b7a2c41788518c080ef3b51631f78985cfdd0228",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
33
flake.nix
Normal file
33
flake.nix
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
description = "IncDown Parser written in Fennel";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:nixos/nixpkgs";
|
||||
};
|
||||
|
||||
outputs = { self, nixpkgs }:
|
||||
let
|
||||
pkgs = nixpkgs.legacyPackages.x86_64-linux;
|
||||
in
|
||||
{
|
||||
defaultPackage.x86_64-linux = pkgs.stdenv.mkDerivation {
|
||||
name = "incd";
|
||||
src = ./.;
|
||||
buildInputs = [ pkgs.luaPackages.fennel pkgs.fd ];
|
||||
installPhase = ''
|
||||
mkdir -p $out/
|
||||
|
||||
cp -r ./ $out
|
||||
'';
|
||||
};
|
||||
devShell.x86_64-linux = pkgs.mkShell {
|
||||
buildInputs = [
|
||||
pkgs.lua
|
||||
pkgs.luaPackages.fennel
|
||||
];
|
||||
shellHook = ''
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
|
91
main.fnl
Normal file
91
main.fnl
Normal file
|
@ -0,0 +1,91 @@
|
|||
(local fennel (require :fennel))
|
||||
(fn _G.pp [x] (print (fennel.view x)))
|
||||
|
||||
(local block-grammar
|
||||
[{:name "Section"
|
||||
:sp-chars ["-----"]
|
||||
:regex "%-%-%-%-%-"}
|
||||
{:name "Image"
|
||||
:sp-chars ["!["]
|
||||
:regex "!%[.-%]%(.-%)\n"}
|
||||
{:name "Quote"
|
||||
:any-space true
|
||||
:sp-chars [">"]
|
||||
:regex "%s*>.-\n"}
|
||||
{:name "Metadata"
|
||||
:sp-chars ["%"]
|
||||
:regex "%%.-%s.-\n"}
|
||||
{:name "Code"
|
||||
:sp-chars ["{{{"]
|
||||
:regex "{{{.-\n.-}}}\n"}
|
||||
{:name "Header"
|
||||
:sp-chars ["="]
|
||||
:end-also true
|
||||
:regex "=+[^=]-=+\n"}
|
||||
{:name "List"
|
||||
:sp-chars ["#" "-"]
|
||||
:any-space true
|
||||
:continue-until-no-match true
|
||||
:regex "%s*[%-%#].-\n"}
|
||||
{:name "Paragraph"
|
||||
:regex ".-\n"}])
|
||||
|
||||
(fn parse-blocks [{: contents : grammar}]
|
||||
(var current 1)
|
||||
(var blocks [])
|
||||
(var current-block-type nil)
|
||||
(var current-block "")
|
||||
(while (< current (- (length contents) 1))
|
||||
(var matched false)
|
||||
(let [start (string.find contents "\n" current)
|
||||
current-str (string.sub contents current start)]
|
||||
(each [_ g (ipairs grammar) &until matched]
|
||||
(print (.. "Current: " current))
|
||||
(print (.. "Start: " start))
|
||||
(print (.. "Current-str: " current-str))
|
||||
(print (.. "checking regex: " (. g :regex)))
|
||||
(print (string.match current-str (. g :regex)))
|
||||
(let [m (string.match current-str (. g :regex))]
|
||||
(if (not (= nil m)) ; This is a match or move on
|
||||
(do
|
||||
(set matched true)
|
||||
(if (or ; We append to the current block
|
||||
(= nil current-block-type) ; If it's the first block
|
||||
(and (= (. g :name) current-block-type) ; Or it matches the previous block,
|
||||
(not (= (. g :name) "Paragraph")))) ; and it's not a paragraph
|
||||
(do
|
||||
(set current-block-type (. g :name))
|
||||
(set current-block (.. current-block current-str "\n"))
|
||||
(print (.. "Set current-block: " current-block)))
|
||||
(do ; Or we start a new block
|
||||
(table.insert blocks {:type current-block-type
|
||||
:block current-block})
|
||||
(print (.. "Inserted into table: " current-block))
|
||||
(set current-block current-str)
|
||||
(print (.. "New current-block: " current-str))
|
||||
(set current-block-type (. g :name))))
|
||||
(set current (+ 1 start))))))))
|
||||
(print "End of file reached, unloading current")
|
||||
(table.insert blocks {:type current-block-type
|
||||
:block current-block})
|
||||
blocks)
|
||||
|
||||
; Each \n point
|
||||
; Read contents from current to next
|
||||
; If it matches any of the block structures
|
||||
; Add to that blocks current
|
||||
; If the block is complete, add it to the blocks list
|
||||
; If not, continue with block descent
|
||||
|
||||
; (let [start (string.find "This is a paragraph.\n- This\n- List\n- Should\n- Be One\n" "\n" 1)]
|
||||
; (print start))
|
||||
|
||||
(string.match "{{{python\n return arg + 1\n}}}\n" "{{{.-\n.-}}}\n")
|
||||
|
||||
; (= [{:type "Paragraph"
|
||||
; :block "This is a paragraph."
|
||||
; {:type "List"
|
||||
; :block "- This\n- List\n- Should\n- Be One"}
|
||||
(parse-blocks
|
||||
{:contents "= Big Test File =\n%title Some Title\nThis is a paragraph.\n- This\n- List\n- Should\n- Be One\n-----\n= A new Section Title =\n![Has an Image](file:///link-to-image.png)\n> With some quoted matieral\n>Across multiple lines\n > and different indents\n\n{{{python \n def file(arg, other):\n rturn arg + other\n}}}\n\nMore Paragraphs\n"
|
||||
:grammar block-grammar})
|
Loading…
Reference in a new issue