Merge pull request 'cpl-rewrite' (#1) from cpl-rewrite into master

Reviewed-on: edraft/sh_cclang#1
This commit is contained in:
Sven Heidemann 2021-10-27 09:22:25 +02:00
commit 793ca62ddd
87 changed files with 1052 additions and 209 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
*.pyc *.pyc
/.idea/ /.idea/
venv

59
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,59 @@
{
// 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": "Python: Aktuelle Datei",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"env": {
"PYTHONPATH": "${workspaceFolder}/src/:${workspaceFolder}/venv/bin/python"
}
},
{
"name": "CCL",
"type": "python",
"request": "launch",
"cwd": "/home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cclang/src/",
"program": "cc_lang_interpreter/main.py",
"console": "integratedTerminal",
"args": [
"First.ccl"
],
"env": {
"PYTHONPATH": "${workspaceFolder}/src/:${workspaceFolder}/venv/bin/python"
}
},
{
"name": "CCL: File",
"type": "python",
"request": "launch",
"cwd": "/home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cclang/src/",
"program": "cc_lang_interpreter/main.py",
"console": "integratedTerminal",
"args": [
"-p",
"../cc_code_preview"
],
"env": {
"PYTHONPATH": "${workspaceFolder}/src/:${workspaceFolder}/venv/bin/python"
}
},
{
"name": "CCL: Console",
"type": "python",
"request": "launch",
"cwd": "/home/sven/Nextcloud_Sven/Schreibtisch/git_sh-edraft_de/sh_cclang/src/",
"program": "cc_lang_interpreter/main.py",
"console": "integratedTerminal",
"args": [],
"env": {
"PYTHONPATH": "${workspaceFolder}/src/:${workspaceFolder}/venv/bin/python"
}
}
]
}

25
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,25 @@
{
"workbench.colorCustomizations": {
"activityBar.activeBackground": "#fbed80",
"activityBar.activeBorder": "#06b9a5",
"activityBar.background": "#fbed80",
"activityBar.foreground": "#15202b",
"activityBar.inactiveForeground": "#15202b99",
"activityBarBadge.background": "#06b9a5",
"activityBarBadge.foreground": "#15202b",
"editorGroup.border": "#fbed80",
"panel.border": "#fbed80",
"sash.hoverBorder": "#fbed80",
"sideBar.border": "#fbed80",
"statusBar.background": "#f9e64f",
"statusBar.foreground": "#15202b",
"statusBarItem.hoverBackground": "#f7df1e",
"statusBarItem.remoteBackground": "#f9e64f",
"statusBarItem.remoteForeground": "#15202b",
"titleBar.activeBackground": "#f9e64f",
"titleBar.activeForeground": "#15202b",
"titleBar.inactiveBackground": "#f9e64f99",
"titleBar.inactiveForeground": "#15202b99"
},
"peacock.color": "#f9e64f"
}

15
appsettings.json Normal file
View File

@ -0,0 +1,15 @@
{
"TimeFormatSettings": {
"DateFormat": "%Y-%m-%d",
"TimeFormat": "%H:%M:%S",
"DateTimeFormat": "%Y-%m-%d %H:%M:%S.%f",
"DateTimeLogFormat": "%Y-%m-%d_%H-%M-%S"
},
"LoggingSettings": {
"Path": "logs/",
"Filename": "log_$start_time.log",
"ConsoleLogLevel": "ERROR",
"FileLogLevel": "WARN"
}
}

View File

@ -0,0 +1,13 @@
public lib Preview.Classes {
public class Test {
private var _name: string;
public constructor(name: string) {
this._name = name;
}
public getName(): string {
return this._name;
}
}
}

View File

@ -0,0 +1,5 @@
public lib Preview.Functions {
public func isTrue(value: bool): bool {
return value;
}
}

View File

@ -0,0 +1,8 @@
public lib Preview.Variables {
public var str: string = "Hello World";
public var test: bool = false;
public var test2: Test = empty;
public var test3: Test = Test(34);
}

View File

@ -0,0 +1,26 @@
use Preview.Variables;
use Preview.Functions;
use Preview.Classes;
public lib Main {
public class Program {
private var test: Test;
public constructor() {
this.test = Test(str);
}
public func Main(): void {
output(str, test, test2, test3);
output(isTrue(test));
output(this.test.getName());
}
private func testForEach(): void {
var list = [];
list.forEach(e => {
output(e);
});
}
}
}

