diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 8c1d82089..8d8275ab6 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -76,6 +76,7 @@ | odin | ✓ | | | `ols` | | openscad | ✓ | | | `openscad-language-server` | | org | ✓ | | | | +| pascal | ✓ | ✓ | | `pasls` | | perl | ✓ | ✓ | ✓ | | | php | ✓ | ✓ | ✓ | `intelephense` | | prisma | ✓ | | | `prisma-language-server` | diff --git a/languages.toml b/languages.toml index 0bcc6ef21..986b927e3 100644 --- a/languages.toml +++ b/languages.toml @@ -1691,3 +1691,17 @@ roots = ["edgedb.toml"] [[grammar]] name ="esdl" source = { git = "https://github.com/greym0uth/tree-sitter-esdl", rev = "b840c8a8028127e0a7c6e6c45141adade2bd75cf" } + +[[language]] +name = "pascal" +scope = "source.pascal" +injection-regex = "pascal" +file-types = ["pas", "pp", "inc", "lpr", "lfm"] +roots = [] +comment-token = "//" +indent = { tab-width = 2, unit = " " } +language-server = { command = "pasls", args = [] } + +[[grammar]] +name = "pascal" +source = { git = "https://github.com/Isopod/tree-sitter-pascal", rev = "2fd40f477d3e2794af152618ccfac8d92eb72a66" } diff --git a/runtime/queries/pascal/highlights.scm b/runtime/queries/pascal/highlights.scm new file mode 100644 index 000000000..5368a22b8 --- /dev/null +++ b/runtime/queries/pascal/highlights.scm @@ -0,0 +1,382 @@ +; -- Identifier type inferrence + +; VERY QUESTIONABLE: Highlighting of identifiers based on spelling +(exprBinary ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprUnary ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(assignment rhs: ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprBrackets ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprParens ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprDot rhs: ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprTpl args: ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprArgs ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(declEnumValue ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(defaultValue ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) + +; -- Break, Continue & Exit +; (Not ideal: ideally, there would be a way to check if these special +; identifiers are shadowed by a local variable) +(statement ((identifier) @keyword.control.return + (#match? @keyword.control.return "^[eE][xX][iI][tT]$"))) +(statement (exprCall entity: ((identifier) @keyword.control.return + (#match? @keyword.control.return "^[eE][xX][iI][tT]$")))) +(statement ((identifier) @keyword.control.repeat + (#match? @keyword.control.repeat "^[bB][rR][eE][aA][kK]$"))) +(statement ((identifier) @keyword.control.repeat + (#match? @keyword.control.repeat "^[cC][oO][nN][tT][iI][nN][uU][eE]$"))) + +; -- Heuristic for procedure/function calls without parentheses +; (If a statement consists only of an identifier, assume it's a procedure) +; (This will still not match all procedure calls, and also may produce false +; positives in rare cases, but only for nonsensical code) + +(statement (exprDot rhs: (exprTpl entity: (identifier) @function))) +(statement (exprTpl entity: (identifier) @function)) +(statement (exprDot rhs: (identifier) @function)) +(statement (identifier) @function) + +; -- Procedure name in calls with parentheses +; (Pascal doesn't require parentheses for procedure calls, so this will not +; detect all calls) + +(inherited) @function + +; foo.bar +(exprCall entity: (exprDot rhs: (exprTpl entity: (identifier) @function))) +; foo.bar +(exprCall entity: (exprDot rhs: (identifier) @function)) +; foobar +(exprCall entity: (exprTpl entity: (identifier) @function)) +; foobar +(exprCall entity: (identifier) @function) + +; -- Fields + +(declSection (declVars (declVar name:(identifier) @variable.other.member))) +(declSection (declField name:(identifier) @variable.other.member)) +(declClass (declField name:(identifier) @variable.other.member)) +(exprDot rhs: (exprDot) @variable.other.member) +(exprDot rhs: (identifier) @variable.other.member) + +(recInitializerField name:(identifier) @variable.other.member) + +; -- Variable & constant declarations +; (This is only questionable because we cannot detect types of identifiers +; declared in other units, so the results will be inconsistent) + +(declVar name: (identifier) @variable) +(declConst name: (identifier) @constant) +(declEnumValue name: (identifier) @constant) + +; -- Constant usage + +[ + (caseLabel) + (label) +] @constant + +(procAttribute (identifier) @constant) +(procExternal (identifier) @constant) + +; -- Type usage + +(typeref) @type + +; -- Exception parameters + +(exceptionHandler variable: (identifier) @variable.parameter) + +; -- Template parameters + +(genericArg type: (typeref) @type) +(genericArg name: (identifier) @variable.parameter) + +(declProc name: (genericDot lhs: (identifier) @type)) +(declType (genericDot (identifier) @type)) + +(genericDot (genericTpl (identifier) @type)) +(genericDot (genericDot (identifier) @type)) + +(genericTpl entity: (genericDot (identifier) @type)) +(genericTpl entity: (identifier) @type) + +; -- Function parameters + +(declArg name: (identifier) @variable.parameter) + +; Treat property declarations like functions + +(declProp name: (identifier) @function) +(declProp getter: (identifier) @variable.other.member) +(declProp setter: (identifier) @variable.other.member) + +; -- Procedure & function declarations + +; foo.bar +(declProc name: (genericDot rhs: (genericTpl entity: (identifier) @function))) +; foo.bar +(declProc name: (genericDot rhs: (identifier) @function)) +; foobar +(declProc name: (genericTpl entity: (identifier) @function)) +; foobar +(declProc name: (identifier) @function) + +; -- Type declaration + +(declType name: (genericTpl entity: (identifier) @type)) +(declType name: (identifier) @type) + +; -- Comments + +(comment) @comment +(pp) @function.macro + +; -- Variables + +(exprBinary (identifier) @variable) +(exprUnary (identifier) @variable) +(assignment (identifier) @variable) +(exprBrackets (identifier) @variable) +(exprParens (identifier) @variable) +(exprDot (identifier) @variable) +(exprTpl (identifier) @variable) +(exprArgs (identifier) @variable) +(defaultValue (identifier) @variable) + +; -- Literals + +(literalNumber) @constant.builtin.numeric +(literalString) @string + +; -- Builtin constants + +[ + (kTrue) + (kFalse) +] @constant.builtin.boolean + +[ + (kNil) +] @constant.builtin + +; -- Punctuation & operators + +[ + (kOr) + (kXor) + (kDiv) + (kMod) + (kAnd) + (kShl) + (kShr) + (kNot) + (kIs) + (kAs) + (kIn) +] @keyword.operator + +[ + (kDot) + (kAdd) + (kSub) + (kMul) + (kFdiv) + (kAssign) + (kAssignAdd) + (kAssignSub) + (kAssignMul) + (kAssignDiv) + (kEq) + (kLt) + (kLte) + (kGt) + (kGte) + (kNeq) + (kAt) + (kHat) +] @operator + +[ + ".." +] @punctuation.special + +[ + ";" + "," + ":" + (kEndDot) +] @punctuation.delimiter + +[ + "(" + ")" + "[" + "]" +] @punctuation.bracket + +; -- Attributes + +(procAttribute (kPublic) @attribute) + +[ + (kDefault) + (kIndex) + (kNodefault) + (kStored) + + (kStatic) + (kVirtual) + (kAbstract) + (kSealed) + (kDynamic) + (kOverride) + (kOverload) + (kReintroduce) + (kInline) + + (kForward) + + (kStdcall) + (kCdecl) + (kCppdecl) + (kPascal) + (kRegister) + (kMwpascal) + (kExternal) + (kName) + (kMessage) + (kDeprecated) + (kExperimental) + (kPlatform) + (kUnimplemented) + (kCvar) + (kExport) + (kFar) + (kNear) + (kSafecall) + (kAssembler) + (kNostackframe) + (kInterrupt) + (kNoreturn) + (kIocheck) + (kLocal) + (kHardfloat) + (kSoftfloat) + (kMs_abi_default) + (kMs_abi_cdecl) + (kSaveregisters) + (kSysv_abi_default) + (kSysv_abi_cdecl) + (kVectorcall) + (kVarargs) + (kWinapi) + (kAlias) + (kDelayed) + + (rttiAttributes) + (procAttribute) + +] @attribute + +; -- Keywords +[ + (kProgram) + (kLibrary) + (kUnit) + (kUses) + + (kBegin) + (kEnd) + (kAsm) + + (kVar) + (kThreadvar) + (kConst) + (kResourcestring) + (kConstref) + (kOut) + (kType) + (kLabel) + (kExports) + + (kAbsolute) + + (kProperty) + (kRead) + (kWrite) + (kImplements) + + (kClass) + (kInterface) + (kObject) + (kRecord) + (kObjcclass) + (kObjccategory) + (kObjcprotocol) + (kArray) + (kFile) + (kString) + (kSet) + (kOf) + (kHelper) + (kPacked) + + (kInherited) + + (kGeneric) + (kSpecialize) + + (kFunction) + (kProcedure) + (kConstructor) + (kDestructor) + (kOperator) + (kReference) + + (kInterface) + (kImplementation) + (kInitialization) + (kFinalization) + + (kPublished) + (kPublic) + (kProtected) + (kPrivate) + (kStrict) + (kRequired) + (kOptional) + + (kTry) + (kExcept) + (kFinally) + (kRaise) + (kOn) + (kCase) + (kWith) + (kGoto) +] @keyword + +[ + (kFor) + (kTo) + (kDownto) + (kDo) + (kWhile) + (kRepeat) + (kUntil) +] @keyword.control.repeat + +[ + (kIf) + (kThen) + (kElse) +] @keyword.control.conditional diff --git a/runtime/queries/pascal/injections.scm b/runtime/queries/pascal/injections.scm new file mode 100644 index 000000000..321c90add --- /dev/null +++ b/runtime/queries/pascal/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/pascal/textobjects.scm b/runtime/queries/pascal/textobjects.scm new file mode 100644 index 000000000..56dbe5403 --- /dev/null +++ b/runtime/queries/pascal/textobjects.scm @@ -0,0 +1,10 @@ + +(declType (declClass (declSection) @class.inside)) @class.around + +(defProc body: (_) @function.inside) @function.around + +(declArgs (_) @parameter.inside) @parameter.around +(exprArgs (_) @parameter.inside) @parameter.around + +(comment) @comment.inside +(comment)+ @comment.around