Bring back the lexer

This commit is contained in:
Tristan Hume
2013-07-24 14:40:29 -04:00
parent 61a6deb43b
commit 76272a1afa
3 changed files with 90 additions and 4 deletions
+1
View File
@@ -46,6 +46,7 @@ module Liquid
end
require "liquid/version"
require 'liquid/lexer'
require 'liquid/parser'
require 'liquid/drop'
require 'liquid/extensions'
+74
View File
@@ -0,0 +1,74 @@
module Liquid
class Token
attr_accessor :type, :contents
def initialize(*args)
@type, @contents = args
end
def self.[](*args)
Token.new(*args)
end
def inspect
out = "<#{@type}"
out << ": \'#{@contents}\'" if contents
out << '>'
end
end
class Lexer
SPECIALS = {
'|' => :pipe,
'.' => :dot,
':' => :colon,
',' => :comma
}
def initialize(input)
@input = input.chars.to_a
end
def tokenize
@p = 0
@output = []
loop do
consume_whitespace
c = @input[@p]
# are we out of input?
return @output unless c
if identifier?(c)
@output << consume_identifier
elsif s = SPECIALS[c]
@output << Token[s]
@p += 1
end
end
end
def identifier?(c)
c =~ /^[\w\-]$/
end
def whitespace?(c)
c =~ /^\s$/
end
def consume_whitespace
while whitespace?(@input[@p])
@p += 1
end
end
def consume_identifier
str = ""
while identifier?(@input[@p])
str << @input[@p]
@p += 1
end
Token[:identifier, str]
end
end
end
+15 -4
View File
@@ -3,13 +3,24 @@ module Liquid
# it provides helpers and encapsulates state
class Parser
def initialize(input)
@tokens = tokenize(input)
l = Lexer.new(input)
@tokens = l.tokenize
@p = 0 # pointer to current location
end
def tokenize(input)
# "foo.bar | filter: baz, qux" becomes ["foo", ".", "bar", "|", "filter", ":", "baz", ",", "qux"]
input.split(/\b/).map {|tok| tok.strip}
def consume(type)
token = @tokens[@p]
if match && token.type != type
raise SyntaxError, "Expected #{match} but found #{@tokens[@p]}"
end
@p += 1
token
end
def look(type)
@tokens[@p].type == type
end
# === General Liquid parsing functions ===
end
end