12
cpl-workspace.json Normal file
View File

@ -0,0 +1,12 @@
{
"WorkspaceSettings": {
"DefaultProject": "cc-lang",
"Projects": {
"cc-lang": "src/cc_lang/cc-lang.json",
"parser": "src/parser/parser.json",
"lexer": "src/lexer/lexer.json",
"runtime": "src/runtime/runtime.json",
"cc-lang-interpreter": "src/cc_lang_interpreter/cc-lang-interpreter.json"
}
}
}

View File

View File

@ -1,5 +1,5 @@
from Interpreter.Interpreter import Interpreter from Interpreter.Interpreter import Interpreter
from CCLang_sly.Interpreter import Interpreter as SlyCCLangInterpreter # from CCLang_sly.Interpreter import Interpreter as SlyCCLangInterpreter
from Interpreter.Utils import Utils from Interpreter.Utils import Utils
from Interpreter.Repo import Repo from Interpreter.Repo import Repo
@ -10,4 +10,4 @@ class ServiceInitializer:
self.repo = Repo() self.repo = Repo()
self.utils = Utils(self.repo) self.utils = Utils(self.repo)
self.interpreter = Interpreter(self.repo, self.utils) self.interpreter = Interpreter(self.repo, self.utils)
self.sly_cclang_interpreter = SlyCCLangInterpreter(self.repo, self.utils) # self.sly_cclang_interpreter = SlyCCLangInterpreter(self.repo, self.utils)

View File

@ -12,7 +12,6 @@ class Main:
self.__utils = self.__services.utils self.__utils = self.__services.utils
self.__repo = self.__services.repo self.__repo = self.__services.repo
self.__interpreter = self.__services.interpreter self.__interpreter = self.__services.interpreter
self.__sly_cclang_interpreter = self.__services.sly_cclang_interpreter
def console(self) -> None: def console(self) -> None:
""" """
@ -22,8 +21,7 @@ class Main:
i = 0 i = 0
while self.__repo.error is None: while self.__repo.error is None:
self.__repo.line_number = i + 1 self.__repo.line_number = i + 1
#self.__interpreter.interpret(input('> ')) self.__interpreter.interpret(input('> '))
self.__sly_cclang_interpreter.interpret(input('> '))
i += 1 i += 1
def files(self, file: str) -> None: def files(self, file: str) -> None:
@ -36,15 +34,14 @@ class Main:
self.__utils.runtime_error(Error(ErrorCodes.FileNotFound)) self.__utils.runtime_error(Error(ErrorCodes.FileNotFound))
return return
if not file.endswith('.cc'): if not file.endswith('.ccl'):
self.__utils.runtime_error(Error(ErrorCodes.WrongFileType)) self.__utils.runtime_error(Error(ErrorCodes.WrongFileType))
return return
f = open(file, 'r', encoding='utf-8').readlines() f = open(file, 'r', encoding='utf-8').readlines()
for i in range(0, len(f)): for i in range(0, len(f)):
self.__repo.line_number = i + 1 self.__repo.line_number = i + 1
# self.__interpreter.interpret(f[i]) self.__interpreter.interpret(f[i])
self.__sly_cclang_interpreter.interpret(f[i])
if __name__ == '__main__': if __name__ == '__main__':

27
old/src/test.cc Normal file
View File

@ -0,0 +1,27 @@
# olc test 1
// olc test 2
/* mlc Test 1 */
/*
mlc Test 2
*/
public lib Main {
class Program {
var test: bool = false;
var test2: Program2 = empty;
var test3: Program2 = Test(34);
func Main(): void {
#func Main {
var hallo: any;
#output('Hello');
#output(this.isTrue(false));
}
func isTrue(value: bool): bool {
#func isTrue {
#return value;
}
}
}

View File

@ -1,31 +0,0 @@
from typing import Optional
from CCLang_sly.Parser import Parser
from Interpreter.Validator import Validator
from CCLang_sly.Lexer import Lexer
from Interpreter.Repo import Repo
from Interpreter.Utils import Utils
from Models.AbstractSyntaxTree.AbstractSyntaxTree import AbstractSyntaxTree
class Interpreter:
def __init__(self, repo: Repo, utils: Utils) -> None:
self.__repo = repo
self.__utils = utils
# self.__lexer = Lexer(repo, utils)
# self.__parser = Parser(repo, utils)
# self.__validator = Validator(repo, utils)
def interpret(self, line_str: str) -> None:
"""
Interprets code line
:param line_str:
:return:
"""
lexer = Lexer()
parser = Parser()
env = {}
ast = parser.parse(lexer.tokenize(line_str))
if ast is not None:
print(ast)

