Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
M
mincss
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
mincss
Commits
da8c2042
Commit
da8c2042
authored
Jul 15, 2014
by
Taddeüs Kroes
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Finished CSS2 grammar and updated main method
parent
c54cfb00
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
149 additions
and
104 deletions
+149
-104
Makefile
Makefile
+2
-1
lexer.mll
lexer.mll
+10
-8
main.ml
main.ml
+3
-4
parser.mly
parser.mly
+117
-72
stringify.ml
stringify.ml
+10
-10
types.ml
types.ml
+7
-9
No files found.
Makefile
View file @
da8c2042
...
@@ -37,4 +37,5 @@ util.cmx: stringify.cmx
...
@@ -37,4 +37,5 @@ util.cmx: stringify.cmx
main.cmx
:
parse.cmx util.cmx
main.cmx
:
parse.cmx util.cmx
clean
:
clean
:
rm
-f
*
.cmi
*
.cmx
*
.o lexer.ml parser.ml parser.mli
$(RESULT)
rm
-f
*
.cmi
*
.cmx
*
.o lexer.ml parser.ml parser.mli parser.conflicts
\
parser.automaton
$(RESULT)
lexer.mll
View file @
da8c2042
...
@@ -11,6 +11,8 @@
...
@@ -11,6 +11,8 @@
pos
with
pos_bol
=
lexbuf
.
lex_curr_pos
;
pos
with
pos_bol
=
lexbuf
.
lex_curr_pos
;
pos_lnum
=
pos
.
pos_lnum
+
1
pos_lnum
=
pos
.
pos_lnum
+
1
}
}
let
strip_quotes
s
=
String
.
sub
s
1
(
String
.
length
s
-
2
)
}
}
let
h
=
[
'
0
'
-
'
9
''
a'
-
'
f'
]
let
h
=
[
'
0
'
-
'
9
''
a'
-
'
f'
]
...
@@ -40,7 +42,7 @@ let comment = '/''*'[^'*']*'*'+([^'/''*'][^'*']*'*'+)'*''/'
...
@@ -40,7 +42,7 @@ let comment = '/''*'[^'*']*'*'+([^'/''*'][^'*']*'*'+)'*''/'
let ident = '-'? nmstart nmchar*
let ident = '-'? nmstart nmchar*
let name = nmchar+
let name = nmchar+
let num = ['0'-'9']+ | ['0'-'9']*'.'['0'-'9']+
let num = ['0'-'9']+ | ['0'-'9']*'.'['0'-'9']+
let url = (['!'
'#''$''%''&''*''-'
'~'] | nonascii | escape)*
let url = (['!'
'#' '$' '%' '&' '*'-
'~'] | nonascii | escape)*
rule token = parse
rule token = parse
| s { S }
| s { S }
...
@@ -53,8 +55,8 @@ rule token = parse
...
@@ -53,8 +55,8 @@ rule token = parse
| ['~''|']?'=' as op { RELATION op }
| ['~''|']?'=' as op { RELATION op }
| ['>''~'] as c { COMBINATOR (Char.escaped c) }
| ['>''~'] as c { COMBINATOR (Char.escaped c) }
| mystring as s { STRING
s
}
| mystring as s { STRING
(strip_quotes s)
}
| badstring
as s
{ raise (SyntaxError "
bad
string
") }
| badstring
{ raise (SyntaxError "
bad
string
") }
| ident as id { IDENT id }
| ident as id { IDENT id }
...
@@ -72,9 +74,9 @@ rule token = parse
...
@@ -72,9 +74,9 @@ rule token = parse
{ UNIT_VALUE (float_of_string n, u) }
{ UNIT_VALUE (float_of_string n, u) }
| num as n { NUMBER (float_of_string n) }
| num as n { NUMBER (float_of_string n) }
| "
url
(
" w (mystring as uri) w "
)
" { URI
uri
}
| "
url
(
" w (mystring as uri) w "
)
" { URI
(strip_quotes uri)
}
| "
url
(
" w (url as uri) w "
)
" { URI uri }
| "
url
(
" w (url as uri) w "
)
" { URI uri }
| baduri
as uri
{ raise (SyntaxError "
bad
uri
") }
| baduri
{ raise (SyntaxError "
bad
uri
") }
| (ident as fn) '(' { FUNCTION fn }
| (ident as fn) '(' { FUNCTION fn }
...
@@ -93,6 +95,6 @@ rule token = parse
...
@@ -93,6 +95,6 @@ rule token = parse
| '/' { SLASH }
| '/' { SLASH }
| '*' { STAR }
| '*' { STAR }
(*
| eof | '
\000
' { EOF }
| _ as c { raise (SyntaxError ("
illegal
string
character
:
" ^ Char.escaped c)) }
*)
| _ as c { raise (SyntaxError ("
unexpected
'
" ^ Char.escaped c ^ "
'
")) }
main.ml
View file @
da8c2042
...
@@ -48,13 +48,12 @@ let main () =
...
@@ -48,13 +48,12 @@ let main () =
loop
files
loop
files
in
in
Util
.
print_css
css
;
Util
.
print_css
css
;
0
exit
0
with
with
|
LocError
(
loc
,
msg
)
->
|
LocError
(
loc
,
msg
)
->
Util
.
prerr_loc_msg
args
loc
(
"Error: "
^
msg
);
Util
.
prerr_loc_msg
args
loc
(
"Error: "
^
msg
);
1
|
Failure
err
->
|
Failure
err
->
prerr_endline
(
"Error: "
^
err
);
prerr_endline
(
"Error: "
^
err
);
1
exit
1
let
_
=
exit
(
main
()
)
let
_
=
main
(
)
parser.mly
View file @
da8c2042
%
{
%
{
open
Lexing
(* CSS grammar based on http://www.w3.org/TR/CSS2/grammar.html *)
open
Types
open
Lexing
open
Types
let
filter_none
l
=
let
rec
filter
l
=
function
let
(
|>
)
a
b
=
b
a
|
[]
->
[]
|
None
::
tl
->
filter
l
tl
let
filter_none
l
=
|
Some
hd
::
tl
->
filter
(
hd
::
l
)
tl
let
rec
filter
l
=
function
in
|
[]
->
l
List
.
rev
(
filter
[]
l
)
|
None
::
tl
->
filter
l
tl
|
Some
hd
::
tl
->
filter
(
hd
::
l
)
tl
in
List
.
rev
(
filter
[]
l
)
type
term_t
=
Term
of
expr
|
Operator
of
string
let
rec
transform_value
f
=
function
|
Concat
terms
->
Concat
(
List
.
map
(
transform_value
f
)
terms
)
|
Function
(
name
,
arg
)
->
Function
(
name
,
transform_value
f
arg
)
|
Unary
(
op
,
term
)
->
Unary
(
op
,
transform_value
f
term
)
|
Nary
(
op
,
terms
)
->
Nary
(
op
,
List
.
map
(
transform_value
f
)
terms
)
|
value
->
f
value
let
concat_terms
terms
=
let
rec
transform_ops
=
function
|
[]
->
[]
|
Term
left
::
Operator
op
::
Term
right
::
tl
->
Nary
(
op
,
[
left
;
right
])
::
transform_ops
tl
|
Term
hd
::
tl
->
hd
::
transform_ops
tl
|
Operator
op
::
_
->
raise
(
SyntaxError
(
"unexpected operator
\"
"
^
op
^
"
\"
"
))
in
let
rec
flatten_nary
=
function
|
[]
->
[]
|
Nary
(
op
,
Nary
(
op2
,
left
)
::
right
)
::
tl
when
op2
=
op
->
Nary
(
op
,
flatten_nary
left
@
flatten_nary
right
)
::
flatten_nary
tl
|
hd
::
tl
->
hd
::
flatten_nary
tl
in
let
comma_to_concat
=
List
.
map
(
transform_value
(
function
|
Nary
(
","
,
terms
)
->
Concat
terms
|
value
->
value
))
in
match
terms
|>
transform_ops
|>
flatten_nary
|>
comma_to_concat
with
|
[
hd
]
->
hd
|
l
->
Concat
l
%
}
%
}
(* Tokens *)
(* Tokens *)
...
@@ -18,7 +54,7 @@ let filter_none l =
...
@@ -18,7 +54,7 @@ let filter_none l =
%
token
<
float
*
string
>
UNIT_VALUE
%
token
<
float
*
string
>
UNIT_VALUE
%
token
<
string
>
COMBINATOR
RELATION
STRING
IDENT
HASH
URI
FUNCTION
%
token
<
string
>
COMBINATOR
RELATION
STRING
IDENT
HASH
URI
FUNCTION
%
token
RPAREN
LBRACE
RBRACE
LBRACK
RBRACK
SEMICOL
COLON
COMMA
DOT
PLUS
MINUS
%
token
RPAREN
LBRACE
RBRACE
LBRACK
RBRACK
SEMICOL
COLON
COMMA
DOT
PLUS
MINUS
%
token
SLASH
STAR
%
token
SLASH
STAR
EOF
(* Start symbol *)
(* Start symbol *)
%
type
<
Types
.
stylesheet
>
stylesheet
%
type
<
Types
.
stylesheet
>
stylesheet
...
@@ -26,124 +62,133 @@ let filter_none l =
...
@@ -26,124 +62,133 @@ let filter_none l =
%%
%%
%
inline
mylist
(
sep
,
x
)
:
(* list with arbitrary whitespace between elements and separators *)
|
l
=
separated_list
(
sep
,
delimited
(
S
*,
x
,
S
*
))
%
inline
wslist
(
sep
,
x
)
:
S
?
l
=
separated_list
(
sep
,
terminated
(
x
,
S
?
))
{
l
}
{
l
}
cd
:
CDO
S
*
|
CDC
S
*
{}
cd
:
CDO
S
?
|
CDC
S
?
{}
%
inline
statement
:
r
=
ruleset
|
r
=
media
|
r
=
page
{
r
}
stylesheet
:
stylesheet
:
|
charset
=
charset
?
S
*
cd
*
|
charset
=
charset
?
S
?
cd
*
imports
=
terminated
(
import
,
cd
*
)
*
imports
=
terminated
(
import
,
cd
*
)
*
statements
=
terminated
(
statement
,
cd
*
)
*
statements
=
terminated
(
statement
,
cd
*
)
*
EOF
{
let
charset
=
match
charset
with
None
->
[]
|
Some
c
->
[
c
]
in
{
let
charset
=
match
charset
with
None
->
[]
|
Some
c
->
[
c
]
in
charset
@
imports
@
statements
}
charset
@
imports
@
statements
}
%
inline
statement
:
|
s
=
ruleset
|
s
=
media
|
s
=
page
{
s
}
charset
:
charset
:
|
CHARSET_SYM
set
=
STRING
SEMICOL
|
CHARSET_SYM
name
=
STRING
SEMICOL
{
Charset
set
}
{
Charset
name
}
%
inline
string_or_uri
:
s
=
STRING
|
s
=
URI
{
s
}
%
inline
string_or_uri
:
|
s
=
STRING
|
s
=
URI
{
s
}
import
:
import
:
|
IMPORT_SYM
S
*
tgt
=
string_or_uri
media
=
mylist
(
COMMA
,
IDENT
)
SEMICOL
S
*
|
IMPORT_SYM
S
?
tgt
=
string_or_uri
media
=
wslist
(
COMMA
,
IDENT
)
SEMICOL
S
?
{
Import
(
tgt
,
media
)
}
{
Import
(
tgt
,
media
)
}
media
:
media
:
|
MEDIA_SYM
S
*
queries
=
mylist
(
COMMA
,
IDENT
)
LBRACE
S
*
rulesets
=
ruleset
*
RBRACE
S
*
|
MEDIA_SYM
queries
=
wslist
(
COMMA
,
IDENT
)
LBRACE
S
?
rulesets
=
ruleset
*
RBRACE
S
?
{
Media
(
queries
,
rulesets
)
}
{
Media
(
queries
,
rulesets
)
}
page
:
page
:
|
PAGE_SYM
S
*
pseudo
=
pseudo_page
?
decls
=
decls_block
|
PAGE_SYM
S
?
pseudo
=
pseudo_page
?
decls
=
decls_block
{
Page
(
pseudo
,
decls
)
}
{
Page
(
pseudo
,
decls
)
}
pseudo_page
:
pseudo_page
:
|
COLON
pseudo
=
IDENT
S
*
|
COLON
pseudo
=
IDENT
S
?
{
pseudo
}
{
pseudo
}
decls_block
:
%
inline
decls_block
:
|
LBRACE
S
*
decls
=
mylist
(
SEMICOL
,
declaration
?
)
RBRACE
S
*
|
LBRACE
S
?
hd
=
declaration
?
tl
=
preceded
(
pair
(
SEMICOL
,
S
?
)
,
declaration
?
)
*
RBRACE
S
?
{
filter_none
decls
}
{
filter_none
(
hd
::
tl
)
}
ruleset
:
ruleset
:
|
selectors_hd
=
selector
|
selectors_hd
=
selector
selectors_tl
=
separated_list
(
COMMA
,
preceded
(
S
*,
selector
))
selectors_tl
=
preceded
(
pair
(
COMMA
,
S
?
)
,
selector
)
*
decls
=
decls_block
decls
=
decls_block
{
Ruleset
(
selectors_hd
::
selectors_tl
,
decls
)
}
{
Ruleset
(
selectors_hd
::
selectors_tl
,
decls
)
}
%
inline
combinator
:
|
S
*
PLUS
S
*
{
[
"+"
]
}
|
S
*
c
=
COMBINATOR
S
*
{
[
c
]
}
|
S
+
{
[]
}
selector
:
selector
:
|
hd
=
simple_selector
comb
=
combinator
tl
=
selector
|
hd
=
simple_selector
S
?
{
hd
::
comb
@
tl
}
{
[
hd
]
}
|
simple
=
simple_selector
|
hd
=
simple_selector
S
tl
=
selector
{
[
simple
]
}
{
hd
::
tl
}
|
hd
=
simple_selector
S
?
c
=
combinator
tl
=
selector
{
hd
::
c
::
tl
}
%
inline
combinator
:
|
PLUS
S
?
{
"+"
}
|
c
=
COMBINATOR
S
?
{
c
}
simple_selector
:
simple_selector
:
|
elem
=
element_name
addons
=
element_addon
*
|
elem
=
element_name
addons
=
element_addon
*
{
elem
^
String
.
concat
""
addons
}
{
elem
^
String
.
concat
""
addons
}
|
addons
=
element_addon
+
|
addons
=
element_addon
+
{
String
.
concat
""
addons
}
{
String
.
concat
""
addons
}
%
inline
element_addon
:
element_addon
:
|
a
=
HASH
|
a
=
cls
|
a
=
attrib
|
a
=
pseudo
|
a
=
HASH
|
a
=
cls
|
a
=
attrib
|
a
=
pseudo
{
a
}
{
a
}
cls
:
|
DOT
name
=
IDENT
{
"."
^
name
}
element_name
:
element_name
:
|
tag
=
IDENT
{
tag
}
|
tag
=
IDENT
{
tag
}
|
STAR
{
"*"
}
|
STAR
{
"*"
}
%
inline
rel_value
:
cls
:
|
S
*
id
=
IDENT
S
*
{
id
}
|
DOT
name
=
IDENT
|
S
*
s
=
STRING
S
*
{
s
}
{
"."
^
name
}
attrib
:
attrib
:
|
LBRACK
S
*
left
=
IDENT
S
*
right
=
pair
(
RELATION
,
rel_value
)
?
RBRACK
|
LBRACK
S
?
left
=
IDENT
S
?
right
=
pair
(
RELATION
,
rel_value
)
?
RBRACK
{
left
^
(
match
right
with
None
->
""
|
Some
(
rel
,
term
)
->
rel
^
term
)
}
{
left
^
(
match
right
with
None
->
""
|
Some
(
rel
,
term
)
->
rel
^
term
)
}
%
inline
rel_value
:
|
S
?
id
=
IDENT
S
?
{
id
}
|
S
?
s
=
STRING
S
?
{
s
}
pseudo
:
pseudo
:
|
COLON
id
=
IDENT
|
COLON
id
=
IDENT
{
":"
^
id
}
{
":"
^
id
}
|
COLON
f
=
FUNCTION
S
*
arg
=
terminated
(
IDENT
,
S
*
)
?
RPAREN
|
COLON
f
=
FUNCTION
S
?
arg
=
terminated
(
IDENT
,
S
?
)
?
RPAREN
{
let
arg
=
match
arg
with
None
->
""
|
Some
id
->
id
in
{
let
arg
=
match
arg
with
None
->
""
|
Some
id
->
id
in
":"
^
f
^
"("
^
arg
^
")"
}
":"
^
f
^
"("
^
arg
^
")"
}
declaration
:
declaration
:
|
name
=
IDENT
S
*
COLON
S
*
value
=
expr
IMPORTANT_SYM
S
*
|
name
=
IDENT
S
?
COLON
S
?
value
=
expr
important
=
boption
(
pair
(
IMPORTANT_SYM
,
S
?
))
{
(
name
,
Prio
value
)
}
{
(
name
,
value
,
important
)
}
|
name
=
IDENT
S
*
COLON
S
*
value
=
expr
{
(
name
,
value
)
}
%
inline
unary_operator
:
|
MINUS
{
"-"
}
|
PLUS
{
"+"
}
expr
:
expr
:
|
left
=
expr
right
=
expr
|
l
=
exprl
{
concat_terms
l
}
{
Concat
[
left
;
right
]
}
%
inline
exprl
:
|
left
=
expr
SLASH
S
*
right
=
expr
|
hd
=
term
tl
=
opterm
*
{
Term
hd
::
List
.
concat
tl
}
{
Binop
(
left
,
"/"
,
right
)
}
%
inline
opterm
:
|
op
=
unary_operator
n
=
NUMBER
S
*
|
t
=
term
{
[
Term
t
]
}
{
Unop
(
op
,
Number
n
)
}
|
op
=
operator
t
=
term
{
[
Operator
op
;
Term
t
]
}
|
op
=
unary_operator
v
=
UNIT_VALUE
S
*
%
inline
operator
:
{
let
(
n
,
u
)
=
v
in
Unop
(
op
,
Unit
(
n
,
u
))
}
|
SLASH
S
?
{
"/"
}
|
n
=
NUMBER
S
*
|
COMMA
S
?
{
","
}
{
Number
n
}
|
v
=
UNIT_VALUE
S
*
term
:
{
let
(
n
,
u
)
=
v
in
Unit
(
n
,
u
)
}
|
op
=
unary_operator
n
=
NUMBER
S
?
|
str
=
STRING
S
*
{
Unary
(
op
,
Number
(
n
,
None
))
}
|
op
=
unary_operator
v
=
UNIT_VALUE
S
?
{
let
(
n
,
u
)
=
v
in
Unary
(
op
,
Number
(
n
,
Some
u
))
}
|
n
=
NUMBER
S
?
{
Number
(
n
,
None
)
}
|
v
=
UNIT_VALUE
S
?
{
let
(
n
,
u
)
=
v
in
Number
(
n
,
Some
u
)
}
|
str
=
STRING
S
?
{
Strlit
str
}
{
Strlit
str
}
|
id
=
IDENT
S
*
|
id
=
IDENT
S
?
{
Ident
id
}
{
Ident
id
}
|
uri
=
URI
S
*
|
uri
=
URI
S
?
{
Uri
uri
}
{
Uri
uri
}
|
fn
=
FUNCTION
S
*
args
=
separated_list
(
COMMA
,
terminated
(
expr
,
S
*
))
RPAREN
S
*
|
fn
=
FUNCTION
arg
=
expr
RPAREN
S
?
{
Function
(
fn
,
arg
s
)
}
{
Function
(
fn
,
arg
)
}
|
hex
=
HASH
S
*
|
hex
=
HASH
S
?
{
if
Str
.
string_match
(
Str
.
regexp
"
\\
d{3}
\\
d{3}?"
)
hex
0
{
if
Str
.
string_match
(
Str
.
regexp
"
\\
d{3}
\\
d{3}?"
)
hex
0
then
Hexcolor
hex
then
Hexcolor
hex
else
raise
(
SyntaxError
(
"invalid color #"
^
hex
))
}
else
raise
(
SyntaxError
(
"invalid color #"
^
hex
))
}
%
inline
unary_operator
:
|
MINUS
{
"-"
}
|
PLUS
{
"+"
}
stringify.ml
View file @
da8c2042
...
@@ -14,22 +14,22 @@ let string_of_num n =
...
@@ -14,22 +14,22 @@ let string_of_num n =
then
string_of_int
(
int_of_float
n
)
then
string_of_int
(
int_of_float
n
)
else
string_of_float
n
else
string_of_float
n
let
rec
string_of_
value
=
function
let
rec
string_of_
expr
=
function
|
Ident
id
->
id
|
Ident
id
->
id
|
Strlit
str
->
"
\"
"
^
str
^
"
\"
"
|
Strlit
str
->
"
\"
"
^
str
^
"
\"
"
|
Uri
uri
when
String
.
contains
uri
'
)
'
->
"url(
\"
"
^
uri
^
"
\"
)"
|
Uri
uri
when
String
.
contains
uri
'
)
'
->
"url(
\"
"
^
uri
^
"
\"
)"
|
Uri
uri
->
"url("
^
uri
^
")"
|
Uri
uri
->
"url("
^
uri
^
")"
|
Concat
values
->
cat
" "
string_of_
value
values
|
Concat
values
->
cat
" "
string_of_
expr
values
|
Number
n
->
string_of_num
n
|
Number
(
n
,
None
)
->
string_of_num
n
|
Unit
(
n
,
u
)
->
string_of_num
n
^
u
|
Number
(
n
,
Some
u
)
->
string_of_num
n
^
u
|
Function
(
name
,
arg
s
)
->
name
^
"("
^
cat
","
string_of_value
args
^
")"
|
Function
(
name
,
arg
)
->
name
^
"("
^
string_of_expr
arg
^
")"
|
Hexcolor
hex
->
"#"
^
hex
|
Hexcolor
hex
->
"#"
^
hex
|
Unop
(
op
,
opnd
)
->
op
^
string_of_value
opnd
|
Unary
(
op
,
opnd
)
->
op
^
string_of_expr
opnd
|
Binop
(
left
,
op
,
right
)
->
string_of_value
left
^
op
^
string_of_value
right
|
Nary
(
op
,
opnds
)
->
cat
op
string_of_expr
opnds
|
Prio
value
->
string_of_value
value
^
" !important"
let
string_of_declaration
(
name
,
value
)
=
let
string_of_declaration
(
name
,
value
,
important
)
=
name
^
": "
^
string_of_value
value
^
";"
let
imp
=
if
important
then
" !important"
else
""
in
name
^
": "
^
string_of_expr
value
^
imp
^
";"
let
block
body
=
" {
\n
"
^
indent
body
^
"
\n
}"
let
block
body
=
" {
\n
"
^
indent
body
^
"
\n
}"
...
...
types.ml
View file @
da8c2042
type
value
=
type
expr
=
|
Ident
of
string
|
Ident
of
string
|
Strlit
of
string
|
Strlit
of
string
|
Uri
of
string
|
Uri
of
string
|
Concat
of
value
list
|
Concat
of
expr
list
|
Number
of
float
|
Number
of
float
*
string
option
|
Unit
of
float
*
string
|
Function
of
string
*
expr
|
Function
of
string
*
value
list
|
Hexcolor
of
string
|
Hexcolor
of
string
|
Unop
of
string
*
value
|
Unary
of
string
*
expr
|
Binop
of
value
*
string
*
value
|
Nary
of
string
*
expr
list
|
Prio
of
value
type
declaration
=
string
*
value
type
declaration
=
string
*
expr
*
bool
type
selector
=
string
list
type
selector
=
string
list
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment