Posted to tcl by Stu at Tue Jun 04 14:31:43 GMT 2024view raw
- #! /usr/bin/env python
- """pTycl - A variation on Python syntax"""
- __cow__ = """Copyright (c) 2024 Stuart Cassoff <stwo@users.sourceforge.net>
- Permission to use, copy, modify, and distribute this software for any
- purpose with or without fee is hereby granted, provided that the above
- copyright notice and this permission notice appear in all copies.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE."""
- __author__ = "Stuart Cassoff"
- __license__ = __cow__
- __copyright__ = __cow__
- __version__ = "1.0"
- __when__ = "Winter/Spring 2024"
- __what__ = "pTycl"
- #
- # pTycl
- #
- import re
- import sys
- import evallers
- def ptycl (blob, interp=None) {
- out = []
- level = 0
- indent = " "
- caret = True
- pblob = preprocess(blob)
- scanned = scan(pblob)
- for n,line in enumerate(pblob.splitlines()) {
- if n in scanned {
- o,p1,p2 = scanned[n]
- if o == -2 {
- continue
- }
- if o == -3 {
- out.append("#" + p1)
- continue
- }
- if o == 1 {
- line = p1 + " " + p2 + ":"
- out.append(indent * level + do_things_to(line, caret))
- } elif o == 0 {
- line = p1 + ("" if p2 == "" else " " + p2) + ":"
- out.append(indent * (level-1) + do_things_to(line, caret))
- }
- level += o
- continue
- }
- out.append(indent * level + do_things_to(line, caret).strip())
- }
- return "\n".join(out)
- }
- def scan (blob) {
- <?pragma lambdas off?>
- rup = re.compile(r"^\s*(async\s+def|async\s+for|async\s+with|case|class|def|for|if|match|try|with|while|mef|maf)\s+(.*?)\s*\{\s*$")
- rz1 = re.compile(r"^\s*\}\s*(elif|except)\s*(.+?)\s*\{.*$")
- rz2 = re.compile(r"^\s*\}\s*(else|finally)\s*\{.*$")
- rdn = re.compile(r"^\s*\}\s*(?:#\s*.*?)?\s*$")
- rpr = re.compile(r"\<\?" + "pragma" + r"\s*(.*?)\?\>", re.S)
- <?pragma lambdas on?>
- nobraces = False
- elide = False
- comment = False
- scanned = {}
- for n,line in enumerate(blob.splitlines()) {
- if (m := rpr.search(line)) {
- g = m.group(1).split(" ")
- if len(g) == 2 {
- if g[0] == "braces" {
- if g[1] == "on" {
- nobraces = False
- scanned[n] = (-2,None,None)
- } elif g[1] == "off" {
- nobraces = True
- scanned[n] = (-2,None,None)
- }
- } elif g[0] == "elide" {
- if g[1] == "on" {
- elide = True
- scanned[n] = (-2,None,None)
- continue
- } elif g[1] == "off" {
- elide = False
- scanned[n] = (-2,None,None)
- continue
- }
- } elif g[0] == "comment" {
- if g[1] == "on" {
- comment = True
- scanned[n] = (-2,None,None)
- continue
- } elif g[1] == "off" {
- comment = False
- scanned[n] = (-2,None,None)
- continue
- }
- }
- }
- }
- if nobraces : continue
- if elide {
- scanned[n] = (-2,None,None)
- continue
- }
- if comment {
- scanned[n] = (-3,line,None)
- continue
- }
- if (m := rup.match(line)) {
- scanned[n] = (1,m.group(1),m.group(2))
- } elif (m := rz1.match(line)) {
- scanned[n] = (0,m.group(1),m.group(2))
- } elif (m := rz2.match(line)) {
- scanned[n] = (0,m.group(1),"")
- } elif (m := rdn.match(line)) {
- scanned[n] = (-1,"","")
- }
- }
- return scanned
- }
- def preprocess (blob) {
- blob = preprocess_includes (blob)
- blob = preprocess_comments (blob)
- blob = preprocess_shells (blob)
- return blob
- }
- def preprocess_includes (blob) {
- while (blob := do_preprocess_includes(nblob:=blob)) != nblob : pass
- return blob
- }
- def do_preprocess_includes (blob) {
- reggy = re.compile(r"\<\?" + "include" + r"\s*(.*?)\?\>", re.S)
- if not (m := reggy.search(blob)): return blob
- for group in m.groups() {
- if (res := file_load(group, nonewline=True))[-1] {
- blob = blob[:m.span(0)[0]] + res[0] + blob[m.span(0)[1]:]
- }
- }
- return blob
- }
- def preprocess_comments (blob, comment="//") {
- return "\n".join((line for line in blob.splitlines() if not line.strip().startswith(comment))) if comment in blob else blob
- }
- def preprocess_shells (blob) {
- interp = None
- shells = {shell:re.compile(r"\<\?" + shell + r"\s*(.*?)\?\>", re.S) for shell in ('tcl','py','sh')}
- for shell,reggy in shells.items() {
- if not (m := reggy.search(blob)): continue
- if shell == 'tcl' {
- if interp is None {
- import tkinter
- interp = tkinter.Tcl()
- }
- cargo = interp
- } elif shell == 'py' {
- cargo = {}
- } else {
- cargo = None
- }
- for group in m.groups() {
- res,ok = evallers.__dict__['eval_' + shell](group, cargo)
- if shell == 'sh' {
- res = res.removesuffix("\n")
- }
- blob = blob[:m.span(0)[0]] + res + blob[m.span(0)[1]:]
- }
- }
- return blob
- }
- def do_things_to (line, caret=False) {
- line = mefalize (line)
- line = mafalize (line)
- line = lambdada (line)
- line = selfetate (line)
- if caret: line = djam_karet (line)
- return line
- }
- <?pragma m_fs off?>
- def mefalize (line) : return re.sub(r"^mef(\s+.+?\()", r"def\1self, " , line).replace("(self, )", "(self)")
- def mafalize (line) : return re.sub(r"^maf(\s+.+?\()", r"async def\1self, " , line).replace("(self, )", "(self)")
- <?pragma m_fs on?>
- def selfetate (line, fles=None) {
- if line == "" or "$" not in line {
- return line
- }
- if fles is None : fles = "self"
- if line[0] == "$" {
- line = fles + "." + line[1:]
- }
- for s,r in zip(*[iter((
- <?pragma self off?>
- " $" , " " + fles + "."
- , "\t$" , "\t" + fles + "."
- , "($)" , "(" + fles + ")"
- , "($," , "(" + fles + ","
- , "($" , "(" + fles + "."
- , "[$" , "[" + fles + "."
- , "{$" , "{" + fles + "."
- , ":$" , ":" + fles + "."
- , ",$" , "," + fles + "."
- <?pragma self on?>
- ))]*2): line = line.replace(s, r)
- return line
- }
- def djam_karet (line) {
- if line == "" or "^" not in line {
- return line
- }
- if line[0] == "^" {
- line = "return" + line[1:]
- }
- for s,r in zip(*[iter((
- <?pragma carets off?>
- " ^ " , " return "
- , "\t^\t" , "\treturn\t"
- , " ^\t" , " return\t"
- , "\t^ " , "\treturn "
- , "#^ " , "#return "
- , "#^\t" , "#return\t"
- <?pragma carets on?>
- ))]*2): line = line.replace(s, r)
- return line
- }
- def lambdada (line) {
- <?pragma lambdas off?>
- reggy = re.compile(r"\|\s*(.*?)\s*\|\s*(.+?)\s*\|")
- <?pragma lambdas on?>
- if not (m := reggy.search(line)): return line
- line = line[:m.span(0)[0]] + "lambda " + ",".join(m.group(1).split()) + ":" + m.group(2) + line[m.span(0)[1]:]
- return line
- }
- def main () {
- print(ptycl(sys.stdin.read()))
- }
- if __name__=="__main__":main()
- # EOF