View File

@ -1,108 +0,0 @@
from sly import Lexer as SlyLexer
from Models.CCLang.TokenDefinition import TokenDefinition
class Lexer(SlyLexer):
# Ignored pattern
ignore = '\t '
# ignore_comment = r'(/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+/)|(//.*)|([#].*)'
ignore_comment = r'([#].*|(//.*))'
ignore_newline = r'\n+'
tokens = {
LIBRARY,
CLASS,
FUNCTION,
VARIABLE,
USE,
FROM,
OUTPUT,
INPUT,
LENGTH,
RANGE,
EXIT,
IF,
ELSEIF,
ELSE,
CONTINUE,
IN,
RETURN,
WHILE,
FOR,
PUBLIC,
THIS,
LBRACE,
RBRACE,
LPARAN,
RPARAN,
LBRACKET,
RBRACKET,
SEMICOLON,
COLON,
COMMA,
POINT,
PLUS,
MINUS,
ASTERIK,
SLASH,
EQUAL,
CARET,
TRUE,
FALSE,
STRING,
NUMBER,
EMPTY,
NAME
}
# token definition
LIBRARY = TokenDefinition.Library.value
CLASS = TokenDefinition.Class.value
FUNCTION = TokenDefinition.Function.value
VARIABLE = TokenDefinition.Variable.value
USE = TokenDefinition.Use.value
FROM = TokenDefinition.From.value
OUTPUT = TokenDefinition.Output.value
INPUT = TokenDefinition.Input.value
LENGTH = TokenDefinition.Length.value
RANGE = TokenDefinition.Range.value
EXIT = TokenDefinition.Exit.value
IF = TokenDefinition.If.value
ELSEIF = TokenDefinition.ElseIf.value
ELSE = TokenDefinition.Else.value
CONTINUE = TokenDefinition.Continue.value
IN = TokenDefinition.In.value
RETURN = TokenDefinition.Return.value
WHILE = TokenDefinition.While.value
FOR = TokenDefinition.For.value
PUBLIC = TokenDefinition.Public.value
THIS = TokenDefinition.This.value
LBRACE = TokenDefinition.LeftBrace.value
RBRACE = TokenDefinition.RightBrace.value
LPARAN = TokenDefinition.LeftParenthesis.value
RPARAN = TokenDefinition.RightParenthesis.value
LBRACKET = TokenDefinition.LeftBracket.value
RBRACKET = TokenDefinition.RightBracket.value
SEMICOLON = TokenDefinition.Semicolon.value
COLON = TokenDefinition.Colon.value
COMMA = TokenDefinition.Comma.value
POINT = TokenDefinition.Point.value
PLUS = TokenDefinition.Plus.value
MINUS = TokenDefinition.Minus.value
ASTERIK = TokenDefinition.Asterisk.value
SLASH = TokenDefinition.Slash.value
EQUAL = TokenDefinition.Equal.value
CARET = TokenDefinition.Caret.value
TRUE = TokenDefinition.BoolTrue.value
FALSE = TokenDefinition.BoolFalse.value
STRING = TokenDefinition.String.value
NUMBER = TokenDefinition.Number.value
EMPTY = TokenDefinition.Empty.value
NAME = TokenDefinition.Name.value
def error(self, t):
print("Illegal character '%s'" % t.value[0])
# self.index += 1

View File

@ -1,61 +0,0 @@
from sly import Parser as SlyParser
from CCLang_sly.Lexer import Lexer
class Parser(SlyParser):
tokens = Lexer.tokens
#precedence = (
# ('left', '+', '-'),
# ('left', '*', '/'),
# ('right', 'UMINUS'),
#)
def __init__(self):
self.env = {}
@_('')
def statement(self, p):
pass
def error(self, p):
print(f'ERROR: {p}')
pass
# lib definition
@_('PUBLIC LIBRARY NAME LBRACE')
def statement(self, p):
return ('lib_def', p.NAME, True)
@_('LIBRARY NAME LBRACE')
def statement(self, p):
return ('lib_def', p.NAME, False)
# class definition
@_('PUBLIC CLASS NAME LBRACE')
def statement(self, p):
return ('class_def', p.NAME, True)
@_('CLASS NAME LBRACE')
def statement(self, p):
return ('class_def', p.NAME, False)
# func definition
@_('PUBLIC FUNCTION NAME LPARAN statement RPARAN COLON type LBRACE')
def statement(self, p):
return ('func_def', p.NAME, True)
@_('FUNCTION NAME LPARAN RPARAN COLON type LBRACE')
def statement(self, p):
return ('func_def', p.NAME, False)
# types
@_('EMPTY')
def type(self, p):
return ('type', p.EMPTY)
# right brace
@_('RBRACE')
def statement(self, p):
return ('end', p.RBRACE)

