1 package org.daisy.pipeline.css.sass.impl;
2
3 import java.util.HashMap;
4 import java.util.Map;
5
6 import java.util.regex.Matcher;
7 import java.util.regex.Pattern;
8
9 import org.unbescape.css.CssEscape;
10
11
12
13
14 public abstract class SassMapParser {
15
16 private static final String IDENT_RE = "[_a-zA-Z][_a-zA-Z0-9-]*";
17 private static final String STRING_RE = "'[^']*'|\"[^\"]*\"";
18 private static final String INTEGER_RE = "0|-?[1-9][0-9]*";
19 private static final Pattern VALUE_RE = Pattern.compile(
20 "(?<ident>" + IDENT_RE + ")|(?<string>" + STRING_RE + ")|(?<integer>" + INTEGER_RE + ")"
21 );
22 private static final Pattern KEY_VALUE_RE = Pattern.compile(
23 "(?<key>" + IDENT_RE + ")\\s*:\\s*(?<value>" + VALUE_RE.pattern() + ")"
24 );
25 private static final Pattern MAP_RE = Pattern.compile(
26 ("\\s*\\(\\s*(?:" + KEY_VALUE_RE.pattern() + "\\s*(?:,\\s*" + KEY_VALUE_RE.pattern() + "\\s*)*)?\\)\\s*")
27 .replaceAll("\\(\\?<[^>]+>", "(?:")
28 );
29
30 private SassMapParser() {}
31
32 public static Map<String,Object> parse(String expression) throws IllegalArgumentException {
33 if (!MAP_RE.matcher(expression).matches())
34 throw new IllegalArgumentException("Could not parse Sass map: " + expression);
35 Map<String,Object> map = new HashMap<>();
36 Matcher m = KEY_VALUE_RE.matcher(expression);
37 while (m.find()) {
38 String key = m.group("key");
39 String value = m.group("value");
40 boolean isString = false;
41 Matcher m2 = VALUE_RE.matcher(value);
42 if (!m2.matches())
43 throw new RuntimeException("Coding error");
44 String ident = m2.group("ident");
45 String string = m2.group("string");
46 String integer = m2.group("integer");
47 if (ident != null) {
48 if ("true".equals(ident))
49 map.put(key, Boolean.TRUE);
50 else if ("false".equals(ident))
51 map.put(key, Boolean.FALSE);
52 else
53 map.put(key, ident);;
54 } else if (string != null && !string.equals(""))
55 map.put(key, CssEscape.unescapeCss(string.substring(1, string.length() - 1)));
56 else if (integer != null && !integer.equals(""))
57 map.put(key, Integer.parseInt(integer));
58 else
59 throw new RuntimeException("Coding error");
60 }
61 return map;
62 }
63
64 public static Pattern asRegex() {
65 return MAP_RE;
66 }
67 }