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}
|
{@lang|en}
|
||||||
{@def|@font|{@quote|FreeSans|AR PL UKai TW}}
|
{@def|@font|{@quote|FreeSans|AR PL UKai TW}}
|
||||||
{@def|@fontsize|12}
|
{@def|@fontsize|12}
|
||||||
therapy of communication and pronounciation123%comment
|
{@def|@linewidth|200} %in px%
|
||||||
|
{@def|@spacing|{@hglue|{@ex|1}|2}}
|
||||||
anotherline%{@set|@fontsize|10} processing
|
{@def|@cjk_spacing|{@hglue|{@ex|0}|0.001}}
|
||||||
|
11111 222 3333333 444444 555555 666666 77777 88888 99999 000000 11111 22222 33333 55555
|
||||||
of the problem
|
|
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
|
u = Main.uahgi
|
||||||
c = Main.uahgi.Parsing.Passes.Classes
|
c = Main.uahgi.Parsing.Passes.Classes
|
||||||
|
|
||||||
|
@enum PutChar begin
|
||||||
|
true_ = 0
|
||||||
|
false_ = 1
|
||||||
|
gen_chbox_ = 2
|
||||||
|
end
|
||||||
|
|
||||||
function interp_main(ast, env, res_box)
|
function interp_main(ast, env, res_box)
|
||||||
ast_inner = ast.val
|
ast_inner = ast.val
|
||||||
val = nothing
|
val = nothing
|
||||||
|
@ -22,17 +28,33 @@ interp: the intepreter of the uahgi.
|
||||||
- ast: element or part of the ast
|
- ast: element or part of the ast
|
||||||
- env: the variable storaging environment
|
- env: the variable storaging environment
|
||||||
- res_box: the generated result box containing the content\
|
- 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)
|
#println("INTERP", ast)
|
||||||
@match ast begin
|
@match ast begin
|
||||||
c.SEQ([c.ELE([c.ID("def")]),
|
c.SEQ([c.ELE([c.ID("def")]),
|
||||||
c.ELE([c.ID(id)]),val]) =>
|
c.ELE([c.ID(id)]),val]) =>
|
||||||
begin
|
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)
|
#println("ID~~~", id, " VAL~~~", val_evaled)
|
||||||
|
if !haskey(env, id)
|
||||||
env[id] = val_evaled
|
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)
|
return (val_evaled, env, res_box)
|
||||||
end
|
end
|
||||||
c.SEQ([c.ELE([c.ID("quote")]),
|
c.SEQ([c.ELE([c.ID("quote")]),
|
||||||
|
@ -45,49 +67,107 @@ function interp(ast, env, res_box, put_char=true)
|
||||||
|
|
||||||
c.ELE([v...]) => begin
|
c.ELE([v...]) => begin
|
||||||
ele = reduce( (x, y) -> x*""*y,
|
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)
|
return (ele, env, res_box)
|
||||||
|
|
||||||
end
|
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
|
c.CHAR(ch) => begin
|
||||||
atomic_ch = ch[1]
|
atomic_ch = ch[1]
|
||||||
|
|
||||||
if put_char == true
|
if put_char == false_
|
||||||
|
return (ch, env, res_box)
|
||||||
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
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
font_family = select_font(atomic_ch, env)
|
||||||
|
|
||||||
font_path = get_font_path(font_family)
|
font_path = get_font_path(font_family)
|
||||||
font_size = parse(Int, env["fontsize"])
|
font_size = parse(Int, env["fontsize"])
|
||||||
glyph_metrics = PDFOperating.check_char_size(
|
glyph_metrics = PDFOperating.check_char_size(
|
||||||
atomic_ch, font_path, font_size)
|
atomic_ch, font_path, font_size)
|
||||||
|
chbox = u.ChBox(ch,
|
||||||
|
|
||||||
push!(res_box.eles[end].eles,
|
|
||||||
u.ChBox(ch,
|
|
||||||
font_path,
|
font_path,
|
||||||
font_size,
|
font_size,
|
||||||
glyph_metrics.ht,
|
glyph_metrics.ht,
|
||||||
glyph_metrics.dp,
|
glyph_metrics.dp,
|
||||||
glyph_metrics.wd))
|
glyph_metrics.wd,
|
||||||
end
|
nothing, nothing)
|
||||||
return (ch, env, res_box)
|
|
||||||
end
|
|
||||||
c.NL(nl) => return (nl, env, res_box)
|
|
||||||
c.SPACE(sp) => return (sp, env, res_box)
|
|
||||||
|
|
||||||
|
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
|
_ => begin
|
||||||
println("不知道")
|
println("不知道")
|
||||||
val_evaled = "不知道"
|
val_evaled = "不知道"
|
||||||
|
@ -144,6 +224,24 @@ function padding_zero(i)
|
||||||
return i
|
return i
|
||||||
end
|
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
|
end
|
|
@ -15,7 +15,7 @@ grammar rules of uahgi
|
||||||
|
|
||||||
comment = P"\%[^%]+\%"
|
comment = P"\%[^%]+\%"
|
||||||
newline = P"(\r?\n)" |> Passes.Classes.NL
|
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_name = p"[_a-zA-Z][_0-9a-zA-Z]*" > Passes.Classes.ID
|
||||||
id = E"@" + id_name
|
id = E"@" + id_name
|
||||||
|
@ -139,10 +139,4 @@ function ast_to_string(ast)
|
||||||
return str
|
return str
|
||||||
end
|
end
|
||||||
|
|
||||||
# Write your package code here.
|
|
||||||
#export cat
|
|
||||||
|
|
||||||
#cat = 1.2
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
|
@ -26,8 +26,7 @@ push!(processed_passes, two_nl_to_par_pass)
|
||||||
|
|
||||||
# in 2 hanzi add glue.
|
# in 2 hanzi add glue.
|
||||||
function insert_hglue_in_adjacent_chinese(two_nl)
|
function insert_hglue_in_adjacent_chinese(two_nl)
|
||||||
_0pt = Classes.SEQ([Classes.ID("pt"); Classes.CHAR(["0"])])
|
inner = Classes.ID("cjk_spacing")
|
||||||
inner = Classes.SEQ([Classes.ID("hglue"); _0pt])
|
|
||||||
return [two_nl[1]; inner; two_nl[2]]
|
return [two_nl[1]; inner; two_nl[2]]
|
||||||
end
|
end
|
||||||
adjacent_chinese_pattern = [Classes.CHAR(r"[\p{Han},。!?:「」『』…]"),
|
adjacent_chinese_pattern = [Classes.CHAR(r"[\p{Han},。!?:「」『』…]"),
|
||||||
|
|
61
src/uahgi.jl
61
src/uahgi.jl
|
@ -1,11 +1,28 @@
|
||||||
module uahgi
|
module uahgi
|
||||||
include("parsing.jl")
|
include("parsing.jl")
|
||||||
include("interp.jl")
|
include("interp.jl")
|
||||||
|
include("arrange.jl")
|
||||||
|
|
||||||
using .Interp
|
using .Interp
|
||||||
using .Parsing
|
using .Parsing
|
||||||
|
using .Arrange
|
||||||
using ArgParse
|
using ArgParse
|
||||||
|
|
||||||
|
export ChBox, HGlue
|
||||||
abstract type Box end
|
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
|
Horizonal Box
|
||||||
|
|
||||||
|
@ -19,8 +36,21 @@ mutable struct HBox<:Box
|
||||||
ht
|
ht
|
||||||
dp
|
dp
|
||||||
wd
|
wd
|
||||||
|
x
|
||||||
|
y
|
||||||
end
|
end
|
||||||
|
|
||||||
|
"""
|
||||||
|
Horizonal Glue (HGlue)
|
||||||
|
- wd: width
|
||||||
|
- str : stretch
|
||||||
|
"""
|
||||||
|
mutable struct HGlue<:Box
|
||||||
|
wd
|
||||||
|
str
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Vertical Box
|
Vertical Box
|
||||||
|
|
||||||
|
@ -34,6 +64,8 @@ mutable struct VBox<:Box
|
||||||
ht
|
ht
|
||||||
dp
|
dp
|
||||||
wd
|
wd
|
||||||
|
x
|
||||||
|
y
|
||||||
end
|
end
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
@ -53,6 +85,8 @@ mutable struct ChBox<:Box
|
||||||
ht
|
ht
|
||||||
dp
|
dp
|
||||||
wd
|
wd
|
||||||
|
x
|
||||||
|
y
|
||||||
end
|
end
|
||||||
|
|
||||||
function parse_commandline()
|
function parse_commandline()
|
||||||
|
@ -64,7 +98,7 @@ function parse_commandline()
|
||||||
@add_arg_table! s begin
|
@add_arg_table! s begin
|
||||||
"FILE"
|
"FILE"
|
||||||
help = "the file path to be converted."
|
help = "the file path to be converted."
|
||||||
required = true
|
required = false
|
||||||
end
|
end
|
||||||
|
|
||||||
return parse_args(s)
|
return parse_args(s)
|
||||||
|
@ -74,6 +108,18 @@ end
|
||||||
function main()
|
function main()
|
||||||
parsed_args = parse_commandline()
|
parsed_args = parse_commandline()
|
||||||
file_path = parsed_args["FILE"]
|
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
|
# for test
|
||||||
#if parsed_args["FILE"] === nothing
|
#if parsed_args["FILE"] === nothing
|
||||||
# file_path = "./example/ex1.ug"
|
# file_path = "./example/ex1.ug"
|
||||||
|
@ -85,11 +131,16 @@ function main()
|
||||||
|
|
||||||
|
|
||||||
default_env = Dict() # the default environment for the intepreter
|
default_env = Dict() # the default environment for the intepreter
|
||||||
output_box_orig = VBox([HBox([], nothing, nothing, nothing)],
|
output_box_orig = VBox([HBox([], nothing, nothing, nothing, nothing, nothing)],
|
||||||
nothing, nothing, nothing)
|
nothing, nothing, nothing, nothing, nothing)
|
||||||
output_box_result = Interp.interp_main(ast, default_env, output_box_orig)
|
output_box_result = Interp.interp_main(ast, default_env, output_box_orig)
|
||||||
print("Env", output_box_result[2])
|
env = output_box_result[2]
|
||||||
print("OutPutBox", output_box_result[3])
|
output_box = output_box_result[3]
|
||||||
|
print(output_box)
|
||||||
|
#TODO
|
||||||
|
arranged = Arrange.arrange(output_box, env)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue