| 2013 | const TOKEN_BLANK = /\s+/y; |
| 2014 | class FluentResource { |
| 2015 | constructor(source) { |
| 2016 | this.body = []; |
| 2017 | RE_MESSAGE_START.lastIndex = 0; |
| 2018 | let cursor = 0; |
| 2019 | while (true) { |
| 2020 | let next = RE_MESSAGE_START.exec(source); |
| 2021 | if (next === null) { |
| 2022 | break; |
| 2023 | } |
| 2024 | cursor = RE_MESSAGE_START.lastIndex; |
| 2025 | try { |
| 2026 | this.body.push(parseMessage(next[1])); |
| 2027 | } catch (err) { |
| 2028 | if (err instanceof SyntaxError) { |
| 2029 | continue; |
| 2030 | } |
| 2031 | throw err; |
| 2032 | } |
| 2033 | } |
| 2034 | function test(re) { |
| 2035 | re.lastIndex = cursor; |
| 2036 | return re.test(source); |
| 2037 | } |
| 2038 | function consumeChar(char, errorClass) { |
| 2039 | if (source[cursor] === char) { |
| 2040 | cursor++; |
| 2041 | return true; |
| 2042 | } |
| 2043 | if (errorClass) { |
| 2044 | throw new errorClass(`Expected ${char}`); |
| 2045 | } |
| 2046 | return false; |
| 2047 | } |
| 2048 | function consumeToken(re, errorClass) { |
| 2049 | if (test(re)) { |
| 2050 | cursor = re.lastIndex; |
| 2051 | return true; |
| 2052 | } |
| 2053 | if (errorClass) { |
| 2054 | throw new errorClass(`Expected ${re.toString()}`); |
| 2055 | } |
| 2056 | return false; |
| 2057 | } |
| 2058 | function match(re) { |
| 2059 | re.lastIndex = cursor; |
| 2060 | let result = re.exec(source); |
| 2061 | if (result === null) { |
| 2062 | throw new SyntaxError(`Expected ${re.toString()}`); |
| 2063 | } |
| 2064 | cursor = re.lastIndex; |
| 2065 | return result; |
| 2066 | } |
| 2067 | function match1(re) { |
| 2068 | return match(re)[1]; |
| 2069 | } |
| 2070 | function parseMessage(id) { |
| 2071 | let value = parsePattern(); |
| 2072 | let attributes = parseAttributes(); |