mirror of
https://github.com/Shopify/liquid.git
synced 2026-09-12 23:40:45 -07:00
Fancy StringScanner based lexer
This commit is contained in:
+19
-51
@@ -23,13 +23,17 @@ module Liquid
|
|||||||
':' => :colon,
|
':' => :colon,
|
||||||
',' => :comma
|
',' => :comma
|
||||||
}
|
}
|
||||||
|
IDENTIFIER = /[\w\-]+/
|
||||||
|
SINGLE_STRING_LITERAL = /'[^\']*'/
|
||||||
|
DOUBLE_STRING_LITERAL = /"[^\"]*"/
|
||||||
|
INTEGER_LITERAL = /-?\d+/
|
||||||
|
FLOAT_LITERAL = /-?\d+(?:\.\d+)?/
|
||||||
|
|
||||||
def initialize(input)
|
def initialize(input)
|
||||||
@input = input
|
@ss = StringScanner.new(input)
|
||||||
end
|
end
|
||||||
|
|
||||||
def tokenize
|
def tokenize
|
||||||
@p = 0
|
|
||||||
@output = []
|
@output = []
|
||||||
|
|
||||||
loop do
|
loop do
|
||||||
@@ -41,62 +45,26 @@ module Liquid
|
|||||||
|
|
||||||
def next_token
|
def next_token
|
||||||
consume_whitespace
|
consume_whitespace
|
||||||
c = @input[@p]
|
return if @ss.eos?
|
||||||
return nil unless c
|
|
||||||
|
|
||||||
if identifier?(c)
|
case
|
||||||
identifier
|
when t = @ss.scan(IDENTIFIER) then Token[:id, t]
|
||||||
elsif c == '"' || c == '\''
|
when t = @ss.scan(SINGLE_STRING_LITERAL) then Token[:string, t]
|
||||||
string_literal
|
when t = @ss.scan(DOUBLE_STRING_LITERAL) then Token[:string, t]
|
||||||
elsif s = SPECIALS[c]
|
when t = @ss.scan(INTEGER_LITERAL) then Token[:integer, t]
|
||||||
@p += 1
|
when t = @ss.scan(FLOAT_LITERAL) then Token[:float, t]
|
||||||
Token[s]
|
|
||||||
else
|
else
|
||||||
|
c = @ss.getch
|
||||||
|
if s = SPECIALS[c]
|
||||||
|
return Token[s]
|
||||||
|
end
|
||||||
|
|
||||||
raise SyntaxError, "Unexpected character #{c}."
|
raise SyntaxError, "Unexpected character #{c}."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def identifier?(c)
|
|
||||||
c =~ /^[\w\-]$/
|
|
||||||
end
|
|
||||||
|
|
||||||
def whitespace?(c)
|
|
||||||
c =~ /^\s$/
|
|
||||||
end
|
|
||||||
|
|
||||||
def consume
|
|
||||||
c = @input[@p]
|
|
||||||
@p += 1
|
|
||||||
c
|
|
||||||
end
|
|
||||||
|
|
||||||
def consume_whitespace
|
def consume_whitespace
|
||||||
while whitespace?(@input[@p])
|
@ss.skip(/\s*/)
|
||||||
@p += 1
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def identifier
|
|
||||||
str = ""
|
|
||||||
while identifier?(@input[@p])
|
|
||||||
str << @input[@p]
|
|
||||||
@p += 1
|
|
||||||
end
|
|
||||||
Token[:id, str]
|
|
||||||
end
|
|
||||||
|
|
||||||
def string_literal
|
|
||||||
quote = consume()
|
|
||||||
|
|
||||||
start = @p
|
|
||||||
while @input[@p] != quote
|
|
||||||
@p += 1
|
|
||||||
end
|
|
||||||
@p += 1 # closing quote
|
|
||||||
|
|
||||||
Token[:string, @input[start..(@p-2)]]
|
|
||||||
end
|
|
||||||
|
|
||||||
def number_literal
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user