Fix remaining legacy parsing issues

This commit is contained in:
LilyRose2798 2025-07-24 21:33:52 +10:00
parent 421924a339
commit 6029c4ea67
3 changed files with 269 additions and 154 deletions

View file

@ -1,3 +1,4 @@
import gleam/bit_array
import gleam/float import gleam/float
import gleam/int import gleam/int
import gleam/list import gleam/list
@ -187,7 +188,10 @@ fn do_string(source: BitArray, acc: List(UtfCodepoint)) -> Parsed(String) {
<<92, 114, rest:bits>> -> do_string(rest, [utf_codepoint_unsafe(13), ..acc]) <<92, 114, rest:bits>> -> do_string(rest, [utf_codepoint_unsafe(13), ..acc])
<<92, cp:utf8_codepoint, rest:bits>> -> do_string(rest, [cp, ..acc]) <<92, cp:utf8_codepoint, rest:bits>> -> do_string(rest, [cp, ..acc])
<<cp:utf8_codepoint, rest:bits>> -> do_string(rest, [cp, ..acc]) <<cp:utf8_codepoint, rest:bits>> -> do_string(rest, [cp, ..acc])
source -> Error(InvalidUtf8Character(source)) source ->
Error(InvalidUtf8Character(
source |> bit_array.slice(0, 4) |> result.unwrap(source),
))
} }
} }
@ -195,6 +199,7 @@ type ParsedType {
ParsedInt ParsedInt
ParsedFloat ParsedFloat
ParsedName ParsedName
ParsedString
} }
fn do_name_number( fn do_name_number(
@ -207,7 +212,7 @@ fn do_name_number(
rest, rest,
#([utf_codepoint_unsafe(i), ..cps], case cps { #([utf_codepoint_unsafe(i), ..cps], case cps {
[] -> parsed_type [] -> parsed_type
_ -> ParsedName _ -> ParsedString
}), }),
) )
<<46 as i, rest:bits>>, #(cps, parsed_type) -> <<46 as i, rest:bits>>, #(cps, parsed_type) ->
@ -215,7 +220,7 @@ fn do_name_number(
rest, rest,
#([utf_codepoint_unsafe(i), ..cps], case parsed_type { #([utf_codepoint_unsafe(i), ..cps], case parsed_type {
ParsedInt -> ParsedFloat ParsedInt -> ParsedFloat
_ -> ParsedName _ -> ParsedString
}), }),
) )
<<48 as i, rest:bits>>, #(cps, parsed_type) <<48 as i, rest:bits>>, #(cps, parsed_type)
@ -229,62 +234,77 @@ fn do_name_number(
| <<56 as i, rest:bits>>, #(cps, parsed_type) | <<56 as i, rest:bits>>, #(cps, parsed_type)
| <<57 as i, rest:bits>>, #(cps, parsed_type) | <<57 as i, rest:bits>>, #(cps, parsed_type)
-> do_name_number(rest, #([utf_codepoint_unsafe(i), ..cps], parsed_type)) -> do_name_number(rest, #([utf_codepoint_unsafe(i), ..cps], parsed_type))
<<65 as i, rest:bits>>, #(cps, _) <<65 as i, rest:bits>>, #(cps, parsed_type)
| <<66 as i, rest:bits>>, #(cps, _) | <<66 as i, rest:bits>>, #(cps, parsed_type)
| <<67 as i, rest:bits>>, #(cps, _) | <<67 as i, rest:bits>>, #(cps, parsed_type)
| <<68 as i, rest:bits>>, #(cps, _) | <<68 as i, rest:bits>>, #(cps, parsed_type)
| <<69 as i, rest:bits>>, #(cps, _) | <<69 as i, rest:bits>>, #(cps, parsed_type)
| <<70 as i, rest:bits>>, #(cps, _) | <<70 as i, rest:bits>>, #(cps, parsed_type)
| <<71 as i, rest:bits>>, #(cps, _) | <<71 as i, rest:bits>>, #(cps, parsed_type)
| <<72 as i, rest:bits>>, #(cps, _) | <<72 as i, rest:bits>>, #(cps, parsed_type)
| <<73 as i, rest:bits>>, #(cps, _) | <<73 as i, rest:bits>>, #(cps, parsed_type)
| <<74 as i, rest:bits>>, #(cps, _) | <<74 as i, rest:bits>>, #(cps, parsed_type)
| <<75 as i, rest:bits>>, #(cps, _) | <<75 as i, rest:bits>>, #(cps, parsed_type)
| <<76 as i, rest:bits>>, #(cps, _) | <<76 as i, rest:bits>>, #(cps, parsed_type)
| <<77 as i, rest:bits>>, #(cps, _) | <<77 as i, rest:bits>>, #(cps, parsed_type)
| <<78 as i, rest:bits>>, #(cps, _) | <<78 as i, rest:bits>>, #(cps, parsed_type)
| <<79 as i, rest:bits>>, #(cps, _) | <<79 as i, rest:bits>>, #(cps, parsed_type)
| <<80 as i, rest:bits>>, #(cps, _) | <<80 as i, rest:bits>>, #(cps, parsed_type)
| <<81 as i, rest:bits>>, #(cps, _) | <<81 as i, rest:bits>>, #(cps, parsed_type)
| <<82 as i, rest:bits>>, #(cps, _) | <<82 as i, rest:bits>>, #(cps, parsed_type)
| <<83 as i, rest:bits>>, #(cps, _) | <<83 as i, rest:bits>>, #(cps, parsed_type)
| <<84 as i, rest:bits>>, #(cps, _) | <<84 as i, rest:bits>>, #(cps, parsed_type)
| <<85 as i, rest:bits>>, #(cps, _) | <<85 as i, rest:bits>>, #(cps, parsed_type)
| <<86 as i, rest:bits>>, #(cps, _) | <<86 as i, rest:bits>>, #(cps, parsed_type)
| <<87 as i, rest:bits>>, #(cps, _) | <<87 as i, rest:bits>>, #(cps, parsed_type)
| <<88 as i, rest:bits>>, #(cps, _) | <<88 as i, rest:bits>>, #(cps, parsed_type)
| <<89 as i, rest:bits>>, #(cps, _) | <<89 as i, rest:bits>>, #(cps, parsed_type)
| <<90 as i, rest:bits>>, #(cps, _) | <<90 as i, rest:bits>>, #(cps, parsed_type)
| <<97 as i, rest:bits>>, #(cps, _) | <<97 as i, rest:bits>>, #(cps, parsed_type)
| <<98 as i, rest:bits>>, #(cps, _) | <<98 as i, rest:bits>>, #(cps, parsed_type)
| <<99 as i, rest:bits>>, #(cps, _) | <<99 as i, rest:bits>>, #(cps, parsed_type)
| <<100 as i, rest:bits>>, #(cps, _) | <<100 as i, rest:bits>>, #(cps, parsed_type)
| <<101 as i, rest:bits>>, #(cps, _) | <<101 as i, rest:bits>>, #(cps, parsed_type)
| <<102 as i, rest:bits>>, #(cps, _) | <<102 as i, rest:bits>>, #(cps, parsed_type)
| <<103 as i, rest:bits>>, #(cps, _) | <<103 as i, rest:bits>>, #(cps, parsed_type)
| <<104 as i, rest:bits>>, #(cps, _) | <<104 as i, rest:bits>>, #(cps, parsed_type)
| <<105 as i, rest:bits>>, #(cps, _) | <<105 as i, rest:bits>>, #(cps, parsed_type)
| <<106 as i, rest:bits>>, #(cps, _) | <<106 as i, rest:bits>>, #(cps, parsed_type)
| <<107 as i, rest:bits>>, #(cps, _) | <<107 as i, rest:bits>>, #(cps, parsed_type)
| <<108 as i, rest:bits>>, #(cps, _) | <<108 as i, rest:bits>>, #(cps, parsed_type)
| <<109 as i, rest:bits>>, #(cps, _) | <<109 as i, rest:bits>>, #(cps, parsed_type)
| <<110 as i, rest:bits>>, #(cps, _) | <<110 as i, rest:bits>>, #(cps, parsed_type)
| <<111 as i, rest:bits>>, #(cps, _) | <<111 as i, rest:bits>>, #(cps, parsed_type)
| <<112 as i, rest:bits>>, #(cps, _) | <<112 as i, rest:bits>>, #(cps, parsed_type)
| <<113 as i, rest:bits>>, #(cps, _) | <<113 as i, rest:bits>>, #(cps, parsed_type)
| <<114 as i, rest:bits>>, #(cps, _) | <<114 as i, rest:bits>>, #(cps, parsed_type)
| <<115 as i, rest:bits>>, #(cps, _) | <<115 as i, rest:bits>>, #(cps, parsed_type)
| <<116 as i, rest:bits>>, #(cps, _) | <<116 as i, rest:bits>>, #(cps, parsed_type)
| <<117 as i, rest:bits>>, #(cps, _) | <<117 as i, rest:bits>>, #(cps, parsed_type)
| <<118 as i, rest:bits>>, #(cps, _) | <<118 as i, rest:bits>>, #(cps, parsed_type)
| <<119 as i, rest:bits>>, #(cps, _) | <<119 as i, rest:bits>>, #(cps, parsed_type)
| <<120 as i, rest:bits>>, #(cps, _) | <<120 as i, rest:bits>>, #(cps, parsed_type)
| <<121 as i, rest:bits>>, #(cps, _) | <<121 as i, rest:bits>>, #(cps, parsed_type)
| <<122 as i, rest:bits>>, #(cps, _) | <<122 as i, rest:bits>>, #(cps, parsed_type)
| <<95 as i, rest:bits>>, #(cps, _) | <<95 as i, rest:bits>>, #(cps, parsed_type)
| <<42 as i, rest:bits>>, #(cps, _) ->
-> do_name_number(rest, #([utf_codepoint_unsafe(i), ..cps], ParsedName)) do_name_number(
source, #(cps, parsed_type) -> { rest,
#([utf_codepoint_unsafe(i), ..cps], case parsed_type {
ParsedInt | ParsedFloat -> ParsedName
x -> x
}),
)
<<32, source:bits>>, #(cps, parsed_type)
| <<9, source:bits>>, #(cps, parsed_type)
| <<10, source:bits>>, #(cps, parsed_type)
| <<11, source:bits>>, #(cps, parsed_type)
| <<12, source:bits>>, #(cps, parsed_type)
| <<13, source:bits>>, #(cps, parsed_type)
| <<34, _:bits>> as source, #(cps, parsed_type)
| <<40, _:bits>> as source, #(cps, parsed_type)
| <<41, _:bits>> as source, #(cps, parsed_type)
-> {
let str = cps |> list.reverse |> string.from_utf_codepoints let str = cps |> list.reverse |> string.from_utf_codepoints
case parsed_type { case parsed_type {
ParsedInt -> ParsedInt ->
@ -298,7 +318,14 @@ fn do_name_number(
Error(Nil) -> Ok(#(Name(str), source)) Error(Nil) -> Ok(#(Name(str), source))
} }
ParsedName -> Ok(#(Name(str), source)) ParsedName -> Ok(#(Name(str), source))
ParsedString -> Ok(#(String(str), source))
} }
} }
<<cp:utf8_codepoint, rest:bits>>, #(cps, _) ->
do_name_number(rest, #([cp, ..cps], ParsedString))
source, #(_, _) ->
Error(InvalidUtf8Character(
source |> bit_array.slice(0, 4) |> result.unwrap(source),
))
} }
} }

