diff options
Diffstat (limited to 'script-beta/parser/emmy.lua')
-rw-r--r-- | script-beta/parser/emmy.lua | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/script-beta/parser/emmy.lua b/script-beta/parser/emmy.lua new file mode 100644 index 00000000..4c1e087a --- /dev/null +++ b/script-beta/parser/emmy.lua @@ -0,0 +1,321 @@ +local State +local pushError + +local grammar = [[ +EmmyLua <- ({} '---' EmmyBody {} ShortComment) + -> EmmyLua +EmmySp <- (!'---@' !'---' Comment / %s / %nl)* +EmmyComments <- (EmmyComment (%nl EmmyComMulti / %nl EmmyComSingle)*) +EmmyComment <- EmmySp %s* {(!%nl .)*} +EmmyComMulti <- EmmySp '---|' {} -> en {(!%nl .)*} +EmmyComSingle <- EmmySp '---' !'@' %s* {} -> ' ' {(!%nl .)*} +EmmyBody <- '@class' %s+ EmmyClass -> EmmyClass + / '@type' %s+ EmmyType -> EmmyType + / '@alias' %s+ EmmyAlias -> EmmyAlias + / '@param' %s+ EmmyParam -> EmmyParam + / '@return' %s+ EmmyReturn -> EmmyReturn + / '@field' %s+ EmmyField -> EmmyField + / '@generic' %s+ EmmyGeneric -> EmmyGeneric + / '@vararg' %s+ EmmyVararg -> EmmyVararg + / '@language' %s+ EmmyLanguage -> EmmyLanguage + / '@see' %s+ EmmySee -> EmmySee + / '@overload' %s+ EmmyOverLoad -> EmmyOverLoad + / %s* EmmyComments -> EmmyComment + / EmmyIncomplete + +EmmyName <- ({} {[a-zA-Z_] [a-zA-Z0-9_]*}) + -> EmmyName +MustEmmyName <- EmmyName / DirtyEmmyName +DirtyEmmyName <- {} -> DirtyEmmyName +EmmyLongName <- ({} {(!%nl .)+}) + -> EmmyName +EmmyIncomplete <- MustEmmyName + -> EmmyIncomplete + +EmmyClass <- (MustEmmyName EmmyParentClass?) +EmmyParentClass <- %s* {} ':' %s* MustEmmyName + +EmmyType <- EmmyTypeUnits EmmyTypeEnums +EmmyTypeUnits <- {| + EmmyTypeUnit? + (%s* '|' %s* !String EmmyTypeUnit)* + |} +EmmyTypeEnums <- {| EmmyTypeEnum* |} +EmmyTypeUnit <- EmmyFunctionType + / EmmyTableType + / EmmyArrayType + / EmmyCommonType +EmmyCommonType <- EmmyName + -> EmmyCommonType +EmmyTypeEnum <- %s* (%nl %s* '---')? '|'? EmmyEnum + -> EmmyTypeEnum +EmmyEnum <- %s* {'>'?} %s* String (EmmyEnumComment / (!%nl !'|' .)*) +EmmyEnumComment <- %s* '#' %s* {(!%nl .)*} + +EmmyAlias <- MustEmmyName %s* EmmyType EmmyTypeEnum* + +EmmyParam <- MustEmmyName %s* EmmyType %s* EmmyOption %s* EmmyTypeEnum* +EmmyOption <- Table? + -> EmmyOption + +EmmyReturn <- {} %nil {} Table -> EmmyOption + / {} EmmyType {} EmmyOption + +EmmyField <- (EmmyFieldAccess MustEmmyName %s* EmmyType) +EmmyFieldAccess <- ({'public'} Cut %s*) + / ({'protected'} Cut %s*) + / ({'private'} Cut %s*) + / {} -> 'public' + +EmmyGeneric <- EmmyGenericBlock + (%s* ',' %s* EmmyGenericBlock)* +EmmyGenericBlock<- (MustEmmyName %s* (':' %s* EmmyType)?) + -> EmmyGenericBlock + +EmmyVararg <- EmmyType + +EmmyLanguage <- MustEmmyName + +EmmyArrayType <- ({} MustEmmyName -> EmmyCommonType {} '[' DirtyBR) + -> EmmyArrayType + / ({} PL EmmyCommonType DirtyPR '[' DirtyBR) + -> EmmyArrayType + +EmmyTableType <- ({} 'table' Cut '<' %s* EmmyType %s* ',' %s* EmmyType %s* '>' {}) + -> EmmyTableType + +EmmyFunctionType<- ({} 'fun' Cut %s* EmmyFunctionArgs %s* EmmyFunctionRtns {}) + -> EmmyFunctionType +EmmyFunctionArgs<- ('(' %s* EmmyFunctionArg %s* (',' %s* EmmyFunctionArg %s*)* DirtyPR) + -> EmmyFunctionArgs + / '(' %nil DirtyPR -> None + / %nil +EmmyFunctionRtns<- (':' %s* EmmyType (%s* ',' %s* EmmyType)*) + -> EmmyFunctionRtns + / %nil +EmmyFunctionArg <- MustEmmyName %s* ':' %s* EmmyType + +EmmySee <- {} MustEmmyName %s* '#' %s* MustEmmyName {} +EmmyOverLoad <- EmmyFunctionType +]] + +local ast = { + EmmyLua = function (start, emmy, finish) + emmy.start = start + emmy.finish = finish - 1 + State.emmy[#State.emmy+1] = emmy + end, + EmmyName = function (start, str) + return { + type = 'name', + start = start, + finish = start + #str - 1, + [1] = str, + } + end, + DirtyEmmyName = function (pos) + pushError { + type = 'MISS_NAME', + level = 'warning', + start = pos, + finish = pos, + } + return { + type = 'emmyName', + start = pos-1, + finish = pos-1, + [1] = '' + } + end, + EmmyClass = function (class, startPos, extends) + if extends and extends[1] == '' then + extends.start = startPos + end + return { + type = 'class', + class = class, + extends = extends, + } + end, + EmmyType = function (types, enums) + local result = { + type = 'type', + types = types, + enums = enums, + } + return result + end, + EmmyCommonType = function (name) + return { + type = 'common', + start = name.start, + finish = name.finish, + name = name, + } + end, + EmmyArrayType = function (start, emmy, _, finish) + emmy.type = 'emmyArrayType' + emmy.start = start + emmy.finish = finish - 1 + return emmy + end, + EmmyTableType = function (start, keyType, valueType, finish) + return { + type = 'emmyTableType', + start = start, + finish = finish - 1, + [1] = keyType, + [2] = valueType, + } + end, + EmmyFunctionType = function (start, args, returns, finish) + local result = { + start = start, + finish = finish - 1, + type = 'emmyFunctionType', + args = args, + returns = returns, + } + return result + end, + EmmyFunctionRtns = function (...) + return {...} + end, + EmmyFunctionArgs = function (...) + local args = {...} + args[#args] = nil + return args + end, + EmmyAlias = function (name, emmyName, ...) + return { + type = 'emmyAlias', + start = name.start, + finish = emmyName.finish, + name, + emmyName, + ... + } + end, + EmmyParam = function (argName, emmyName, option, ...) + local emmy = { + type = 'emmyParam', + option = option, + argName, + emmyName, + ... + } + emmy.start = emmy[1].start + emmy.finish = emmy[#emmy].finish + return emmy + end, + EmmyReturn = function (start, type, finish, option) + local emmy = { + type = 'emmyReturn', + option = option, + start = start, + finish = finish - 1, + [1] = type, + } + return emmy + end, + EmmyField = function (access, fieldName, ...) + local obj = { + type = 'emmyField', + access, fieldName, + ... + } + obj.start = obj[2].start + obj.finish = obj[3].finish + return obj + end, + EmmyGenericBlock = function (genericName, parentName) + return { + start = genericName.start, + finish = parentName and parentName.finish or genericName.finish, + genericName, + parentName, + } + end, + EmmyGeneric = function (...) + local emmy = { + type = 'emmyGeneric', + ... + } + emmy.start = emmy[1].start + emmy.finish = emmy[#emmy].finish + return emmy + end, + EmmyVararg = function (typeName) + return { + type = 'emmyVararg', + start = typeName.start, + finish = typeName.finish, + typeName, + } + end, + EmmyLanguage = function (language) + return { + type = 'emmyLanguage', + start = language.start, + finish = language.finish, + language, + } + end, + EmmySee = function (start, className, methodName, finish) + return { + type = 'emmySee', + start = start, + finish = finish - 1, + className, methodName + } + end, + EmmyOverLoad = function (EmmyFunctionType) + EmmyFunctionType.type = 'emmyOverLoad' + return EmmyFunctionType + end, + EmmyIncomplete = function (emmyName) + emmyName.type = 'emmyIncomplete' + return emmyName + end, + EmmyComment = function (...) + return { + type = 'emmyComment', + [1] = table.concat({...}), + } + end, + EmmyOption = function (options) + if not options or options == '' then + return nil + end + local option = {} + for _, pair in ipairs(options) do + if pair.type == 'pair' then + local key = pair[1] + local value = pair[2] + if key.type == 'name' then + option[key[1]] = value[1] + end + end + end + return option + end, + EmmyTypeEnum = function (default, enum, comment) + enum.type = 'enum' + if default ~= '' then + enum.default = true + end + enum.comment = comment + return enum + end, +} + +local function init(state) + State = state + pushError = state.pushError +end + +return { + grammar = grammar, + ast = ast, + init = init, +} |