glimr/loom/lexer

Template Lexer

Converts template source text into a stream of tokens. Recognizes variables, directives, components, and plain text for the parser to process.

Types

Component and element tags support several attribute flavors that need different code generation strategies. Separating them here lets the generator handle each without re-parsing attribute strings.

pub type ComponentAttr {
  StringAttr(name: String, value: String)
  ExprAttr(name: String, value: String)
  BoolAttr(name: String)
  ClassAttr(value: String)
  StyleAttr(value: String)
  LmIf(condition: String, line: Int)
  LmElseIf(condition: String, line: Int)
  LmElse
  LmFor(
    collection: String,
    items: List(String),
    loop_var: option.Option(String),
    line: Int,
  )
  LmOn(
    event: String,
    modifiers: List(String),
    handler: String,
    line: Int,
  )
  LmModel(prop: String, line: Int)
  LmShow(condition: String, line: Int)
}

Constructors

  • StringAttr(name: String, value: String)
  • ExprAttr(name: String, value: String)
  • BoolAttr(name: String)
  • ClassAttr(value: String)
  • StyleAttr(value: String)
  • LmIf(condition: String, line: Int)
  • LmElseIf(condition: String, line: Int)
  • LmElse
  • LmFor(
      collection: String,
      items: List(String),
      loop_var: option.Option(String),
      line: Int,
    )
  • LmOn(
      event: String,
      modifiers: List(String),
      handler: String,
      line: Int,
    )

    l-on:event handler (e.g., l-on:click=“count = count + 1”)

  • LmModel(prop: String, line: Int)

    l-model two-way binding (e.g., l-model=“name”)

  • LmShow(condition: String, line: Int)

    l-show conditional visibility (e.g., l-show=“active”)

Surfacing specific error variants allows the compiler to produce actionable messages with position info, so users can quickly locate malformed template syntax.

pub type LexerError {
  UnterminatedExpression(position: Int)
  EmptyExpression(position: Int)
  UnterminatedDirective(position: Int)
  InvalidDirective(directive: String, position: Int)
  InvalidLmForSyntax(content: String, position: Int)
  UnterminatedComponent(position: Int)
  InvalidComponentSyntax(content: String, position: Int)
  InvalidPropsDirective(content: String, line: Int)
  InvalidImportDirective(content: String, line: Int)
  UnterminatedPropsDirective(line: Int)
  UnterminatedImportDirective(line: Int)
}

Constructors

  • UnterminatedExpression(position: Int)
  • EmptyExpression(position: Int)
  • UnterminatedDirective(position: Int)
  • InvalidDirective(directive: String, position: Int)
  • InvalidLmForSyntax(content: String, position: Int)
  • UnterminatedComponent(position: Int)
  • InvalidComponentSyntax(content: String, position: Int)
  • InvalidPropsDirective(content: String, line: Int)
  • InvalidImportDirective(content: String, line: Int)
  • UnterminatedPropsDirective(line: Int)
  • UnterminatedImportDirective(line: Int)

The parser needs a structured representation of template syntax to build the AST. Each variant captures a distinct construct so the parser can pattern match on it directly.

pub type Token {
  Text(String)
  Variable(name: String, line: Int)
  RawVariable(name: String, line: Int)
  Slot(name: option.Option(String))
  SlotDef(name: option.Option(String))
  SlotDefEnd
  Attributes
  Component(
    name: String,
    attributes: List(ComponentAttr),
    self_closing: Bool,
  )
  ComponentEnd(name: String)
  Element(
    tag: String,
    attributes: List(ComponentAttr),
    self_closing: Bool,
  )
  ElementEnd(tag: String)
  ImportDirective(import_str: String, line: Int)
  PropsDirective(props: List(#(String, String)), line: Int)
}

Constructors

  • Text(String)
  • Variable(name: String, line: Int)
  • RawVariable(name: String, line: Int)
  • Slot(name: option.Option(String))
  • SlotDef(name: option.Option(String))
  • SlotDefEnd
  • Attributes
  • Component(
      name: String,
      attributes: List(ComponentAttr),
      self_closing: Bool,
    )
  • ComponentEnd(name: String)
  • Element(
      tag: String,
      attributes: List(ComponentAttr),
      self_closing: Bool,
    )
  • ElementEnd(tag: String)
  • ImportDirective(import_str: String, line: Int)

    @import directive for importing types/modules

  • PropsDirective(props: List(#(String, String)), line: Int)

    @props directive declaring template parameters

Values

pub fn tokenize(input: String) -> Result(List(Token), LexerError)

Entry point for the lexer. Wraps the recursive loop so callers don’t need to supply internal state like position, line number, or the tag stack.

Search Document