View file

@ -1,5 +1,5 @@
import gleam/list import gleam/list
import gleam/option.{type Option} import gleam/option.{type Option, None, Some}
import gleam/pair import gleam/pair
import kicad_sexpr/decode.{type Decoder, type NextFn} import kicad_sexpr/decode.{type Decoder, type NextFn}
@ -19,7 +19,7 @@ fn allowed(then next: NextFn(Bool, a)) -> Decoder(a) {
decode.enum(with: [#("allowed", True), #("not_allowed", False)], then: next) decode.enum(with: [#("allowed", True), #("not_allowed", False)], then: next)
} }
fn fill_flag(then next: NextFn(Bool, a)) -> Decoder(a) { fn filled(then next: NextFn(Bool, a)) -> Decoder(a) {
decode.token_wrapper(named: "fill", with: yes_no, then: next) decode.token_wrapper(named: "fill", with: yes_no, then: next)
} }
@ -52,7 +52,11 @@ fn margins(then next: NextFn(#(Float, Float, Float, Float), a)) -> Decoder(a) {
} }
fn hide(then next: NextFn(Bool, a)) -> Decoder(a) { fn hide(then next: NextFn(Bool, a)) -> Decoder(a) {
decode.token_wrapper(named: "hide", with: yes_no, then: next) decode.one_of(
decode.token_wrapper(named: "hide", with: yes_no, then: _),
or: [decode.flag("hide", then: _)],
then: next,
)
} }
fn custom_xy(named name: String, then next: NextFn(XY, a)) -> Decoder(a) { fn custom_xy(named name: String, then next: NextFn(XY, a)) -> Decoder(a) {
@ -65,14 +69,19 @@ fn custom_xy(named name: String, then next: NextFn(XY, a)) -> Decoder(a) {
fn layers(then next: NextFn(List(Layer), a)) -> Decoder(a) { fn layers(then next: NextFn(List(Layer), a)) -> Decoder(a) {
decode.token(named: "layers", then: next, with: { decode.token(named: "layers", then: next, with: {
use layers <- decode.list(decode.name_or_string) use layers <- decode.list(decode.name_string)
let layers = list.map(layers, Layer) let layers = list.map(layers, Layer)
decode.success(layers) decode.success(layers)
}) })
} }
pub type PositionIdentifier { pub type PositionIdentifier {
PositionIdentifier(x: Float, y: Float, angle: Option(Float)) PositionIdentifier(
x: Float,
y: Float,
angle: Option(Float),
locked: Option(Bool),
)
} }
pub fn position_identifier( pub fn position_identifier(
@ -82,7 +91,11 @@ pub fn position_identifier(
use x <- decode.float() use x <- decode.float()
use y <- decode.float() use y <- decode.float()
use angle <- decode.optional(decode.float) use angle <- decode.optional(decode.float)
decode.success(PositionIdentifier(x:, y:, angle:)) use locked <- decode.optional(decode.enum(
[#("locked", True), #("unlocked", False)],
then: _,
))
decode.success(PositionIdentifier(x:, y:, angle:, locked:))
}) })
} }
@ -257,19 +270,21 @@ pub fn stroke(then next: NextFn(Stroke, a)) -> Decoder(a) {
pub type FillType { pub type FillType {
NoFill NoFill
SolidFillType
OutlineFillType OutlineFillType
BackgroundFillType BackgroundFillType
} }
pub fn fill_type(then next: NextFn(FillType, a)) -> Decoder(a) { pub fn fill_type(then next: NextFn(FillType, a)) -> Decoder(a) {
decode.token(named: "type", then: next, with: { decode.enum(
use value <- decode.enum([ [
#("none", NoFill), #("none", NoFill),
#("solid", SolidFillType),
#("outline", OutlineFillType), #("outline", OutlineFillType),
#("background", BackgroundFillType), #("background", BackgroundFillType),
]) ],
decode.success(value) then: next,
}) )
} }
pub type Fill { pub type Fill {
@ -278,7 +293,10 @@ pub type Fill {
pub fn fill(then next: NextFn(Fill, a)) -> Decoder(a) { pub fn fill(then next: NextFn(Fill, a)) -> Decoder(a) {
decode.token(named: "fill", then: next, with: { decode.token(named: "fill", then: next, with: {
use type_ <- fill_type() use type_ <- decode.one_of(
decode.token_wrapper(named: "type", with: fill_type, then: _),
or: [fill_type],
)
decode.success(Fill(type_:)) decode.success(Fill(type_:))
}) })
} }
@ -315,14 +333,14 @@ pub fn font(then next: NextFn(Font, a)) -> Decoder(a) {
)) ))
use size <- size() use size <- size()
use thickness <- decode.optional(thickness) use thickness <- decode.optional(thickness)
use bold <- decode.optional(decode.token_wrapper( use bold <- decode.optional(decode.one_of(
named: "bold", decode.token_wrapper(named: "bold", with: yes_no, then: _),
with: yes_no, or: [decode.flag("bold", then: _)],
then: _, then: _,
)) ))
use italic <- decode.optional(decode.token_wrapper( use italic <- decode.optional(decode.one_of(
named: "italic", decode.token_wrapper(named: "italic", with: yes_no, then: _),
with: yes_no, or: [decode.flag("italic", then: _)],
then: _, then: _,
)) ))
use line_spacing <- decode.optional(decode.token_wrapper( use line_spacing <- decode.optional(decode.token_wrapper(
@ -497,7 +515,7 @@ pub type Timestamp {
pub fn timestamp(then next: NextFn(Timestamp, a)) -> Decoder(a) { pub fn timestamp(then next: NextFn(Timestamp, a)) -> Decoder(a) {
decode.token(named: "tstamp", then: next, with: { decode.token(named: "tstamp", then: next, with: {
use ts <- decode.name_string() use ts <- decode.string()
decode.success(Timestamp(ts:)) decode.success(Timestamp(ts:))
}) })
} }
@ -508,7 +526,7 @@ pub type Layer {
pub fn layer(then next: NextFn(Layer, a)) -> Decoder(a) { pub fn layer(then next: NextFn(Layer, a)) -> Decoder(a) {
decode.token(named: "layer", then: next, with: { decode.token(named: "layer", then: next, with: {
use layer <- decode.name_or_string() use layer <- decode.name_string()
decode.success(Layer(layer:)) decode.success(Layer(layer:))
}) })
} }
@ -671,7 +689,7 @@ pub type FootprintText {
pub fn footprint_text(then next: NextFn(FootprintText, a)) -> Decoder(a) { pub fn footprint_text(then next: NextFn(FootprintText, a)) -> Decoder(a) {
decode.token(named: "fp_text", then: next, with: { decode.token(named: "fp_text", then: next, with: {
use type_ <- footprint_text_type() use type_ <- footprint_text_type()
use text <- decode.string() use text <- decode.name_string()
use position <- position_identifier() use position <- position_identifier()
use unlocked <- decode.optional(decode.token_wrapper( use unlocked <- decode.optional(decode.token_wrapper(
named: "unlocked", named: "unlocked",
@ -734,7 +752,7 @@ pub fn footprint_text_box(then next: NextFn(FootprintTextBox, a)) -> Decoder(a)
then: _, then: _,
)) ))
use stroke <- decode.optional(stroke) use stroke <- decode.optional(stroke)
let render_cache = option.None let render_cache = None
use timestamp <- decode.optional(timestamp) use timestamp <- decode.optional(timestamp)
decode.success(FootprintTextBox( decode.success(FootprintTextBox(
locked:, locked:,
@ -796,8 +814,10 @@ pub type FootprintRectangle {
start: XY, start: XY,
end: XY, end: XY,
stroke: Option(Stroke), stroke: Option(Stroke),
fill: Option(Bool), filled: Option(Bool),
layer: Layer, layer: Layer,
fill: Option(Fill),
width: Option(Float),
locked: Bool, locked: Bool,
uuid: Option(Uuid), uuid: Option(Uuid),
timestamp: Option(Timestamp), timestamp: Option(Timestamp),
@ -811,8 +831,12 @@ pub fn footprint_rectangle(
use start <- custom_xy("start") use start <- custom_xy("start")
use end <- custom_xy("end") use end <- custom_xy("end")
use stroke <- decode.optional(stroke) use stroke <- decode.optional(stroke)
use fill <- decode.optional(fill_flag) use filled <- decode.optional(filled)
use layer <- layer() use layer <- layer()
use fill_a <- decode.optional(fill)
use width <- decode.optional(width)
use fill_b <- decode.optional(fill)
let fill = fill_a |> option.or(fill_b)
use locked <- decode.flag("locked") use locked <- decode.flag("locked")
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
use timestamp <- decode.optional(timestamp) use timestamp <- decode.optional(timestamp)
@ -820,8 +844,10 @@ pub fn footprint_rectangle(
start:, start:,
end:, end:,
stroke:, stroke:,
fill:, filled:,
layer:, layer:,
fill:,
width:,
locked:, locked:,
uuid:, uuid:,
timestamp:, timestamp:,
@ -834,8 +860,10 @@ pub type FootprintCircle {
center: XY, center: XY,
end: XY, end: XY,
stroke: Option(Stroke), stroke: Option(Stroke),
fill: Option(Bool), filled: Option(Bool),
layer: Layer, layer: Layer,
fill: Option(Fill),
width: Option(Float),
locked: Bool, locked: Bool,
uuid: Option(Uuid), uuid: Option(Uuid),
timestamp: Option(Timestamp), timestamp: Option(Timestamp),
@ -847,8 +875,12 @@ pub fn footprint_circle(then next: NextFn(FootprintCircle, a)) -> Decoder(a) {
use center <- custom_xy("center") use center <- custom_xy("center")
use end <- custom_xy("end") use end <- custom_xy("end")
use stroke <- decode.optional(stroke) use stroke <- decode.optional(stroke)
use fill <- decode.optional(fill_flag) use filled <- decode.optional(filled)
use layer <- layer() use layer <- layer()
use fill_a <- decode.optional(fill)
use width <- decode.optional(width)
use fill_b <- decode.optional(fill)
let fill = fill_a |> option.or(fill_b)
use locked <- decode.flag("locked") use locked <- decode.flag("locked")
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
use timestamp <- decode.optional(timestamp) use timestamp <- decode.optional(timestamp)
@ -856,8 +888,10 @@ pub fn footprint_circle(then next: NextFn(FootprintCircle, a)) -> Decoder(a) {
center:, center:,
end:, end:,
stroke:, stroke:,
fill:, filled:,
layer:, layer:,
fill:,
width:,
locked:, locked:,
uuid:, uuid:,
timestamp:, timestamp:,
@ -872,6 +906,7 @@ pub type FootprintArc {
end: XY, end: XY,
stroke: Option(Stroke), stroke: Option(Stroke),
layer: Layer, layer: Layer,
width: Option(Float),
locked: Bool, locked: Bool,
uuid: Option(Uuid), uuid: Option(Uuid),
timestamp: Option(Timestamp), timestamp: Option(Timestamp),
@ -885,6 +920,7 @@ pub fn footprint_arc(then next: NextFn(FootprintArc, a)) -> Decoder(a) {
use end <- custom_xy("end") use end <- custom_xy("end")
use stroke <- decode.optional(stroke) use stroke <- decode.optional(stroke)
use layer <- layer() use layer <- layer()
use width <- decode.optional(width)
use locked <- decode.flag("locked") use locked <- decode.flag("locked")
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
use timestamp <- decode.optional(timestamp) use timestamp <- decode.optional(timestamp)
@ -894,6 +930,7 @@ pub fn footprint_arc(then next: NextFn(FootprintArc, a)) -> Decoder(a) {
end:, end:,
stroke:, stroke:,
layer:, layer:,
width:,
locked:, locked:,
uuid:, uuid:,
timestamp:, timestamp:,
@ -905,8 +942,10 @@ pub type FootprintPolygon {
FootprintPolygon( FootprintPolygon(
points: PolyPoints, points: PolyPoints,
stroke: Option(Stroke), stroke: Option(Stroke),
fill: Option(Bool), filled: Option(Bool),
layer: Layer, layer: Layer,
fill: Option(Fill),
width: Option(Float),
locked: Bool, locked: Bool,
uuid: Option(Uuid), uuid: Option(Uuid),
timestamp: Option(Timestamp), timestamp: Option(Timestamp),
@ -917,16 +956,22 @@ pub fn footprint_polygon(then next: NextFn(FootprintPolygon, a)) -> Decoder(a) {
decode.token(named: "fp_poly", then: next, with: { decode.token(named: "fp_poly", then: next, with: {
use points <- poly_points() use points <- poly_points()
use stroke <- decode.optional(stroke) use stroke <- decode.optional(stroke)
use fill <- decode.optional(fill_flag) use filled <- decode.optional(filled)
use layer <- layer() use layer <- layer()
use fill_a <- decode.optional(fill)
use width <- decode.optional(width)
use fill_b <- decode.optional(fill)
let fill = fill_a |> option.or(fill_b)
use locked <- decode.flag("locked") use locked <- decode.flag("locked")
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
use timestamp <- decode.optional(timestamp) use timestamp <- decode.optional(timestamp)
decode.success(FootprintPolygon( decode.success(FootprintPolygon(
points:, points:,
stroke:, stroke:,
fill:, filled:,
layer:, layer:,
fill:,
width:,
locked:, locked:,
uuid:, uuid:,
timestamp:, timestamp:,
@ -939,6 +984,7 @@ pub type FootprintCurve {
points: Points, points: Points,
stroke: Option(Stroke), stroke: Option(Stroke),
layer: Layer, layer: Layer,
width: Option(Float),
locked: Bool, locked: Bool,
uuid: Option(Uuid), uuid: Option(Uuid),
timestamp: Option(Timestamp), timestamp: Option(Timestamp),
@ -950,6 +996,7 @@ pub fn footprint_curve(then next: NextFn(FootprintCurve, a)) -> Decoder(a) {
use points <- points() use points <- points()
use stroke <- decode.optional(stroke) use stroke <- decode.optional(stroke)
use layer <- layer() use layer <- layer()
use width <- decode.optional(width)
use locked <- decode.flag("locked") use locked <- decode.flag("locked")
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
use timestamp <- decode.optional(timestamp) use timestamp <- decode.optional(timestamp)
@ -957,6 +1004,7 @@ pub fn footprint_curve(then next: NextFn(FootprintCurve, a)) -> Decoder(a) {
points:, points:,
stroke:, stroke:,
layer:, layer:,
width:,
locked:, locked:,
uuid:, uuid:,
timestamp:, timestamp:,
@ -1334,7 +1382,7 @@ pub fn graphical_text_box(then next: NextFn(GraphicalTextBox, a)) -> Decoder(a)
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
use effects <- effects() use effects <- effects()
use stroke <- decode.optional(stroke) use stroke <- decode.optional(stroke)
let render_cache = option.None let render_cache = None
decode.success(GraphicalTextBox( decode.success(GraphicalTextBox(
locked:, locked:,
text:, text:,
@ -1393,7 +1441,7 @@ pub fn graphical_rectangle(
use end <- custom_xy("end") use end <- custom_xy("end")
use layer <- decode.optional(layer) use layer <- decode.optional(layer)
use width <- width() use width <- width()
use fill <- decode.optional(fill_flag) use fill <- decode.optional(filled)
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
decode.success(GraphicalRectangle( decode.success(GraphicalRectangle(
start:, start:,
@ -1423,7 +1471,7 @@ pub fn graphical_circle(then next: NextFn(GraphicalCircle, a)) -> Decoder(a) {
use end <- custom_xy("end") use end <- custom_xy("end")
use layer <- decode.optional(layer) use layer <- decode.optional(layer)
use width <- width() use width <- width()
use fill <- decode.optional(fill_flag) use fill <- decode.optional(filled)
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
decode.success(GraphicalCircle(center:, end:, layer:, width:, fill:, uuid:)) decode.success(GraphicalCircle(center:, end:, layer:, width:, fill:, uuid:))
}) })
@ -1467,7 +1515,7 @@ pub fn graphical_polygon(then next: NextFn(GraphicalPolygon, a)) -> Decoder(a) {
use points <- poly_points() use points <- poly_points()
use layer <- decode.optional(layer) use layer <- decode.optional(layer)
use width <- width() use width <- width()
use fill <- decode.optional(fill_flag) use fill <- decode.optional(filled)
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
decode.success(GraphicalPolygon(points:, layer:, width:, fill:, uuid:)) decode.success(GraphicalPolygon(points:, layer:, width:, fill:, uuid:))
}) })
@ -1780,12 +1828,7 @@ pub fn symbol_pin(then next: NextFn(SymbolPin, a)) -> Decoder(a) {
use graphical_style <- pin_graphical_style() use graphical_style <- pin_graphical_style()
use position <- position_identifier() use position <- position_identifier()
use length <- decode.token_wrapper(named: "length", with: decode.float) use length <- decode.token_wrapper(named: "length", with: decode.float)
use hide_flag <- decode.flag("hide") use hide <- decode.optional(hide)
use hide <-
case hide_flag {
True -> decode.of(with: decode.success(option.Some(True)), then: _)
False -> decode.optional(hide, then: _)
}
use name <- pin_name() use name <- pin_name()
use number <- pin_number() use number <- pin_number()
use alternatives <- decode.list(pin_alternate) use alternatives <- decode.list(pin_alternate)
@ -2005,7 +2048,7 @@ pub fn custom_pad_primitives(
decode.token(named: "primitives", then: next, with: { decode.token(named: "primitives", then: next, with: {
use graphic_items <- decode.list(graphic_item) use graphic_items <- decode.list(graphic_item)
use width <- decode.optional(width) use width <- decode.optional(width)
use fill <- decode.optional(fill_flag) use fill <- decode.optional(filled)
decode.success(CustomPadPrimitives(graphic_items:, width:, fill:)) decode.success(CustomPadPrimitives(graphic_items:, width:, fill:))
}) })
} }
@ -2049,7 +2092,7 @@ pub type Pad {
pub fn pad(then next: NextFn(Pad, a)) -> Decoder(a) { pub fn pad(then next: NextFn(Pad, a)) -> Decoder(a) {
decode.token(named: "pad", then: next, with: { decode.token(named: "pad", then: next, with: {
use number <- decode.string() use number <- decode.name_number_string()
use type_ <- pad_type() use type_ <- pad_type()
use shape <- pad_shape() use shape <- pad_shape()
use position <- position_identifier() use position <- position_identifier()
@ -2065,14 +2108,16 @@ pub fn pad(then next: NextFn(Pad, a)) -> Decoder(a) {
use layers <- layers() use layers <- layers()
use remove_unused_layers <- decode.optional(decode.token_wrapper( use remove_unused_layers <- decode.optional(decode.token_wrapper(
named: "remove_unused_layers", named: "remove_unused_layers",
with: yes_no, with: decode.optional(yes_no, then: _),
then: _, then: _,
)) ))
let remove_unused_layers = option.flatten(remove_unused_layers)
use keep_end_layers <- decode.optional(decode.token_wrapper( use keep_end_layers <- decode.optional(decode.token_wrapper(
named: "keep_end_layers", named: "keep_end_layers",
with: yes_no, with: decode.optional(yes_no, then: _),
then: _, then: _,
)) ))
let keep_end_layers = option.flatten(keep_end_layers)
use roundrect_rratio <- decode.optional(decode.token_wrapper( use roundrect_rratio <- decode.optional(decode.token_wrapper(
named: "roundrect_rratio", named: "roundrect_rratio",
with: decode.float, with: decode.float,
@ -2485,6 +2530,7 @@ pub type Zone {
net_name: String, net_name: String,
layers: List(Layer), layers: List(Layer),
uuid: Option(Uuid), uuid: Option(Uuid),
timestamp: Option(Timestamp),
name: Option(String), name: Option(String),
hatch: Hatch, hatch: Hatch,
priority: Option(Int), priority: Option(Int),
@ -2506,6 +2552,7 @@ pub fn zone(then next: NextFn(Zone, a)) -> Decoder(a) {
use net_name <- decode.token_wrapper(named: "net_name", with: decode.string) use net_name <- decode.token_wrapper(named: "net_name", with: decode.string)
use layers <- decode.one_of(layer |> decode.map(list.wrap), or: [layers]) use layers <- decode.one_of(layer |> decode.map(list.wrap), or: [layers])
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
use timestamp <- decode.optional(timestamp)
use name <- decode.optional(decode.token_wrapper( use name <- decode.optional(decode.token_wrapper(
named: "name", named: "name",
with: decode.string, with: decode.string,
@ -2538,6 +2585,7 @@ pub fn zone(then next: NextFn(Zone, a)) -> Decoder(a) {
net_name:, net_name:,
layers:, layers:,
uuid:, uuid:,
timestamp:,
name:, name:,
hatch:, hatch:,
priority:, priority:,
@ -2585,7 +2633,10 @@ pub fn footprint_model(then next: NextFn(FootprintModel, a)) -> Decoder(a) {
decode.token(named: "model", then: next, with: { decode.token(named: "model", then: next, with: {
use file <- decode.string() use file <- decode.string()
use hide <- decode.optional(hide) use hide <- decode.optional(hide)
use offset <- decode.token_wrapper(named: "offset", with: xyz) use offset <- decode.one_of(
decode.token_wrapper(named: "offset", with: xyz, then: _),
or: [decode.token_wrapper(named: "at", with: xyz, then: _)],
)
use scale <- decode.token_wrapper(named: "scale", with: xyz) use scale <- decode.token_wrapper(named: "scale", with: xyz)
use rotate <- decode.token_wrapper(named: "rotate", with: xyz) use rotate <- decode.token_wrapper(named: "rotate", with: xyz)
decode.success(FootprintModel(file:, hide:, offset:, scale:, rotate:)) decode.success(FootprintModel(file:, hide:, offset:, scale:, rotate:))
@ -2635,7 +2686,7 @@ fn base_footprint(then next: NextFn(Footprint, a)) -> Decoder(a) {
use layer <- layer() use layer <- layer()
use tedit <- decode.optional(decode.token_wrapper( use tedit <- decode.optional(decode.token_wrapper(
named: "tedit", named: "tedit",
with: decode.name_or_string, with: decode.name_number_string,
then: _, then: _,
)) ))
use uuid <- decode.optional(uuid) use uuid <- decode.optional(uuid)
@ -2656,6 +2707,7 @@ fn base_footprint(then next: NextFn(Footprint, a)) -> Decoder(a) {
with: decode.string, with: decode.string,
then: _, then: _,
)) ))
use attributes_a <- decode.optional(footprint_attributes)
use autoplace_cost_90 <- decode.optional(decode.token_wrapper( use autoplace_cost_90 <- decode.optional(decode.token_wrapper(
named: "autoplace_cost90", named: "autoplace_cost90",
with: decode.int, with: decode.int,
@ -2708,7 +2760,8 @@ fn base_footprint(then next: NextFn(Footprint, a)) -> Decoder(a) {
with: decode.float, with: decode.float,
then: _, then: _,
)) ))
use attributes <- decode.optional(footprint_attributes) use attributes_b <- decode.optional(footprint_attributes)
let attributes = attributes_a |> option.or(attributes_b)
use private_layers <- decode.optional(decode.token_wrapper( use private_layers <- decode.optional(decode.token_wrapper(
named: "private_layers", named: "private_layers",
with: decode.list(decode.string, then: _), with: decode.list(decode.string, then: _),
@ -2719,8 +2772,10 @@ fn base_footprint(then next: NextFn(Footprint, a)) -> Decoder(a) {
with: decode.list(decode.string, then: _), with: decode.list(decode.string, then: _),
then: _, then: _,
)) ))
use graphic_items <- decode.list(footprint_graphic_item) use graphic_items_a <- decode.list(footprint_graphic_item)
use pads <- decode.list(pad) use pads <- decode.list(pad)
use graphic_items_b <- decode.list(footprint_graphic_item)
let graphic_items = list.append(graphic_items_a, graphic_items_b)
use zones <- decode.list(zone) use zones <- decode.list(zone)
use groups <- decode.list(group) use groups <- decode.list(group)
use embedded_fonts <- decode.optional(decode.token_wrapper( use embedded_fonts <- decode.optional(decode.token_wrapper(
@ -2771,35 +2826,64 @@ pub fn footprint(then next: NextFn(Footprint, a)) -> Decoder(a) {
pub type FootprintFile { pub type FootprintFile {
FootprintFile( FootprintFile(
name: String, name: String,
version: Int, version: Option(Int),
generator: String, generator: Option(String),
generator_version: Option(String), generator_version: Option(String),
footprint: Footprint, footprint: Footprint,
) )
} }
pub fn footprint_file(then next: NextFn(FootprintFile, a)) -> Decoder(a) { pub fn footprint_file(then next: NextFn(FootprintFile, a)) -> Decoder(a) {
decode.token(named: "footprint", then: next, with: { decode.one_of(
use name <- decode.string() decode.token(
use version <- decode.token_wrapper(named: "version", with: decode.int) named: "footprint",
use generator <- decode.token_wrapper( with: {
named: "generator", use name <- decode.string()
with: decode.name_or_string, use version <- decode.token_wrapper(named: "version", with: decode.int)
) let version = Some(version)
use generator_version <- decode.optional(decode.token_wrapper( use generator <- decode.token_wrapper(
named: "generator_version", named: "generator",
with: decode.string, with: decode.name_string,
)
let generator = Some(generator)
use generator_version <- decode.optional(decode.token_wrapper(
named: "generator_version",
with: decode.string,
then: _,
))
use footprint <- base_footprint()
decode.success(FootprintFile(
name:,
version:,
generator:,
generator_version:,
footprint:,
))
},
then: _, then: _,
)) ),
use footprint <- base_footprint() or: [
decode.success(FootprintFile( decode.token(
name:, named: "module",
version:, with: {
generator:, use name <- decode.name_string()
generator_version:, let version = None
footprint:, let generator = None
)) let generator_version = None
}) use footprint <- base_footprint()
decode.success(FootprintFile(
name:,
version:,
generator:,
generator_version:,
footprint:,
))
},
then: _,
),
],
then: next,
)
} }
pub type SymbolProperty { pub type SymbolProperty {
@ -2863,7 +2947,7 @@ pub type Symbol {
fn base_symbol(then next: NextFn(Symbol, a)) -> Decoder(a) { fn base_symbol(then next: NextFn(Symbol, a)) -> Decoder(a) {
decode.of(then: next, with: { decode.of(then: next, with: {
use library_unit_id <- decode.string use library_unit_id <- decode.string()
use extends <- decode.optional(decode.token_wrapper( use extends <- decode.optional(decode.token_wrapper(
named: "extends", named: "extends",
with: decode.string, with: decode.string,
@ -2963,7 +3047,7 @@ pub fn symbol_library(then next: NextFn(SymbolLibrary, a)) -> Decoder(a) {
use version <- decode.token_wrapper(named: "version", with: decode.int) use version <- decode.token_wrapper(named: "version", with: decode.int)
use generator <- decode.token_wrapper( use generator <- decode.token_wrapper(
named: "generator", named: "generator",
with: decode.string, with: decode.name_string,
) )
use generator_version <- decode.optional(decode.token_wrapper( use generator_version <- decode.optional(decode.token_wrapper(
named: "generator_version", named: "generator_version",

View file

@ -2,8 +2,6 @@ import gleam/float
import gleam/int import gleam/int
import gleam/io import gleam/io
import gleam/list import gleam/list
// import gleam/pair
import gleam/result import gleam/result
import gleam/string import gleam/string
import gleam/time/duration import gleam/time/duration
@ -18,21 +16,19 @@ pub fn main() -> Nil {
io.println("\nTesting Footprints") io.println("\nTesting Footprints")
let assert Ok(footprint_files) = let assert Ok(footprint_files) =
simplifile.get_files("/usr/share/kicad/footprints") simplifile.get_files("/usr/share/kicad/footprints")
// test_read_parse_decode( // let footprint_files = footprint_files |> list.drop(0) |> list.take(5000)
// footprint_files |> list.drop(0) |> list.split(10) |> pair.first, // let footprint_files = footprint_files |> list.sample(1000)
// token.footprint_file, // let footprint_files = ["test_files/test3.kicad_mod"]
// True, test_read_parse_decode(footprint_files, token.footprint_file, True)
// )
// test_read_parse_decode(
// ["test_files/test3.kicad_mod"],
// token.footprint_file,
// True,
// )
test_read_parse_decode(footprint_files, token.footprint_file, False)
io.println("\nTesting Symbol Libraries") io.println("\nTesting Symbol Libraries")
let assert Ok(symbol_libraries) = let assert Ok(symbol_libraries) =
simplifile.get_files("/usr/share/kicad/symbols") simplifile.get_files("/usr/share/kicad/symbols")
test_read_parse_decode(symbol_libraries, token.symbol_library, False) // let symbol_libraries = symbol_libraries |> list.drop(0) |> list.take(20)
// let symbol_libraries = symbol_libraries |> list.sample(1000)
// let symbol_libraries = ["test_files/test3.kicad_mod"]
test_read_parse_decode(symbol_libraries, token.symbol_library, True)
gleeunit.main() gleeunit.main()
} }
@ -50,20 +46,23 @@ fn print_stats(
title: String, title: String,
successes: Int, successes: Int,
total: Int, total: Int,
num_len: Int,
start_time: Timestamp, start_time: Timestamp,
end_time: Timestamp, end_time: Timestamp,
) -> Nil { ) -> Nil {
io.println( io.println(
title title
<> int.to_string(successes) <> { int.to_string(successes) |> string.pad_start(num_len, "0") }
<> "/" <> "/"
<> int.to_string(total) <> { int.to_string(total) |> string.pad_start(num_len, "0") }
<> " (" <> " ("
<> int.to_float(100 * successes) /. int.to_float(total) <> {
|> float.to_precision(1) int.to_float(100 * successes) /. int.to_float(total)
|> float.to_string |> float.to_precision(1)
|> string.pad_start(5, "0") |> float.to_string
|> string.append("%") |> string.pad_start(5, "0")
|> string.append("%")
}
<> ") in " <> ") in "
<> time_taken_string(start_time, end_time), <> time_taken_string(start_time, end_time),
) )
@ -75,7 +74,9 @@ fn test_read_parse_decode(
print_errors: Bool, print_errors: Bool,
) -> Nil { ) -> Nil {
let num_file_names = list.length(file_names) let num_file_names = list.length(file_names)
io.println("Total: " <> int.to_string(num_file_names)) let num_file_names_str = int.to_string(num_file_names)
let num_len = string.length(num_file_names_str)
io.println("Total: " <> num_file_names_str)
let time_before_read = timestamp.system_time() let time_before_read = timestamp.system_time()
let #(successfully_read, failed_to_read) = let #(successfully_read, failed_to_read) =
@ -92,6 +93,7 @@ fn test_read_parse_decode(
"Read: ", "Read: ",
num_successfully_read, num_successfully_read,
num_file_names, num_file_names,
num_len,
time_before_read, time_before_read,
time_after_read, time_after_read,
) )
@ -121,6 +123,7 @@ fn test_read_parse_decode(
"Parsed: ", "Parsed: ",
num_successfully_parsed, num_successfully_parsed,
num_successfully_read, num_successfully_read,
num_len,
time_before_parse, time_before_parse,
time_after_parse, time_after_parse,
) )
@ -150,6 +153,7 @@ fn test_read_parse_decode(
"Decoded: ", "Decoded: ",
num_successfully_decoded, num_successfully_decoded,
num_successfully_parsed, num_successfully_parsed,
num_len,
time_before_decode, time_before_decode,
time_after_decode, time_after_decode,
) )