parser.jison 5.79 KB
/* description: Parses expressions. */

/* lexical grammar */
%lex

%options case-insensitive

%%
\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]+)(e(\+|-)[0-9]+)?)em\b              return 'EMS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)ex\b              return 'EXS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)ch\b              return 'CHS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)rem\b             return 'REMS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)vw\b              return 'VWS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)vh\b              return 'VHS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)vmin\b            return 'VMINS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)vmax\b            return 'VMAXS';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)cm\b              return 'LENGTH';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)mm\b              return 'LENGTH';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)Q\b               return 'LENGTH';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)in\b              return 'LENGTH';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)pt\b              return 'LENGTH';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)pc\b              return 'LENGTH';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)px\b              return 'LENGTH';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)deg\b             return 'ANGLE';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)grad\b            return 'ANGLE';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)rad\b             return 'ANGLE';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)turn\b            return 'ANGLE';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)s\b               return 'TIME';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)ms\b              return 'TIME';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)Hz\b              return 'FREQ';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)kHz\b             return 'FREQ';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)dpi\b             return 'RES';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)dpcm\b            return 'RES';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)dppx\b            return 'RES';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)\%                return 'PERCENTAGE';
(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)\b                return 'NUMBER';

(([0-9]+("."[0-9]+)?|"."[0-9]+)(e(\+|-)[0-9]+)?)-?([a-zA-Z_]|[\240-\377]|(\\[0-9a-fA-F]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-fA-F]))([a-zA-Z0-9_-]|[\240-\377]|(\\[0-9a-fA-F]{1,6}(\r\n|[ \t\r\n\f])?|\\[^\r\n\f0-9a-fA-F]))*\b       return 'UNKNOWN_DIMENSION';

"("                                             return 'LPAREN';
")"                                             return 'RPAREN';

<<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; }
    | math_expression ADD math_expression { $$ = { type: 'MathExpression', operator: $2, left: $1, right: $3 }; }
    | math_expression SUB math_expression { $$ = { type: 'MathExpression', operator: $2, left: $1, right: $3 }; }
    | math_expression MUL math_expression { $$ = { type: 'MathExpression', operator: $2, left: $1, right: $3 }; }
    | math_expression DIV math_expression { $$ = { type: 'MathExpression', operator: $2, left: $1, right: $3 }; }
    | LPAREN math_expression RPAREN { $$ = { type: 'ParenthesizedExpression', content: $2 }; }
    | function { $$ = $1; }
    | dimension { $$ = $1; }
    | number { $$ = $1; }
    ;

  function
    : FUNCTION { $$ = { type: 'Function', value: $1 }; }
    ;

  dimension
    : LENGTH { $$ = { type: 'LengthValue', value: parseFloat($1), unit: /[a-z]+$/i.exec($1)[0] }; }
    | ANGLE { $$ = { type: 'AngleValue', value: parseFloat($1), unit: /[a-z]+$/i.exec($1)[0] }; }
    | TIME { $$ = { type: 'TimeValue', value: parseFloat($1), unit: /[a-z]+$/i.exec($1)[0] }; }
    | FREQ { $$ = { type: 'FrequencyValue', value: parseFloat($1), unit: /[a-z]+$/i.exec($1)[0] }; }
    | RES { $$ = { type: 'ResolutionValue', value: parseFloat($1), unit: /[a-z]+$/i.exec($1)[0] }; }
    | UNKNOWN_DIMENSION { $$ = { type: 'UnknownDimension', value: parseFloat($1), unit: /[a-z]+$/i.exec($1)[0] }; }
    | EMS { $$ = { type: 'EmValue', value: parseFloat($1), unit: 'em' }; }
    | EXS { $$ = { type: 'ExValue', value: parseFloat($1), unit: 'ex' }; }
    | CHS { $$ = { type: 'ChValue', value: parseFloat($1), unit: 'ch' }; }
    | REMS { $$ = { type: 'RemValue', value: parseFloat($1), unit: 'rem' }; }
    | VHS { $$ = { type: 'VhValue', value: parseFloat($1), unit: 'vh' }; }
    | VWS { $$ = { type: 'VwValue', value: parseFloat($1), unit: 'vw' }; }
    | VMINS { $$ = { type: 'VminValue', value: parseFloat($1), unit: 'vmin' }; }
    | VMAXS { $$ = { type: 'VmaxValue', value: parseFloat($1), unit: 'vmax' }; }
    | PERCENTAGE { $$ = { type: 'PercentageValue', value: parseFloat($1), unit: '%' }; }
    | ADD dimension { var prev = $2; $$ = prev; }
    | SUB dimension { var prev = $2; prev.value *= -1; $$ = prev; }
    ;

  number
    : NUMBER { $$ = { type: 'Number', value: parseFloat($1) }; }
    | ADD NUMBER { $$ = { type: 'Number', value: parseFloat($2) }; }
    | SUB NUMBER { $$ = { type: 'Number', value: parseFloat($2) * -1 }; }
    ;