package liquid_parser

  1. Overview
  2. Docs

Source file parser.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
open Base
open Liquid_syntax
open Tools
open Syntax
open Parser_tools

type parse_result = (ast * lex_token list) option

let is_parsable_test =
  function
  | If :: _ | Case :: _ | Unless :: _ -> true
  | _ -> false


let parse_test block_parser = function
  | tokens when is_parsable_test tokens ->
    let bounds = Bounds.find_bounds tokens 0 in
    let chunks = bounds |> Bounds.bounds_to_chunks tokens in
    let stop_point = Bounds.stop_point_from_bounds bounds in
    let rest = sub_list_suffix tokens stop_point in
    Some (Test.parse_test_chain block_parser chunks, rest)
  | _ -> None

let parse_capture block_parser = function
  | Tokens.Capture :: LexValue (LexId id) :: EOS :: tl ->
    let (body, rest) = parse_single_body Capture tl in
    let capture = Capture (join id, block_parser body) in
    Some (capture, rest)
  | _ -> None


let parse_cycle _ all_tokens =
  let parse_state name tokens =
    let (state, rest) = scan_until_eos tokens in
    let rec aux acc = function
      | LexValue (LexString s) :: Comma :: tl -> aux (acc @ [s]) tl
      | LexValue (LexString s) :: _ -> acc @ [s]
      | _ -> []
    in
    Some (Cycle (name, aux [] state), rest)
  in

  match all_tokens with
  | Tokens.Cycle :: LexValue (LexString name) :: Colon :: tl -> parse_state (Some name) tl
  | Cycle :: tl -> parse_state None tl
  | _ -> None

let parse_other _ = function
  | LexText t :: tl -> Some (Text t, tl)
  | Newline :: tl -> Some (Text "\n", tl)
  | EOS :: tl -> Some (Nothing, tl)
  | LexBreak :: tl -> Some (Break, tl)
  | LexContinue :: tl -> Some (Continue, tl)
  | _ -> None

let parse_for = For.parse_for
let parse_tablerow = For.parse_tablerow
let parse_paginate = For.parse_paginate
let parse_theme = Theme.parse_theme
let parse_expression = Expression.parse_expression
let parse_assignment = Expression.parse_assignment

let rec first_successful block_parser tokens =
  function
  | parser :: other_parsers -> (
    match parser block_parser tokens with
    | Some (got, rest) -> Some (got, rest)
    | None -> first_successful block_parser tokens other_parsers
  )
  | _ -> None


let rec parse init_tokens =
  let folder block tokens =
    match parse_one tokens with
    | Some (got, rest) ->
      Next (block @ (if got != Nothing then [got] else []), rest)
    | None ->
      Stop (block)
  in

  Block (unfold [] init_tokens folder)
and parse_one tokens =
  let parsers =
    [ parse_assignment
    ; parse_test
    ; parse_capture
    ; parse_for
    ; parse_tablerow
    ; parse_cycle
    ; parse_theme
    ; parse_paginate
    ; parse_expression
    ; parse_other ] in

  first_successful parse tokens parsers
OCaml

Innovation. Community. Security.