From b885649ae170bec3df95bcb4ff779d5a4148aaca Mon Sep 17 00:00:00 2001 From: Fredrik Nicol Date: Sat, 28 Apr 2018 09:12:47 +0200 Subject: [PATCH] WIP --- src/keywords.ts | 71 ------------------------------------------------- src/parser.ts | 18 +++++++++++++ src/typer.ts | 68 +++++++++++++++++++++++++++++++++++++++------- 3 files changed, 77 insertions(+), 80 deletions(-) delete mode 100644 src/keywords.ts diff --git a/src/keywords.ts b/src/keywords.ts deleted file mode 100644 index a39f29b..0000000 --- a/src/keywords.ts +++ /dev/null @@ -1,71 +0,0 @@ -import { isProperty, isSyntax, getSyntax, getPropertySyntax } from './data'; -import parse, { - Component, - EntityType, - ICombinator, - isCombinator, - isComponent, - isCurlyBracesMultiplier, -} from './parser'; -import { TypeType } from './typer'; - -const CURLY_BRACES_MULTIPLIER_MAXIMUM = 3; - -export function combineKeywords(entities: EntityType[]) { - const types: TypeType[] = []; - const combinator = precedenceCombinator(entities); - - for (const entity of entities) { - if (isComponent(entity)) { - switch (entity.component) { - case Component.DataType: { - if (isSyntax(entity.value)) { - const keywords = combineKeywords(parse(getSyntax(entity.value))); - } - if (isProperty(entity.value) && !combineKeywords(parse(getPropertySyntax(entity.value)))) { - return null; - } - - // Missing or basic data type - return false; - } - case Component.Group: { - if (!combineKeywords(entity.entities)) { - return false; - } - break; - } - } - - if ( - entity.multiplier !== null && - // We can work with a small amount. But too many isn't worth it. - !(isCurlyBracesMultiplier(entity.multiplier) && entity.multiplier.max < CURLY_BRACES_MULTIPLIER_MAXIMUM) - ) { - return null; - } - - continue; - } - } - - return true; -} - -export function precedenceCombinator(entities: EntityType[]) { - let combinator: ICombinator | null = null; - - for (const entity of entities) { - if (isCombinator(entity)) { - if (!combinator) { - combinator = entity; - } - if (combinator !== entity) { - // This should never happen if grouping works as it should. So we just wnt to make sure. - throw new Error('Combinators must be grouped by precedence'); - } - } - } - - return combinator; -} diff --git a/src/parser.ts b/src/parser.ts index c9cb1e9..ac5f31c 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -263,6 +263,24 @@ function multiplierData(raw: string[]): MultiplierType | null { } } +export function precedenceCombinator(entities: EntityType[]) { + let combinator: ICombinator | null = null; + + for (const entity of entities) { + if (isCombinator(entity)) { + if (!combinator) { + combinator = entity; + } + if (combinator !== entity) { + // This should never happen if grouping works as it should. So we just wnt to make sure. + throw new Error('Combinators must be grouped by precedence'); + } + } + } + + return combinator; +} + function groupByPrecedence(entities: EntityType[], precedence: number = Combinator.SingleBar): EntityType[] { if (precedence < 0) { // We've reached the lowest precedence possible diff --git a/src/typer.ts b/src/typer.ts index 43efe7d..e54122c 100644 --- a/src/typer.ts +++ b/src/typer.ts @@ -1,7 +1,7 @@ import * as cssTypes from 'mdn-data/css/types.json'; -import { isProperty, isSyntax } from './data'; +import { isProperty, isSyntax, getSyntax, getPropertySyntax } from './data'; import { warn } from './logger'; -import { +import parse, { Combinator, Component, EntityType, @@ -10,8 +10,9 @@ import { isMandatoryEntity, isMandatoryMultiplied, isOptionallyMultiplied, + isCurlyBracesMultiplier, + precedenceCombinator, } from './parser'; -import { combineKeywords } from './keywords'; export enum Type { Alias, @@ -50,6 +51,8 @@ export type TypeType = IBasic | IStringLiteral | INumeric export type ResolvedType = TypeType; +const CURLY_BRACES_MULTIPLIER_MAXIMUM = 3; + let getBasicDataTypes = () => { const types = Object.keys(cssTypes).reduce<{ [name: string]: IBasic }>((dataTypes, name) => { switch (name) { @@ -81,12 +84,10 @@ let getBasicDataTypes = () => { }; export default function typing(entities: EntityType[]): TypeType[] { - if (combineKeywords(entities)) { - return [ - { - type: Type.String, - }, - ]; + const strictTypes = strictTyping(entities); + + if (strictTypes !== null) { + return strictTypes; } let mandatoryCombinatorCount = 0; @@ -179,6 +180,55 @@ export default function typing(entities: EntityType[]): TypeType[] { return types; } +export function strictTyping(entities: EntityType[]): TypeType[] | null { + const types: TypeType[] = []; + const combinator = precedenceCombinator(entities); + + for (const entity of entities) { + if (isComponent(entity)) { + switch (entity.component) { + case Component.DataType: { + if (isSyntax(entity.value) || isProperty(entity.value)) { + const strictTypes = strictTyping( + parse(isSyntax(entity.value) ? getSyntax(entity.value) : getPropertySyntax(entity.value)), + ); + + if (strictTypes === null) { + return null; + } + } + + // Missing or basic data type + return null; + } + case Component.Group: { + const strictTypes = strictTyping(entity.entities); + + if (strictTypes === null) { + return null; + } + + // TODO + + break; + } + } + + if ( + entity.multiplier !== null && + // We can work with a small amount. But too many isn't worth it. + !(isCurlyBracesMultiplier(entity.multiplier) && entity.multiplier.max < CURLY_BRACES_MULTIPLIER_MAXIMUM) + ) { + return null; + } + + continue; + } + } + + return types; +} + function addLength(types: Array>): Array> { if (types.every(type => type.type !== Type.Length)) { return [