1
src/cc_lang/__init__.py Normal file
View File

@ -0,0 +1 @@
# imports

43
src/cc_lang/cc-lang.json Normal file
View File

@ -0,0 +1,43 @@
{
"ProjectSettings": {
"Name": "cc-lang",
"Version": {
"Major": "0",
"Minor": "0",
"Micro": "0"
},
"Author": "",
"AuthorEmail": "",
"Description": "",
"LongDescription": "",
"URL": "",
"CopyrightDate": "",
"CopyrightName": "",
"LicenseName": "",
"LicenseDescription": "",
"Dependencies": [
"sh_cpl==2021.4.0.post2"
],
"PythonVersion": ">=3.9.2",
"PythonPath": {
"linux": ""
},
"Classifiers": []
},
"BuildSettings": {
"ProjectType": "library",
"SourcePath": "",
"OutputPath": "../../dist",
"Main": "",
"EntryPoint": "",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,4 @@
class Type:
def __init__(self):
pass

View File

@ -0,0 +1,4 @@
class Class:
def __init__(self):
pass

View File

@ -0,0 +1,12 @@
from enum import Enum
class Datatypes(Enum):
Empty = 'empty'
Any = 'any'
Number = 'number'
String = 'string'
Bool = 'bool'
List = 'list'
Dict = 'dict'

View File

@ -0,0 +1,4 @@
class Function:
def __init__(self):
pass

View File

@ -0,0 +1,69 @@
from cc_lang.model.datatypes import Datatypes
from cc_lang.model.language_definition_classes import Keywords, FormatCharacters, ExpressionCharacters, Booleans
class LanguageDefinition:
# interpreter
keywords = [
# define keywords
Keywords.Library.value,
Keywords.Class.value,
Keywords.Function.value,
Keywords.Variable.value,
Keywords.Use.value,
Keywords.From.value,
# builtin functions
Keywords.Output.value,
Keywords.Input.value,
Keywords.Length.value,
Keywords.Range.value,
Keywords.Exit.value,
Keywords.ForEach.value,
# normal keywords
Keywords.If.value,
Keywords.ElseIf.value,
Keywords.Else.value,
Keywords.Continue.value,
Keywords.If.value,
Keywords.Return.value,
# loops
Keywords.While.value,
Keywords.For.value,
Keywords.Foreach.value,
# access
Keywords.Public.value,
Keywords.Private.value,
Keywords.Static.value,
Keywords.This.value
]
datatypes = [
Datatypes.Empty.value,
Datatypes.Any.value,
Datatypes.Number.value,
Datatypes.String.value,
Datatypes.Bool.value,
Datatypes.List.value,
Datatypes.Dict.value
]
format_chars = [
FormatCharacters.Left_Brace.value,
FormatCharacters.Right_Brace.value,
FormatCharacters.Left_Parenthesis.value,
FormatCharacters.Right_Parenthesis.value,
FormatCharacters.Left_Bracket.value,
FormatCharacters.Right_Bracket.value,
FormatCharacters.Semicolon.value,
FormatCharacters.Colon.value,
FormatCharacters.Comma.value,
FormatCharacters.Point.value
]
expr_chars = [
ExpressionCharacters.Plus.value,
ExpressionCharacters.Minus.value,
ExpressionCharacters.Asterisk.value,
ExpressionCharacters.Slash.value,
ExpressionCharacters.Equal.value,
ExpressionCharacters.Caret.value
]
bool_expr_chars = ['<', '>', '!', '!=', '==', '>=', '<=', '&&', '||']
bool_values = [Booleans.Right.value, Booleans.Wrong.value]

View File

@ -0,0 +1,66 @@
from enum import Enum
class Keywords(Enum):
# define keywords
Library = 'lib'
Class = 'class'
Function = 'func'
Variable = 'var'
Use = 'use'
From = 'from'
# builtin functions
Output = 'output'
Input = 'input'
Length = 'length'
Range = 'range'
Exit = 'exit'
ForEach = 'forEach'
# normal keywords
If = 'if'
ElseIf = 'elseif'
Else = 'else'
Continue = 'continue'
In = 'in'
Return = 'return'
# loops
While = 'while'
For = 'for'
Foreach = 'foreach'
# access
Public = 'public'
Private = 'private'
Static = 'static'
This = 'this'
class Booleans(Enum):
Right = 'true'
Wrong = 'false'
class ExpressionCharacters(Enum):
Plus = '+'
Minus = '-'
Asterisk = '*'
Slash = '/'
Equal = '='
Caret = '^'
class FormatCharacters(Enum):
Left_Brace = '{'
Right_Brace = '}'
Left_Parenthesis = '('
Right_Parenthesis = ')'
Left_Bracket = '['
Right_Bracket = ']'
Semicolon = ';'
Colon = ':'
Comma = ','
Point = '.'

View File

@ -0,0 +1,4 @@
class Library:
def __init__(self):
pass

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,4 @@
class Bool:
def __init__(self):
pass

View File

@ -0,0 +1,4 @@
class Number:
def __init__(self):
pass

View File

@ -0,0 +1,4 @@
class String:
def __init__(self):
pass

View File

@ -0,0 +1,4 @@
class Variable:
def __init__(self):
pass

View File

@ -0,0 +1 @@
# imports:

View File

@ -0,0 +1,76 @@
import os
from cpl_core.application import ApplicationABC
from cpl_core.configuration import ConfigurationABC
from cpl_core.console import Console
from cpl_core.dependency_injection import ServiceProviderABC
from lexer.abc.lexer_abc import LexerABC
from parser.abc.parser_abc import ParserABC
from runtime.abc.runtime_service_abc import RuntimeServiceABC
class Application(ApplicationABC):
def __init__(self, config: ConfigurationABC, services: ServiceProviderABC):
ApplicationABC.__init__(self, config, services)
self._lexer: LexerABC = services.get_service(LexerABC)
self._parser: ParserABC = services.get_service(ParserABC)
self._runtime: RuntimeServiceABC = services.get_service(RuntimeServiceABC)
self._path = config.get_configuration('p')
def _interpret(self, line: str):
tokens = self._lexer.tokenize(line)
ast = self._parser.create_ast(tokens)
line.replace("\n", "").replace("\t", "")
# Console.write_line(f'<{self._runtime.line_count}> LINE: {line}')
# header, values = ['Type', 'Value'], []
# tokens.for_each(lambda t: values.append([t.type, t.value]))
# Console.table(header, values)
def _console(self):
i = 0
while True:
self._runtime.line_count = i + 1
self._interpret(Console.read('> '))
i += 1
def _files(self):
if not os.path.isdir(self._path):
raise FileNotFoundError(self._path)
# r=root, d=directories, f=files
for r, d, f in os.walk(self._path):
for file in f:
if file.endswith('.ccl'):
self._read_file(os.path.join(r, file))
def _read_file(self, file: str):
if not os.path.isfile(file):
raise FileNotFoundError
# self.__utils.runtime_error(Error(ErrorCodes.FileNotFound))
if not file.endswith('.ccl'):
raise Exception('Wrong file type')
# self.__utils.runtime_error(Error(ErrorCodes.WrongFileType))
f = open(file, 'r', encoding='utf-8').readlines()
for i in range(0, len(f)):
self._runtime.line_count = i + 1
self._interpret(f[i])
def configure(self):
pass
def main(self):
if self._path is None:
self._console()
return
if os.path.isfile(self._path):
self._read_file(self._path)
else:
self._files()

View File

@ -0,0 +1,44 @@
{
"ProjectSettings": {
"Name": "cc-lang-interpreter",
"Version": {
"Major": "0",
"Minor": "0",
"Micro": "0"
},
"Author": "",
"AuthorEmail": "",
"Description": "",
"LongDescription": "",
"URL": "",
"CopyrightDate": "",
"CopyrightName": "",
"LicenseName": "",
"LicenseDescription": "",
"Dependencies": [
"sh_cpl-core==2021.10.0.post1",
"sh_cpl-query==2021.10.0"
],
"PythonVersion": ">=3.9.2",
"PythonPath": {
"linux": ""
},
"Classifiers": []
},
"BuildSettings": {
"ProjectType": "console",
"SourcePath": "",
"OutputPath": "../../dist",
"Main": "cc_lang_interpreter.main",
"EntryPoint": "cc-lang-interpreter",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

@ -0,0 +1,14 @@
from cpl_core.application import ApplicationBuilder
from cc_lang_interpreter.application import Application
from cc_lang_interpreter.startup import Startup
def main():
app_builder = ApplicationBuilder(Application)
app_builder.use_startup(Startup)
app_builder.build().run()
if __name__ == '__main__':
main()

View File

@ -0,0 +1,30 @@
from cpl_core.application import StartupABC
from cpl_core.configuration import ConfigurationABC, ConsoleArgument
from cpl_core.dependency_injection import ServiceProviderABC, ServiceCollectionABC
from cpl_core.environment import ApplicationEnvironment
from lexer.abc.lexer_abc import LexerABC
from lexer.service.lexer_service import LexerService
from parser.abc.parser_abc import ParserABC
from parser.service.parser_service import ParserService
from runtime.abc.runtime_service_abc import RuntimeServiceABC
from runtime.service.runtime_service import RuntimeService
class Startup(StartupABC):
def __init__(self):
StartupABC.__init__(self)
def configure_configuration(self, config: ConfigurationABC, env: ApplicationEnvironment) -> ConfigurationABC:
config.add_console_argument(ConsoleArgument('-', 'p', [], ' ', is_value_token_optional=True))
config.add_console_arguments()
return config
def configure_services(self, services: ServiceCollectionABC, env: ApplicationEnvironment) -> ServiceProviderABC:
services.add_singleton(LexerABC, LexerService)
services.add_singleton(ParserABC, ParserService)
services.add_singleton(RuntimeServiceABC, RuntimeService)
return services.build_service_provider()

1
src/lexer/__init__.py Normal file
View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,14 @@
from abc import ABC, abstractmethod
from cpl_query.extension.list import List
from lexer.model.token import Token
class LexerABC(ABC):
@abstractmethod
def __init__(self): pass
@abstractmethod
def tokenize(self, line: str) -> List[Token]: pass

43
src/lexer/lexer.json Normal file
View File

@ -0,0 +1,43 @@
{
"ProjectSettings": {
"Name": "lexer",
"Version": {
"Major": "0",
"Minor": "0",
"Micro": "0"
},
"Author": "",
"AuthorEmail": "",
"Description": "",
"LongDescription": "",
"URL": "",
"CopyrightDate": "",
"CopyrightName": "",
"LicenseName": "",
"LicenseDescription": "",
"Dependencies": [
"sh_cpl==2021.4.0.post2"
],
"PythonVersion": ">=3.9.2",
"PythonPath": {
"linux": ""
},
"Classifiers": []
},
"BuildSettings": {
"ProjectType": "library",
"SourcePath": "",
"OutputPath": "../../dist",
"Main": "",
"EntryPoint": "",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

23
src/lexer/model/token.py Normal file
View File

@ -0,0 +1,23 @@
from lexer.model.token_types import TokenTypes
class Token:
def __init__(self, token_type: TokenTypes, value: str) -> None:
self._type: TokenTypes = token_type
self._value: str = value
@property
def type(self) -> TokenTypes:
return self._type
@property
def value(self) -> str:
return self._value
@value.setter
def value(self, value: str):
self._value = value
def __str__(self) -> str:
return f'Token: Type: {self._type}, Value: {self._value}'

View File

@ -0,0 +1,24 @@
from enum import Enum
class TokenTypes(Enum):
Empty = 0
Keyword = 1
Type = 2
Name = 3
Bool = 4
String = 5
Number = 6
Expression_Character = 7
Bool_Expression_Character = 8
Format_Character = 9
class UnresolvedTokenTypes(Enum):
Empty = 0
Word = 1
Number = 2
String = 3
Expression_Character = 4
Bool_Expression_Character = 5
Format_Character = 6

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,166 @@
from cpl_query.extension.list import List
from cc_lang.model.language_definition import LanguageDefinition
from lexer.abc.lexer_abc import LexerABC
from lexer.model.token import Token
from lexer.model.token_types import UnresolvedTokenTypes, TokenTypes
from runtime.abc.runtime_service_abc import RuntimeServiceABC
class LexerService(LexerABC):
def __init__(self, runtime: RuntimeServiceABC):
self._runtime = runtime
self._is_ml_comment = False
def _add_tok(self, tokens: List[Token], value: str, input_token_type: UnresolvedTokenTypes) -> None:
"""
Creates token object
:param value:
:param input_token_type:
:return:
"""
token_type: TokenTypes = TokenTypes.Empty
if value != '':
if input_token_type == UnresolvedTokenTypes.Word:
if value in LanguageDefinition.keywords:
token_type = TokenTypes.Keyword
elif value in LanguageDefinition.datatypes:
token_type = TokenTypes.Type
elif value in LanguageDefinition.bool_values:
token_type = TokenTypes.Bool
elif value == UnresolvedTokenTypes.Empty:
token_type = TokenTypes.Empty
else:
token_type = TokenTypes.Name
elif input_token_type == UnresolvedTokenTypes.Number:
token_type = TokenTypes.Number
elif input_token_type == UnresolvedTokenTypes.String:
token_type = TokenTypes.String
elif input_token_type == UnresolvedTokenTypes.Expression_Character:
token_type = TokenTypes.Expression_Character
elif input_token_type == UnresolvedTokenTypes.Bool_Expression_Character:
token_type = TokenTypes.Bool_Expression_Character
elif input_token_type == UnresolvedTokenTypes.Format_Character:
token_type = TokenTypes.Format_Character
tokens.append(Token(token_type, value))
def tokenize(self, line: str) -> List[Token]:
tokens: List[Token] = List(Token)
word = ''
ol_comment = False
is_string1 = False # 'hello'
is_string2 = False # "hello"
is_number = False
is_expr_char = False
for i in range(0, len(line)):
c = line[i]
# ignore comments and spaces
if not ol_comment and not self._is_ml_comment:
# comment filtering
if c == '#' and not is_string1 and not is_string2:
ol_comment = True
elif line[i - 1] == '/' and c == '/':
ol_comment = True
elif line[i - 1] == '/' and c == '*':
self._is_ml_comment = True
i += 2
# end of number
elif not c.isdigit() and c != '.' and is_number:
self._add_tok(tokens, word, UnresolvedTokenTypes.Number)
local_tokens = self.tokenize(c)
for local_token in local_tokens:
tokens.append(local_token)
word = ''
is_number = False
# end of expression char
elif c not in LanguageDefinition.expr_chars and is_expr_char:
self._add_tok(tokens, word, UnresolvedTokenTypes.Expression_Character)
word = ''
is_expr_char = False
# begin of is_string1
elif c == '\'' and not is_string1:
is_string1 = True
word = ''
# end of is_string1
elif c == '\'' and is_string1:
is_string1 = False
self._add_tok(tokens, word, UnresolvedTokenTypes.String)
word = ''
# begin of is_string2
elif c == '\"' and not is_string2:
is_string2 = True
word = ''
# end of is_string2
elif c == '\"' and is_string2:
is_string2 = False
self._add_tok(tokens, word, UnresolvedTokenTypes.String)
word = ''
# format char
elif c in LanguageDefinition.format_chars:
self._add_tok(tokens, word, UnresolvedTokenTypes.Word)
self._add_tok(tokens, c, UnresolvedTokenTypes.Format_Character)
word = ''
# begin of number
elif c.isdigit() and not is_number and word == '':
word += c
is_number = True
# continue number
elif (c.isdigit() or c == '.') and is_number:
word += c
# begin expression char
elif c in LanguageDefinition.expr_chars and not is_expr_char:
word += c
is_expr_char = True
# continue expression char
elif c in LanguageDefinition.expr_chars and is_expr_char:
word += c
# bool expression char
elif c in LanguageDefinition.bool_expr_chars:
self._add_tok(tokens, word, UnresolvedTokenTypes.Word)
self._add_tok(tokens, c, UnresolvedTokenTypes.Bool_Expression_Character)
word = ''
# end of word
elif c == ' ' and not is_string1 and not is_string2 or c == '\n':
self._add_tok(tokens, word, UnresolvedTokenTypes.Word)
word = ''
else:
word += c
if c == '\n' and ol_comment:
ol_comment = False
if line[i - 1] == '*' and c == '/':
self._is_ml_comment = False
return tokens

1
src/parser/__init__.py Normal file
View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,7 @@
from abc import ABC, abstractmethod
class AST(ABC):
@abstractmethod
def __init__(self): pass

View File

@ -0,0 +1,14 @@
from abc import ABC, abstractmethod
from cpl_query.extension.list import List
from parser.abc.ast_abc import AST
from lexer.model.token import Token
class ParserABC(ABC):
@abstractmethod
def __init__(self): pass
@abstractmethod
def create_ast(self, tokens: List[Token]) -> List[AST]: pass

43
src/parser/parser.json Normal file
View File

@ -0,0 +1,43 @@
{
"ProjectSettings": {
"Name": "parser",
"Version": {
"Major": "0",
"Minor": "0",
"Micro": "0"
},
"Author": "",
"AuthorEmail": "",
"Description": "",
"LongDescription": "",
"URL": "",
"CopyrightDate": "",
"CopyrightName": "",
"LicenseName": "",
"LicenseDescription": "",
"Dependencies": [
"sh_cpl==2021.4.0.post2"
],
"PythonVersion": ">=3.9.2",
"PythonPath": {
"linux": ""
},
"Classifiers": []
},
"BuildSettings": {
"ProjectType": "library",
"SourcePath": "",
"OutputPath": "../../dist",
"Main": "",
"EntryPoint": "",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,19 @@
from cpl_core.console.console import Console
from cpl_query.extension.list import List
from lexer.model.token import Token
from parser.abc.ast_abc import AST
from parser.abc.parser_abc import ParserABC
class ParserService(ParserABC):
def __init__(self):
pass
def create_ast(self, tokens: List[Token]) -> List[AST]:
for i in range(0, tokens.count()):
prev_token = tokens[i-1] if i-1 > 0 else None
token = tokens[i]
next_token = tokens[i+1] if i+1 < tokens.count() else None
Console.write_line(token)

1
src/runtime/__init__.py Normal file
View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,7 @@
from abc import ABC, abstractmethod
class ClassStackABC(ABC):
@abstractmethod
def __init__(self): pass

View File

@ -0,0 +1,7 @@
from abc import ABC, abstractmethod
class FunctionStackABC(ABC):
@abstractmethod
def __init__(self): pass

View File

@ -0,0 +1,7 @@
from abc import ABC, abstractmethod
class LibraryStackABC(ABC):
@abstractmethod
def __init__(self): pass

View File

@ -0,0 +1,15 @@
from abc import ABC, abstractmethod
class RuntimeServiceABC(ABC):
@abstractmethod
def __init__(self): pass
@property
@abstractmethod
def line_count(self) -> int: pass
@line_count.setter
@abstractmethod
def line_count(self, line_count: int): pass

View File

@ -0,0 +1,7 @@
from abc import ABC, abstractmethod
class VariableStackABC(ABC):
@abstractmethod
def __init__(self): pass

43
src/runtime/runtime.json Normal file
View File

@ -0,0 +1,43 @@
{
"ProjectSettings": {
"Name": "runtime",
"Version": {
"Major": "0",
"Minor": "0",
"Micro": "0"
},
"Author": "",
"AuthorEmail": "",
"Description": "",
"LongDescription": "",
"URL": "",
"CopyrightDate": "",
"CopyrightName": "",
"LicenseName": "",
"LicenseDescription": "",
"Dependencies": [
"sh_cpl==2021.4.0.post2"
],
"PythonVersion": ">=3.9.2",
"PythonPath": {
"linux": ""
},
"Classifiers": []
},
"BuildSettings": {
"ProjectType": "library",
"SourcePath": "",
"OutputPath": "../../dist",
"Main": "",
"EntryPoint": "",
"IncludePackageData": false,
"Included": [],
"Excluded": [
"*/__pycache__",
"*/logs",
"*/tests"
],
"PackageData": {},
"ProjectReferences": []
}
}

View File

@ -0,0 +1 @@
# imports

View File

@ -0,0 +1,15 @@
from runtime.abc.runtime_service_abc import RuntimeServiceABC
class RuntimeService(RuntimeServiceABC):
def __init__(self):
self._line_count = 0
@property
def line_count(self) -> int:
return self._line_count
@line_count.setter
def line_count(self, line_count: int):
self._line_count = line_count

1
src/tests/__init__.py Normal file
View File

@ -0,0 +1 @@
# imports: