pret-pas/pret-pas.lua

291 lines
9.1 KiB
Lua

if not modules then modules = { } end modules ['pret-pas'] = {
version = 1.0,
comment = "custom pretty printer for Pascal code",
author = "Stefan Müller, Chemnitz DE",
copyright = "Stefan Müller",
license = "see context related readme files"
}
local utf = unicode.utf8
local utfcharacters, utfvalues = string.utfcharacters, string.utfvalues
local utfbyte, utffind = utf.byte, utf.find
local byte, sub, find, match = string.byte, string.sub, string.find, string.match
local texsprint, texwrite = tex.sprint, tex.write
local ctxcatcodes = tex.ctxcatcodes
local buffers = buffers
local changestate, finishstate = buffers.changestate, buffers.finishstate
local visualizer = buffers.newvisualizer("pas")
-- reserved words taken from http://www.freepascal.org/docs-html/ref/refse3.html
visualizer.reservedwords = {
-- Turbo Pascal
"absolute", "and", "array", "asm", "begin", "case", "const", "constructor",
"destructor", "div", "do", "downto", "else", "end", "file", "for",
"function", "goto", "if", "implementation", "in", "inherited", "inline",
"interface", "label", "mod", "nil", "not", "object", "of", "on", "operator",
"or", "packed", "procedure", "program", "record", "reintroduce", "repeat",
"self", "set", "shl", "shr", "string", "then", "to", "type", "unit",
"until", "uses", "var", "while", "with", "xor",
-- Free Pascal
-- these are not bold type (keeping them, just in case)
-- "dispose", "exit", "false", "new", "true",
-- Object Pascal
"as", "class", "dispinterface", "except", "exports", "finalization",
"finally", "initialization", "inline", "is", "library", "on", "out",
"packed", "property", "raise", "resourcestring", "threadvar", "try",
-- Modifiers
-- some of these are only bold in specific places (this is deliberately
-- ignored)
"absolute", "abstract", "alias", "assembler", "cdecl", "cppdecl", "default",
"export", "external", "far", "far16", "forward", "index", "local", "name",
"near", "nostackframe", "oldfpccall", "override", "pascal", "private",
"protected", "public", "published", "read", "register", "reintroduce",
"safecall", "softfloat", "stdcall", "virtual", "write"
}
local known_words = { }
for k,v in next, visualizer.reservedwords do
known_words[v] = k
end
local colors = {
"prettyone", -- red
"prettytwo", -- green
"prettythree", -- blue
"prettyfour", -- yellow
}
local states = {
['"']=1, ["'"]=1, ["[["] = 1, ["]]"] = 1,
['+']=1, ['-']=1, ['*']=1, ['/']=1, ['%']=1, ['^']=1,
["("] = 3, [")"] = 3, ["["] = 3, ["]"] = 3,
['--']=4,
}
local function flush_pas_word(word)
if word then
local id = known_words[word]
if id then
tex.sprint(tex.ctxcatcodes,"\{\\bf ")
tex.write(word)
tex.sprint(tex.ctxcatcodes,"\}")
else
tex.write(word)
end
end
end
local incomment, inlongstring = false, false
local incompdirec, inasm = false, false
function visualizer.reset()
incomment, inlongstring = false, false
incompdirec, inasm = false, false
end
local function written(state,c,i)
if c == " " then
state = finishstate(state)
texsprint(ctxcatcodes,"\\obs")
elseif c == "\t" then
state = finishstate(state)
texsprint(ctxcatcodes,"\\obs")
if buffers.visualizers.enabletab then
texsprint(ctxcatcodes,rep("\\obs ",i%buffers.visualizers.tablength))
end
else
texwrite(c)
end
return state, 0
end
function visualizer.flush_line(str, nested)
--[[
buffers.currentcolors = colors
local identifier = nil
for c in string.utfcharacters(str) do
if string.string.find(c, "^[%a%_]$") then
if identifier then
identifier = identifier .. c
else
identifier = c
end
elseif string.string.find(c, "^[%d]$")
if identifier and #identifier > 1 then
identifier = identifier .. c
end
elseif
--flush_pas_word(identifier)
identifier = nil
end
tex.write("p")
end
--flush_pas_word(identifier)
identifier = nil
]]
local state, instr, inesc, word = 0, false, false, nil
buffers.currentcolors = colors
local code, comment = match(str,"^(.-)%-%-%[%[(.*)$")
if comment then
-- process the code and then flush the comment
elseif incomment then
comment, code = match(str,"^(.-)%]%](.*)$")
if comment then
-- flush the comment and then process the code
for c in utfcharacters(comment) do
if c == " " then texsprint(ctxcatcodes,"\\obs") else texwrite(c) end
end
state = changestate(states['--'], state)
texwrite("]]")
state = finishstate(state)
incomment = false
else
for c in utfcharacters(str) do
if c == " " then texsprint(ctxcatcodes,"\\obs") else texwrite(c) end
end
end
comment = nil
else
code = str
end
if code and code ~= "" then
local pre, post = match(code,"^(.-)%-%-(.*)$")
if pre then
code = pre
end
local p, s, i = nil, nil, 0
for c in utfcharacters(code) do
i = i + 1
if instr then
if p then
texwrite(p)
p = nil
end
if c == s then
if inesc then
texwrite(c)
inesc = false
else
state = changestate(states[c],state)
instr = false
texwrite(c)
state = finishstate(state)
end
s = nil
else
if c == "\\" then
inesc = not inesc
else
inesc = false
end
state, i = written(state,c,i)
end
elseif c == "[" then
if word then
texwrite(word)
word = nil
end
if p == "[" then
inlongstring = true
state = changestate(states["[["],state)
texwrite(p,c)
state = finishstate(state)
p = nil
else
if p then
state, i = written(state,p,i)
end
p = c
end
elseif c == "]" then
if word then
texwrite(word)
word = nil
end
if p == "]" then
inlongstring = false
state = changestate(states["]]"],state)
texwrite(p,c)
state = finishstate(state)
p = nil
else
if p then
state, i = written(state,p,i)
end
p = c
end
else
if p then
state = changestate(states[p],state)
texwrite(p)
state = finishstate(state)
p = nil
end
if c == " " or c == "\t" then
if word then
flush_pas_word(word)
word = nil
end
state, i = written(state,c,i)
elseif inlongstring then
state, i = written(state,c,i)
elseif c == '"' or c == "'" then
if word then
flush_pas_word(word)
word = nil
end
instr = true
state = changestate(states[c],state)
state, i = written(state,c,i)
state = finishstate(state)
s = c
elseif find(c,"^[%a]$") then
state = finishstate(state)
if word then word = word .. c else word = c end
elseif word and (#word > 1) and find(c,"^[%d%.%_]$") then
if word then word = word .. c else word = c end
else
flush_pas_word(word)
word = nil
state = changestate(states[c],state)
texwrite(c)
instr = (c == '"')
end
end
end
if p then
texwrite(p)
-- state, i = written(state,p,i)
p = nil
end
flush_pas_word(word)
if post then
state = changestate(states['--'], state)
texwrite("--")
state = finishstate(state)
for c in utfcharacters(post) do
state, i = written(state,c,i)
end
end
end
if comment then
incomment = true
state = changestate(states['--'], state)
texwrite("[[")
state = finishstate(state)
-- texwrite(comment) -- maybe also split and
for c in utfcharacters(comment) do
state, i = written(state,c,i)
end
end
state = finishstate(state)
end