123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172 |
- /* description: Parses expressions. */
-
- %options case-insensitive
-
- /* lexical grammar */
- %lex
- %%
- \s+ /* skip whitespace */
-
- (\-(webkit|moz)\-)?calc\b return 'CALC';
-
- [a-z][a-z0-9-]*\s*\((?:(?:\"(?:\\.|[^\"\\])*\"|\'(?:\\.|[^\'\\])*\')|\([^)]*\)|[^\(\)]*)*\) return 'FUNCTION';
-
- "*" return 'MUL';
- "/" return 'DIV';
- "+" return 'ADD';
- "-" return 'SUB';
-
- ([0-9]+("."[0-9]+)?|"."[0-9]+)em\b return 'LENGTH'; // em
- ([0-9]+("."[0-9]+)?|"."[0-9]+)ex\b return 'LENGTH'; // ex
- ([0-9]+("."[0-9]+)?|"."[0-9]+)ch\b return 'LENGTH'; // ch
- ([0-9]+("."[0-9]+)?|"."[0-9]+)rem\b return 'LENGTH'; // rem
- ([0-9]+("."[0-9]+)?|"."[0-9]+)vw\b return 'LENGTH'; // vw
- ([0-9]+("."[0-9]+)?|"."[0-9]+)vh\b return 'LENGTH'; // vh
- ([0-9]+("."[0-9]+)?|"."[0-9]+)vmin\b return 'LENGTH'; // vmin
- ([0-9]+("."[0-9]+)?|"."[0-9]+)vmax\b return 'LENGTH'; // vmax
- ([0-9]+("."[0-9]+)?|"."[0-9]+)vm\b return 'LENGTH'; // vm (non-standard name)
- ([0-9]+("."[0-9]+)?|"."[0-9]+)px\b return 'LENGTH'; // px
- ([0-9]+("."[0-9]+)?|"."[0-9]+)mm\b return 'LENGTH'; // mm
- ([0-9]+("."[0-9]+)?|"."[0-9]+)cm\b return 'LENGTH'; // cm
- ([0-9]+("."[0-9]+)?|"."[0-9]+)in\b return 'LENGTH'; // in
- ([0-9]+("."[0-9]+)?|"."[0-9]+)pt\b return 'LENGTH'; // pt
- ([0-9]+("."[0-9]+)?|"."[0-9]+)pc\b return 'LENGTH'; // pc
- ([0-9]+("."[0-9]+)?|"."[0-9]+)Q\b return 'LENGTH'; // Q
- ([0-9]+("."[0-9]+)?|"."[0-9]+)fr\b return 'LENGTH'; // fr
- ([0-9]+("."[0-9]+)?|"."[0-9]+)deg\b return 'ANGLE'; // deg
- ([0-9]+("."[0-9]+)?|"."[0-9]+)grad\b return 'ANGLE'; // grad
- ([0-9]+("."[0-9]+)?|"."[0-9]+)turn\b return 'ANGLE'; // turn
- ([0-9]+("."[0-9]+)?|"."[0-9]+)rad\b return 'ANGLE'; // rad
- ([0-9]+("."[0-9]+)?|"."[0-9]+)s\b return 'TIME'; // s
- ([0-9]+("."[0-9]+)?|"."[0-9]+)ms\b return 'TIME'; // ms
- ([0-9]+("."[0-9]+)?|"."[0-9]+)Hz\b return 'FREQ'; // Hz
- ([0-9]+("."[0-9]+)?|"."[0-9]+)kHz\b return 'FREQ'; // kHz
- ([0-9]+("."[0-9]+)?|"."[0-9]+)dpi\b return 'RES'; // dpi
- ([0-9]+("."[0-9]+)?|"."[0-9]+)dpcm\b return 'RES'; // dpcm
- ([0-9]+("."[0-9]+)?|"."[0-9]+)dppx\b return 'RES'; // dppm
- ([0-9]+("."[0-9]+)?|"."[0-9]+)\% return 'PERCENTAGE';
- ([0-9]+("."[0-9]+)?|"."[0-9]+)\b return 'NUMBER';
-
- "(" return 'LPAREN';
- ")" return 'RPAREN';
-
- #\{([\s\S]*?)\} return 'UNKNOWN'; // scss interpolation
- @\{([\s\S]*?)\} return 'UNKNOWN'; // less interpolation
-
- \S[^\s()*/+-]* return 'UNKNOWN';
-
- <<EOF>> return 'EOF';
-
- /lex
-
- %left ADD SUB
- %left MUL DIV
- %left UPREC
-
-
- %start expression
-
- %%
-
- expression
- : math_expression EOF { return $1; }
- ;
-
- math_expression
- : CALC LPAREN math_expression RPAREN {
- $$ = $3;
- $$.source.start = { index: @1.range[0] };
- $$.source.end = { index: @4.range[1] };
- }
- | math_expression ADD math_expression {
- $$ = {
- type: 'MathExpression', operator: $2, left: $1, right: $3,
- source: {
- start: $1.source.start, end: $3.source.end,
- operator: { start: { index: @2.range[0] }, end: { index: @2.range[1] } }
- }
- };
- }
- | math_expression SUB math_expression {
- $$ = {
- type: 'MathExpression', operator: $2, left: $1, right: $3,
- source: {
- start: $1.source.start, end: $3.source.end,
- operator: { start: { index: @2.range[0] }, end: { index: @2.range[1] } }
- }
- };
- }
- | math_expression MUL math_expression {
- $$ = {
- type: 'MathExpression', operator: $2, left: $1, right: $3,
- source: {
- start: $1.source.start, end: $3.source.end,
- operator: { start: { index: @2.range[0] }, end: { index: @2.range[1] } }
- }
- };
- }
- | math_expression DIV math_expression {
- $$ = {
- type: 'MathExpression', operator: $2, left: $1, right: $3,
- source: {
- start: $1.source.start, end: $3.source.end,
- operator: { start: { index: @2.range[0] }, end: { index: @2.range[1] } }
- }
- };
- }
- | SUB math_expression %prec UPREC {
- if (@1.range[1] !== $2.source.start.index) {
- throw new Error('Unexpected spaces was found between sign and value');
- }
- if (typeof $2.value !== 'number') {
- throw new Error('Unexpected sign');
- }
- if ($2.sign) {
- throw new Error('Unexpected continuous sign');
- }
- $$ = $2;
- $$.sign = '-'
- $$.value = -$2.value;
- $$.source.start.index = @1.range[0];
- }
- | ADD math_expression %prec UPREC {
- if (@1.range[1] !== $2.source.start.index) {
- throw new Error('Unexpected spaces was found between sign and value');
- }
- if (typeof $2.value !== 'number') {
- throw new Error('Unexpected sign');
- }
- if ($2.sign) {
- throw new Error('Unexpected continuous sign');
- }
- $$ = $2;
- $$.sign = '+'
- $$.source.start.index = @1.range[0];
- }
- | LPAREN math_expression RPAREN {
- $$ = $2;
- $$.source.start = { index: @1.range[0] };
- $$.source.end = { index: @3.range[1] };
- }
- | function { $$ = $1; }
- | css_value { $$ = $1; }
- | value { $$ = $1; }
- ;
-
- value
- : NUMBER { $$ = { type: 'Value', value: parseFloat($1), source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- ;
-
- function
- : FUNCTION { $$ = { type: 'Function', value: $1, source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- ;
-
- css_value
- : LENGTH { $$ = { type: 'LengthValue', value: parseFloat($1), unit: /[a-z]+/i.exec($1)[0], source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- | ANGLE { $$ = { type: 'AngleValue', value: parseFloat($1), unit: /[a-z]+/i.exec($1)[0], source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- | TIME { $$ = { type: 'TimeValue', value: parseFloat($1), unit: /[a-z]+/i.exec($1)[0], source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- | FREQ { $$ = { type: 'FrequencyValue', value: parseFloat($1), unit: /[a-z]+/i.exec($1)[0], source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- | RES { $$ = { type: 'ResolutionValue', value: parseFloat($1), unit: /[a-z]+/i.exec($1)[0], source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- | PERCENTAGE { $$ = { type: 'PercentageValue', value: parseFloat($1), unit: '%', source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- | UNKNOWN { $$ = { type: 'UnknownValue', value: $1, unit: '', source: { start: { index: @1.range[0] }, end: { index: @1.range[1] } } }; }
- ;
|