create basic modification of arranger
This commit is contained in:
parent
eb3f1967aa
commit
27d66b0e51
7 changed files with 248 additions and 59 deletions
|
@ -1,8 +1,7 @@
|
|||
{@lang|en}
|
||||
{@def|@font|{@quote|FreeSans|AR PL UKai TW}}
|
||||
{@def|@fontsize|12}
|
||||
therapy of communication and pronounciation123%comment
|
||||
|
||||
anotherline%{@set|@fontsize|10} processing
|
||||
|
||||
of the problem
|
||||
{@def|@linewidth|200} %in px%
|
||||
{@def|@spacing|{@hglue|{@ex|1}|2}}
|
||||
{@def|@cjk_spacing|{@hglue|{@ex|0}|0.001}}
|
||||
11111 222 3333333 444444 555555 666666 77777 88888 99999 000000 11111 22222 33333 55555
|
11
example/ex2.ug
Normal file
11
example/ex2.ug
Normal file
|
@ -0,0 +1,11 @@
|
|||
{@lang|en}
|
||||
{@def|@font|{@quote|FreeSans|AR PL UKai TW}}
|
||||
{@def|@fontsize|12}
|
||||
{@def|@linewidth|300} %in px%
|
||||
{@def|@spacing|{@hglue|{@ex|1}|2}}
|
||||
{@def|@cjk_spacing|{@hglue|{@ex|0}|0.001}}
|
||||
therapy of communication and pronounciation123%comment
|
||||
|
||||
anotherline%{@set|@fontsize|10} processing of
|
||||
|
||||
of the problem
|
37
src/arrange.jl
Normal file
37
src/arrange.jl
Normal file
|
@ -0,0 +1,37 @@
|
|||
module Arrange
|
||||
using Match
|
||||
|
||||
u = Main.uahgi
|
||||
|
||||
# the cost of make ith to jth char a line
|
||||
function cost(items, i, j, linewidth)
|
||||
slice = items[i:j]
|
||||
cost_list = map(x -> item_cost(x), slice)
|
||||
sum_of_cost_list = reduce((x, y)-> x+y, cost_list)
|
||||
if sum_of_cost_list > linewidth
|
||||
return Inf
|
||||
else
|
||||
return linewidth - sum_of_cost_list
|
||||
end
|
||||
end
|
||||
|
||||
function item_cost(i)
|
||||
if typeof(i) == u.HGlue
|
||||
return i.wd
|
||||
elseif typeof(i) == u.ChBox
|
||||
return i.wd
|
||||
else
|
||||
return 0
|
||||
end
|
||||
end
|
||||
|
||||
function arrange(vbox, env)
|
||||
result_vbox_inner = []
|
||||
linewidth = parse(Int, env["linewidth"])
|
||||
print(cost(vbox.eles[1].eles, 1, 20, linewidth))
|
||||
|
||||
return vbox
|
||||
|
||||
end
|
||||
|
||||
end
|
156
src/interp.jl
156
src/interp.jl
|
@ -8,6 +8,12 @@ using .PDFOperating
|
|||
u = Main.uahgi
|
||||
c = Main.uahgi.Parsing.Passes.Classes
|
||||
|
||||
@enum PutChar begin
|
||||
true_ = 0
|
||||
false_ = 1
|
||||
gen_chbox_ = 2
|
||||
end
|
||||
|
||||
function interp_main(ast, env, res_box)
|
||||
ast_inner = ast.val
|
||||
val = nothing
|
||||
|
@ -22,17 +28,33 @@ interp: the intepreter of the uahgi.
|
|||
- ast: element or part of the ast
|
||||
- env: the variable storaging environment
|
||||
- res_box: the generated result box containing the content\
|
||||
- put_char(bool. value): if the character should be put into the res_box
|
||||
- put_char(PutChar): if the character should be put into the res_box.
|
||||
"""
|
||||
function interp(ast, env, res_box, put_char=true)
|
||||
function interp(ast, env, res_box, put_char=true_)
|
||||
#println("INTERP", ast)
|
||||
@match ast begin
|
||||
c.SEQ([c.ELE([c.ID("def")]),
|
||||
c.ELE([c.ID(id)]),val]) =>
|
||||
begin
|
||||
(val_evaled, env, res_box) = interp(val, env, res_box, false)
|
||||
(val_evaled, env, res_box) = interp(val, env, res_box, false_)
|
||||
#println("ID~~~", id, " VAL~~~", val_evaled)
|
||||
if !haskey(env, id)
|
||||
env[id] = val_evaled
|
||||
else
|
||||
throw("the variable $id has been defined.")
|
||||
end
|
||||
return (val_evaled, env, res_box)
|
||||
end
|
||||
c.SEQ([c.ELE([c.ID("set")]),
|
||||
c.ELE([c.ID(id)]),val]) =>
|
||||
begin
|
||||
(val_evaled, env, res_box) = interp(val, env, res_box, false_)
|
||||
#println("ID~~~", id, " VAL~~~", val_evaled)
|
||||
if haskey(env, id)
|
||||
env[id] = val_evaled
|
||||
else
|
||||
throw("the variable $id is not defined yet.")
|
||||
end
|
||||
return (val_evaled, env, res_box)
|
||||
end
|
||||
c.SEQ([c.ELE([c.ID("quote")]),
|
||||
|
@ -45,49 +67,107 @@ function interp(ast, env, res_box, put_char=true)
|
|||
|
||||
c.ELE([v...]) => begin
|
||||
ele = reduce( (x, y) -> x*""*y,
|
||||
map(i -> interp(i, env, res_box, false)[1], v))
|
||||
map(i -> interp(i, env, res_box, false_)[1], v))
|
||||
return (ele, env, res_box)
|
||||
|
||||
end
|
||||
c.SEQ([c.ELE([c.ID("par")])]) =>begin
|
||||
push!(res_box.eles, u.HBox([],
|
||||
nothing, nothing, nothing, nothing, nothing))
|
||||
return (ast, env, res_box)
|
||||
end
|
||||
c.SEQ([c.ELE([c.ID("ex")]), val]) =>begin
|
||||
x = 'x'
|
||||
font_family = select_font(x, env)
|
||||
font_path = get_font_path(font_family)
|
||||
font_size = parse(Int, env["fontsize"])
|
||||
charmetrics = PDFOperating.check_char_size(
|
||||
'x',
|
||||
font_path,
|
||||
font_size)
|
||||
ex_in_px = charmetrics.wd
|
||||
(val, _, _) = interp(val, env, res_box, false_)
|
||||
val_ex_in_px = ex_in_px * parse(Int,val)
|
||||
return (val_ex_in_px, env, res_box)
|
||||
end
|
||||
c.SEQ([c.ELE([c.ID("hglue")]),
|
||||
width,stretch]) => begin
|
||||
if put_char == true_
|
||||
(width_evaled, _, _) = interp(width, env, res_box, false_)
|
||||
(stretch_evaled, _, _) = interp(stretch, env, res_box, false_)
|
||||
push!(res_box.eles[end].eles,
|
||||
u.HGlue(width_evaled, parse(Int, stretch_evaled))
|
||||
)
|
||||
end
|
||||
|
||||
return (ast, env, res_box)
|
||||
end
|
||||
|
||||
c.CHAR(ch) => begin
|
||||
atomic_ch = ch[1]
|
||||
|
||||
if put_char == true
|
||||
|
||||
font_idx = 1
|
||||
font_family = string(env["font"][font_idx])
|
||||
font_family_length = length(font_family)
|
||||
while !is_in_font(atomic_ch, font_family)
|
||||
if font_idx <= font_family_length
|
||||
font_idx += 1
|
||||
font_family = string(env["font"][font_idx])
|
||||
else
|
||||
font_list = string(env["font"])
|
||||
throw("the chars $atomic_ch is not contained in all the fonts
|
||||
listed in listed fonts: $font_list")
|
||||
end
|
||||
if put_char == false_
|
||||
return (ch, env, res_box)
|
||||
end
|
||||
|
||||
font_family = select_font(atomic_ch, env)
|
||||
|
||||
font_path = get_font_path(font_family)
|
||||
font_size = parse(Int, env["fontsize"])
|
||||
glyph_metrics = PDFOperating.check_char_size(
|
||||
atomic_ch, font_path, font_size)
|
||||
|
||||
|
||||
push!(res_box.eles[end].eles,
|
||||
u.ChBox(ch,
|
||||
chbox = u.ChBox(ch,
|
||||
font_path,
|
||||
font_size,
|
||||
glyph_metrics.ht,
|
||||
glyph_metrics.dp,
|
||||
glyph_metrics.wd))
|
||||
end
|
||||
return (ch, env, res_box)
|
||||
end
|
||||
c.NL(nl) => return (nl, env, res_box)
|
||||
c.SPACE(sp) => return (sp, env, res_box)
|
||||
glyph_metrics.wd,
|
||||
nothing, nothing)
|
||||
|
||||
if put_char == true_
|
||||
push!(res_box.eles[end].eles, chbox)
|
||||
return (ch, env, res_box)
|
||||
else # put_char == gen_chbox_
|
||||
return (chbox, env, res_box)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
c.SEQ([c.ELE([c.ID("disc")]),
|
||||
c.ELE(before),
|
||||
c.ELE(after),
|
||||
c.ELE(orig)])=> begin
|
||||
before_item = length(before) == 0 ? [] : before[1]
|
||||
after_item = length(after) == 0 ? [] : after[1]
|
||||
orig_item = length(orig) == 0 ? [] : orig[1]
|
||||
|
||||
(before_evaled, _, _) = interp(before_item, env, res_box, gen_chbox_)
|
||||
(after_evaled, _, _) = interp(after_item, env, res_box, gen_chbox_)
|
||||
(orig_evaled, _, _) = interp(orig_item, env, res_box, gen_chbox_)
|
||||
ret = u.Disc(before_evaled, after_evaled, orig_evaled)
|
||||
println("RETURN", ret)
|
||||
push!(res_box.eles[end].eles, ret)
|
||||
return (ret, env, res_box)
|
||||
|
||||
end
|
||||
c.NL(nl) => begin
|
||||
#if spacing defined
|
||||
if haskey(env, "spacing")
|
||||
(spacing, _, _) = interp(env["spacing"], env, res_box, false_)
|
||||
add_spacing = interp(spacing, env, res_box, true_)
|
||||
end
|
||||
return (nl, env, res_box)
|
||||
end
|
||||
c.SPACE(sp) => begin
|
||||
#if spacing defined
|
||||
if haskey(env, "spacing")
|
||||
(spacing, _, _) = interp(env["spacing"], env, res_box, false_)
|
||||
add_spacing = interp(spacing, env, res_box, true_)
|
||||
end
|
||||
return (sp, env, res_box)
|
||||
end
|
||||
# empty item
|
||||
[] => return (ast, env, res_box)
|
||||
_ => begin
|
||||
println("不知道")
|
||||
val_evaled = "不知道"
|
||||
|
@ -144,6 +224,24 @@ function padding_zero(i)
|
|||
return i
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
Select proper font having the glyph of char `ch`
|
||||
"""
|
||||
function select_font(ch, env)
|
||||
font_idx = 1
|
||||
font_family = string(env["font"][font_idx])
|
||||
font_family_length = length(font_family)
|
||||
while !is_in_font(ch, font_family)
|
||||
if font_idx <= font_family_length
|
||||
font_idx += 1
|
||||
font_family = string(env["font"][font_idx])
|
||||
else
|
||||
font_list = string(env["font"])
|
||||
throw("the chars $atomic_ch is not contained in all the fonts
|
||||
listed in listed fonts: $font_list")
|
||||
end
|
||||
end
|
||||
return font_family
|
||||
end
|
||||
|
||||
end
|
|
@ -15,7 +15,7 @@ grammar rules of uahgi
|
|||
|
||||
comment = P"\%[^%]+\%"
|
||||
newline = P"(\r?\n)" |> Passes.Classes.NL
|
||||
space = p"[ \t]" > Passes.Classes.SPACE
|
||||
space = p"[ \t]+" > Passes.Classes.SPACE
|
||||
|
||||
id_name = p"[_a-zA-Z][_0-9a-zA-Z]*" > Passes.Classes.ID
|
||||
id = E"@" + id_name
|
||||
|
@ -139,10 +139,4 @@ function ast_to_string(ast)
|
|||
return str
|
||||
end
|
||||
|
||||
# Write your package code here.
|
||||
#export cat
|
||||
|
||||
#cat = 1.2
|
||||
|
||||
|
||||
end
|
|
@ -26,8 +26,7 @@ push!(processed_passes, two_nl_to_par_pass)
|
|||
|
||||
# in 2 hanzi add glue.
|
||||
function insert_hglue_in_adjacent_chinese(two_nl)
|
||||
_0pt = Classes.SEQ([Classes.ID("pt"); Classes.CHAR(["0"])])
|
||||
inner = Classes.SEQ([Classes.ID("hglue"); _0pt])
|
||||
inner = Classes.ID("cjk_spacing")
|
||||
return [two_nl[1]; inner; two_nl[2]]
|
||||
end
|
||||
adjacent_chinese_pattern = [Classes.CHAR(r"[\p{Han},。!?:「」『』…]"),
|
||||
|
|
61
src/uahgi.jl
61
src/uahgi.jl
|
@ -1,11 +1,28 @@
|
|||
module uahgi
|
||||
include("parsing.jl")
|
||||
include("interp.jl")
|
||||
include("arrange.jl")
|
||||
|
||||
using .Interp
|
||||
using .Parsing
|
||||
using .Arrange
|
||||
using ArgParse
|
||||
|
||||
export ChBox, HGlue
|
||||
abstract type Box end
|
||||
|
||||
"""
|
||||
a like-breakable discrete point.
|
||||
- before: the item before likebreaking
|
||||
- after: the item after linebreaking
|
||||
- orig: the status while not triggering like breaking
|
||||
"""
|
||||
mutable struct Disc<:Box
|
||||
before
|
||||
after
|
||||
orig
|
||||
end
|
||||
|
||||
"""
|
||||
Horizonal Box
|
||||
|
||||
|
@ -19,8 +36,21 @@ mutable struct HBox<:Box
|
|||
ht
|
||||
dp
|
||||
wd
|
||||
x
|
||||
y
|
||||
end
|
||||
|
||||
"""
|
||||
Horizonal Glue (HGlue)
|
||||
- wd: width
|
||||
- str : stretch
|
||||
"""
|
||||
mutable struct HGlue<:Box
|
||||
wd
|
||||
str
|
||||
end
|
||||
|
||||
|
||||
"""
|
||||
Vertical Box
|
||||
|
||||
|
@ -34,6 +64,8 @@ mutable struct VBox<:Box
|
|||
ht
|
||||
dp
|
||||
wd
|
||||
x
|
||||
y
|
||||
end
|
||||
|
||||
"""
|
||||
|
@ -53,6 +85,8 @@ mutable struct ChBox<:Box
|
|||
ht
|
||||
dp
|
||||
wd
|
||||
x
|
||||
y
|
||||
end
|
||||
|
||||
function parse_commandline()
|
||||
|
@ -64,7 +98,7 @@ function parse_commandline()
|
|||
@add_arg_table! s begin
|
||||
"FILE"
|
||||
help = "the file path to be converted."
|
||||
required = true
|
||||
required = false
|
||||
end
|
||||
|
||||
return parse_args(s)
|
||||
|
@ -74,6 +108,18 @@ end
|
|||
function main()
|
||||
parsed_args = parse_commandline()
|
||||
file_path = parsed_args["FILE"]
|
||||
if file_path === nothing
|
||||
#help string
|
||||
help = "usage: uahgi.jl [-h] [FILE]
|
||||
|
||||
positional arguments:
|
||||
FILE the file path to be converted.
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit"
|
||||
println(help)
|
||||
return 0
|
||||
end
|
||||
# for test
|
||||
#if parsed_args["FILE"] === nothing
|
||||
# file_path = "./example/ex1.ug"
|
||||
|
@ -85,11 +131,16 @@ function main()
|
|||
|
||||
|
||||
default_env = Dict() # the default environment for the intepreter
|
||||
output_box_orig = VBox([HBox([], nothing, nothing, nothing)],
|
||||
nothing, nothing, nothing)
|
||||
output_box_orig = VBox([HBox([], nothing, nothing, nothing, nothing, nothing)],
|
||||
nothing, nothing, nothing, nothing, nothing)
|
||||
output_box_result = Interp.interp_main(ast, default_env, output_box_orig)
|
||||
print("Env", output_box_result[2])
|
||||
print("OutPutBox", output_box_result[3])
|
||||
env = output_box_result[2]
|
||||
output_box = output_box_result[3]
|
||||
print(output_box)
|
||||
#TODO
|
||||
arranged = Arrange.arrange(output_box, env)
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue