diff --git a/README.md b/README.md index eb10a6f..e3dec68 100644 --- a/README.md +++ b/README.md @@ -181,12 +181,3 @@ struct Rect @Rect r = {{1, 2}, {3, 4}}; r:size:x ``` - -- **Generic Structs** - -```c -struct Rect[A] -{ - attribute: A, -}; -``` diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index d10ee06..e503371 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -6,3 +6,4 @@ made in Haskell. [README](README.md) [Byte Code Spec](ByteCodeSpec.md) [Byte Code Spec Ex](ByteCodeSpecEx.md) +[Syntax Highlighting Extension](SyntaxHighlighting.md) diff --git a/docs/SyntaxHighlighting.md b/docs/SyntaxHighlighting.md new file mode 100644 index 0000000..547b400 --- /dev/null +++ b/docs/SyntaxHighlighting.md @@ -0,0 +1,10 @@ +## Leviator Lang Extension for Visual Studio Code + +We are thrilled to introduce our Leviator lang extension, providing enhanced syntax highlighting for an optimized coding experience. While currently available exclusively for vscode, we have ambitious plans to extend support to JetBrains and Vim in the future. + +### Installation + +To install the Leviator Language extension for **Visual Studio Code**, follow the steps below: + +1. Navigate to the "lvtext" directory in our [Leviator GitHub repository](https://github.com/X-R-G-B/Leviator/lvtext). +2. Refer to the detailed installation instructions provided in the [README.md](https://github.com/X-R-G-B/Leviator/blob/lvtext/vscode/leviator-lang/README.md) file. diff --git a/lvtc/app/Main.hs b/lvtc/app/Main.hs index 92571b4..13e878a 100644 --- a/lvtc/app/Main.hs +++ b/lvtc/app/Main.hs @@ -7,8 +7,9 @@ module Main (main) where -import Expression (parseExpresion) +import Expression (parseExpresion, parseAllExpression) import Parser (runParser) +import Alias (proceedAlias) import ParseLvt (parseInstruction, parseInstructions) test1 :: String @@ -32,6 +33,13 @@ test5 = "@Int a = 4 + 5;\n" test6 :: String test6 = "@Int a = 3 + 4 * 2 / ( 1 - 5 );\n" +text :: String +text = aliasInt ++ aliasRetValue ++ funcMain + where + aliasInt = "alias int Int;\n" + aliasRetValue = "alias retValue 0;\n" + funcMain = "fn main () -> int \n{\n <- retValue;\n};\n" + main :: IO () main = print (runParser parseInstruction test1) @@ -40,3 +48,4 @@ main = >> print (runParser parseExpresion test4) >> print (runParser parseInstruction test5) >> print (runParser parseInstruction test6) + >> print (runParser (proceedAlias <$> parseAllExpression) text) diff --git a/lvtc/lvtc.cabal b/lvtc/lvtc.cabal index 7726e4c..04ee4ee 100644 --- a/lvtc/lvtc.cabal +++ b/lvtc/lvtc.cabal @@ -25,6 +25,7 @@ source-repository head library exposed-modules: + Alias AST Expression Lib diff --git a/lvtc/src/Alias.hs b/lvtc/src/Alias.hs new file mode 100644 index 0000000..fafd5f2 --- /dev/null +++ b/lvtc/src/Alias.hs @@ -0,0 +1,80 @@ +{- +-- EPITECH PROJECT, 2023 +-- Leviator compiler +-- File description: +-- Alias +-} + +module Alias ( + proceedAlias, +) where + +import Expression +import Parser +import ParseUtil +import Control.Applicative + +data Alias = Alias String String + +instance Show Alias.Alias where + show (Alias.Alias str1 str2) = "ALIAS `" ++ str1 ++ "`:`" ++ str2 ++ "`" + +parseAliasKeyword :: Parser String +parseAliasKeyword = parseString "alias " + +parseAliasName :: Parser String +parseAliasName = parseAllCharUntil " " + +parseAliasValue :: Parser String +parseAliasValue = parseAllCharUntil ";\n" + +parseAlias' :: Parser String +parseAlias' = (parseAliasKeyword *> parseAliasName <* many (parseChar ' ')) + +parseAlias :: Parser Alias.Alias +parseAlias = Parser f + where + f str = case runParser parseAlias' str of + Nothing -> Nothing + Just (key, xs) -> case runParser parseAliasValue xs of + Nothing -> Nothing + Just (value, ys) -> Just (Alias.Alias key value, ys) + +replaceAliasInString :: Alias.Alias -> String -> String +replaceAliasInString _ [] = [] +replaceAliasInString (Alias.Alias key value) (x:xs) + | take (length key) (x:xs) == key = + value ++ replaceAliasInString + (Alias.Alias key value) + (drop (length key) (x:xs)) + | otherwise = x : replaceAliasInString (Alias.Alias key value) xs + +replaceAlias :: Alias -> [Expression] -> [Expression] +replaceAlias _ [] = [] +replaceAlias alias ((Expression.Alias _):xs) = + replaceAlias alias xs +replaceAlias (Alias.Alias key value) ((Expression.Function str):xs) = + (Expression.Function (replaceAliasInString (Alias.Alias key value) str)) + : (replaceAlias (Alias.Alias key value) xs) +replaceAlias (Alias.Alias key value) ((Expression.Comment str):xs) = + (Expression.Comment (replaceAliasInString (Alias.Alias key value) str)) + : (replaceAlias (Alias.Alias key value) xs) + +replaceAllAlias :: [Alias] -> [Expression] -> [Expression] +replaceAllAlias [] exprs = exprs +replaceAllAlias _ [] = [] +replaceAllAlias (x:xs) exprs = replaceAllAlias xs newExprs + where + newExprs = replaceAlias x exprs + +getListAlias :: [Expression] -> [Alias] +getListAlias [] = [] +getListAlias ((Expression.Alias str):xs) = case runParser parseAlias str of + Just (alias, _) -> alias : getListAlias xs + Nothing -> getListAlias xs +getListAlias (_:xs) = getListAlias xs + +proceedAlias :: [Expression] -> [Expression] +proceedAlias exprs = replaceAllAlias lstAlias exprs + where + lstAlias = getListAlias exprs diff --git a/lvtc/test/Spec.hs b/lvtc/test/Spec.hs index c83982d..c0054a1 100644 --- a/lvtc/test/Spec.hs +++ b/lvtc/test/Spec.hs @@ -10,6 +10,7 @@ import Test.Tasty.HUnit import Expression import Parser +import Alias import UTParseLvt import UTShuntingYard @@ -23,7 +24,8 @@ tests = testGroup "Leviator Tests - Compiler" utParserExpression, utParserExpressions, utParserLvt, - utShuntingYard + utShuntingYard, + utAlias ] testParserHelper :: String -> String -> Expression -> IO () @@ -66,7 +68,7 @@ utParserExpression = testGroup "Parse Expression" testParserHelper "alias abc def;\n" "" - (Alias "alias abc def;\n") + (Expression.Alias "alias abc def;\n") , testCase "alias bad formated (no end `\\n`)" $ testParserHelperFail "alias abc def;" @@ -130,16 +132,42 @@ utParserExpressions = testGroup "Parse Expressions" testParserHelpers "alias abc def;\nalias def def;\n" "" - [Alias "alias abc def;\n", Alias "alias def def;\n"] + [Expression.Alias "alias abc def;\n", Expression.Alias "alias def def;\n"] , testCase "alias multiline" $ testParserHelpers "alias abc def\nefg hij;\n" "" - [Alias "alias abc def\nefg hij;\n"] + [Expression.Alias "alias abc def\nefg hij;\n"] -- comment , testCase "comment" $ testParserHelpers "// this is a comment\nalias abc def;\n" "" - [Comment "// this is a comment\n", Alias "alias abc def;\n"] + [Comment "// this is a comment\n", Expression.Alias "alias abc def;\n"] + ] + +utAlias :: TestTree +utAlias = testGroup "Alias" + [ + testCase "alias" $ + assertEqual "alias" + [ + Expression.Function "fn main() -> Int \n{\n <- 0;\n};" + ] + (proceedAlias [ + Expression.Alias "alias int Int;\n", + Expression.Alias "alias retValue 0;\n", + Expression.Function "fn main() -> int \n{\n <- retValue;\n};" + ]) + , testCase "nested alias" $ + assertEqual "alias nested" + [ + Expression.Function "fn main() -> Int \n{\n <- 0;\n};" + ] + (proceedAlias [ + Expression.Alias "alias int INT;\n", + Expression.Alias "alias retValue 0;\n", + Expression.Alias "alias INT Int;\n", + Expression.Function "fn main() -> int \n{\n <- retValue;\n};" + ]) ] diff --git a/lvtext/vscode/leviator-lang/.vscode/launch.json b/lvtext/vscode/leviator-lang/.vscode/launch.json new file mode 100644 index 0000000..e64ce7a --- /dev/null +++ b/lvtext/vscode/leviator-lang/.vscode/launch.json @@ -0,0 +1,17 @@ +// A launch configuration that launches the extension inside a new window +// Use IntelliSense to learn about possible attributes. +// Hover to view descriptions of existing attributes. +// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Extension", + "type": "extensionHost", + "request": "launch", + "args": [ + "--extensionDevelopmentPath=${workspaceFolder}" + ] + } + ] +} diff --git a/lvtext/vscode/leviator-lang/.vscodeignore b/lvtext/vscode/leviator-lang/.vscodeignore new file mode 100644 index 0000000..19bbe78 --- /dev/null +++ b/lvtext/vscode/leviator-lang/.vscodeignore @@ -0,0 +1,3 @@ +.vscode/** +.vscode-test/** +.gitignore diff --git a/lvtext/vscode/leviator-lang/README.md b/lvtext/vscode/leviator-lang/README.md new file mode 100644 index 0000000..226e7d9 --- /dev/null +++ b/lvtext/vscode/leviator-lang/README.md @@ -0,0 +1,13 @@ +## About + +Extension to enable syntax highlighting for [Leviator](https://github.com/X-R-G-B/Leviator) in [Visual Studio Code](https://code.visualstudio.com/). + +## Installation + +1. Find your vscode extension directory (default: `~/.vscode/extensions`) +2. Copy or move the "./lvtext/vscode/leviator-lang" directory into the vscode extension directory +3. Reload vscode + +## Usage + +Open a Leviator file (`.lvt`) and enjoy the syntax highlighting. diff --git a/lvtext/vscode/leviator-lang/assets/icon.png b/lvtext/vscode/leviator-lang/assets/icon.png new file mode 100644 index 0000000..7eba1c1 Binary files /dev/null and b/lvtext/vscode/leviator-lang/assets/icon.png differ diff --git a/lvtext/vscode/leviator-lang/language-configuration.json b/lvtext/vscode/leviator-lang/language-configuration.json new file mode 100644 index 0000000..9da1356 --- /dev/null +++ b/lvtext/vscode/leviator-lang/language-configuration.json @@ -0,0 +1,28 @@ +{ + "comments": { + // symbol used for single line comment. Remove this entry if your language does not support line comments + "lineComment": "//" + }, + // symbols used as brackets + "brackets": [ + ["{", "}"], + ["[", "]"], + ["(", ")"] + ], + // symbols that are auto closed when typing + "autoClosingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ], + // symbols that can be used to surround a selection + "surroundingPairs": [ + ["{", "}"], + ["[", "]"], + ["(", ")"], + ["\"", "\""], + ["'", "'"] + ] +} diff --git a/lvtext/vscode/leviator-lang/package.json b/lvtext/vscode/leviator-lang/package.json new file mode 100644 index 0000000..c7c4d63 --- /dev/null +++ b/lvtext/vscode/leviator-lang/package.json @@ -0,0 +1,41 @@ +{ + "name": "leviator-lang", + "displayName": "Leviator Lang", + "version": "0.0.1", + "description": "Syntax highlighting for leviator lang", + "author": { + "name": "GTX", + "url": "https://github.com/X-R-G-B" + }, + "icon": "assets/icon.png", + "engines": { + "vscode": "^1.85.0" + }, + "publisher": "X-L-R-G-B", + "categories": [ + "Programming Languages" + ], + "pricing": "Free", + "license": "MIT", + "repository": { + "type": "git", + "url": "https://github.com/X-R-G-B/Leviator" + }, + "bugs": { + "url": "https://github.com/X-R-G-B/Leviator/issues" + }, + "homepage": "https://github.com/X-R-G-B/Leviator/blob/main/README.md", + "contributes": { + "languages": [{ + "id": "leviator", + "aliases": ["Leviator", "leviator"], + "extensions": [".lvt"], + "configuration": "./language-configuration.json" + }], + "grammars": [{ + "language": "leviator", + "scopeName": "source.lvt", + "path": "./syntaxes/leviator.tmLanguage.json" + }] + } +} diff --git a/lvtext/vscode/leviator-lang/syntaxes/leviator.tmLanguage.json b/lvtext/vscode/leviator-lang/syntaxes/leviator.tmLanguage.json new file mode 100644 index 0000000..b2200fa --- /dev/null +++ b/lvtext/vscode/leviator-lang/syntaxes/leviator.tmLanguage.json @@ -0,0 +1,112 @@ +{ + "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json", + "name": "Leviator", + "patterns": [ + { + "include": "#keywords" + }, + { + "include": "#string" + }, + { + "include": "#storage" + }, + { + "include": "#constant" + }, + { + "include": "#entity" + }, + { + "include": "#variable" + }, + { + "include": "#comment" + } + ], + "repository": { + "keywords": { + "patterns": [ + { + "name": "keyword.control.leviator", + "match": "\\b(if|else|while|foreach|break)\\b" + }, + { + "name": "keyword.other.leviator", + "match": "(<-|->)" + }, + { + "name": "keyword.operator.leviator", + "match": "(\\+|-|%|\\*|!=|==|<|>|<=|>=|=|/(?!/))" + } + ] + }, + "storage": { + "patterns": [ + { + "name": "storage.type.leviator", + "match": "\\b(struct|fn|Int|Char|Float|Bool|Void|StringView)\\b" + } + ] + }, + "entity": { + "patterns": [ + { + "name": "entity.name.tag.leviator", + "match": "\\b(start)\\b" + }, + { + "name": "entity.name.function", + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b\\(" + } + ] + }, + "constant": { + "patterns": [ + { + "name": "constant.language.leviator", + "match": "\\b(True|False)\\b" + }, + { + "name": "constant.numeric.leviator", + "match": "\\b([0-9]+)\\b" + } + ] + }, + "string": { + "patterns": [ + { + "name": "string.quoted.double.leviator", + "begin": "\"", + "end": "\"" + }, + { + "name": "string.quoted.single.leviator", + "begin": "'", + "end": "'" + } + ] + }, + "variable": { + "patterns": [ + { + "name": "variable.other.leviator", + "match": "\\b([a-zA-Z_][a-zA-Z0-9_]*)\\b" + }, + { + "name": "variable.parameter", + "match": "@" + } + ] + }, + "comment": { + "patterns": [ + { + "name": "comment.line.double-slash.leviator", + "match": "//.*" + } + ] + } + }, + "scopeName": "source.lvt" +} diff --git a/lvtext/vscode/leviator-lang/test.lvt b/lvtext/vscode/leviator-lang/test.lvt new file mode 100644 index 0000000..881031b --- /dev/null +++ b/lvtext/vscode/leviator-lang/test.lvt @@ -0,0 +1,64 @@ +// Types +@Int a = 1; +@Char b = 'a'; +@Float c = 1.0; +@Bool d = true; +@StringView e = "Leviator"; + +// Data types +struct Point +{ + x: Float, + y: Float, +}; + +fn printPoint(p: Point) -> Void +{ + print(p:x); + print(p:y); +}; + +// Functions +fn add(a: Int, b: Int) -> Int +{ + <- a + b; +}; + +// Conditions + flow control +fn max(a: Int, b: Int) -> Int +{ + if (a > b) + { + <- a; + } + else + { + <- b; + }; +}; + +fn hundredPrinter() -> Void +{ + @Int i = 0; + + while (True) + { + // New line every 10 numbers + if (i % 10 == 0) + { + print("\n"); + }; + print(i); + if (i == 100) + { + break; + }; + i = i + 1; + }; +}; + +// Entry point of the program +fn start() +{ + print("Hello, world!\n"); +};