summaryrefslogtreecommitdiff
path: root/script-beta/parser/emmy.lua
diff options
context:
space:
mode:
Diffstat (limited to 'script-beta/parser/emmy.lua')
-rw-r--r--script-beta/parser/emmy.lua321
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,
+}