1
0
mirror of https://github.com/danog/liquid.git synced 2024-12-02 16:27:45 +01:00
liquid/expressions/scanner.rl

113 lines
2.3 KiB
Plaintext
Raw Normal View History

2017-06-25 22:21:31 +02:00
// Adapted from https://github.com/mhamrah/thermostat
2017-06-26 15:33:07 +02:00
package expressions
2017-06-25 18:36:28 +02:00
2017-06-25 22:21:31 +02:00
import "fmt"
2017-06-25 18:36:28 +02:00
import "strconv"
2017-06-25 22:21:31 +02:00
%%{
machine expression;
write data;
access lex.;
variable p lex.p;
variable pe lex.pe;
}%%
2017-06-25 18:36:28 +02:00
2017-06-25 22:21:31 +02:00
type lexer struct {
data []byte
p, pe, cs int
ts, te, act int
val func(Context) interface{}
}
2017-06-26 04:00:36 +02:00
func (l* lexer) token() string {
return string(l.data[l.ts:l.te])
}
2017-06-25 22:21:31 +02:00
func newLexer(data []byte) *lexer {
lex := &lexer{
data: data,
pe: len(data),
}
%% write init;
return lex
}
func (lex *lexer) Lex(out *yySymType) int {
eof := lex.pe
tok := 0
2017-06-25 18:36:28 +02:00
%%{
2017-06-26 02:20:58 +02:00
action Bool {
tok = LITERAL
2017-06-26 04:00:36 +02:00
out.val = lex.token() == "true"
fbreak;
2017-06-26 02:20:58 +02:00
}
2017-06-25 22:21:31 +02:00
action Ident {
tok = IDENTIFIER
2017-06-26 04:00:36 +02:00
out.name = lex.token()
2017-06-25 22:21:31 +02:00
fbreak;
}
2017-06-26 13:50:53 +02:00
action Int {
tok = LITERAL
n, err := strconv.ParseInt(lex.token(), 10, 64)
if err != nil {
panic(err)
}
out.val = int(n)
2017-06-26 13:50:53 +02:00
fbreak;
}
action Float {
2017-06-26 02:20:58 +02:00
tok = LITERAL
2017-06-26 04:00:36 +02:00
n, err := strconv.ParseFloat(lex.token(), 64)
2017-06-25 22:21:31 +02:00
if err != nil {
panic(err)
}
out.val = n
2017-06-25 22:21:31 +02:00
fbreak;
}
action String {
tok = LITERAL
// TODO unescape \x
out.val = string(lex.data[lex.ts+1:lex.te-1])
fbreak;
}
2017-06-26 04:00:36 +02:00
action Relation { tok = RELATION; out.name = lex.token(); fbreak; }
2017-06-25 22:21:31 +02:00
2017-06-28 21:33:04 +02:00
# TODO this allows medial '-' because some themes allow it in properties.
# Is this a general feature of Liquid identifiers, or is it limited to
# property names?
ident = (alpha | '_') . (alnum | '_' | '-')* ;
int = '-'? digit+ ;
float = '-'? (digit+ '.' digit* | '.' digit+) ;
string = '"' (any - '"')* '"' | "'" (any - "'")* "'" ; # TODO escapes
2017-06-25 22:21:31 +02:00
main := |*
2017-06-26 21:36:05 +02:00
"%assign" => { tok = ASSIGN; fbreak; };
2017-06-27 19:18:01 +02:00
"%loop" => { tok = LOOP; fbreak; };
int => Int;
2017-06-26 13:50:53 +02:00
float => Float;
string => String;
2017-06-26 02:20:58 +02:00
("true" | "false") => Bool;
2017-06-26 15:06:55 +02:00
"==" => { tok = EQ; fbreak; };
2017-06-27 23:54:24 +02:00
"!=" => { tok = NEQ; fbreak; };
(">=" | "<=") => Relation;
"and" => { tok = AND; fbreak; };
"or" => { tok = OR; fbreak; };
"contains" => { tok = CONTAINS; fbreak; };
"for" => { tok = FOR; fbreak; };
2017-06-27 19:18:01 +02:00
"in" => { tok = IN; fbreak; };
2017-06-27 03:32:08 +02:00
ident ':' => { tok = KEYWORD; out.name = string(lex.data[lex.ts:lex.te-1]); fbreak; };
2017-06-26 02:20:58 +02:00
ident => Ident;
2017-06-25 22:21:31 +02:00
space+;
2017-06-26 15:06:55 +02:00
any => { tok = int(lex.data[lex.ts]); fbreak; };
2017-06-25 22:21:31 +02:00
*|;
2017-06-25 18:36:28 +02:00
write exec;
2017-06-25 22:21:31 +02:00
}%%
2017-06-25 18:36:28 +02:00
2017-06-25 22:21:31 +02:00
return tok
2017-06-25 18:36:28 +02:00
}
2017-06-25 22:21:31 +02:00
func (lex *lexer) Error(e string) {
fmt.Println("error:", e)
}