package style import "github.com/yhirose/go-peg" import "fmt" import "os" import "io/ioutil" import "errors" const CSS1PEG = ` # CSS1 parser for a PEG parser generator. # and a user command parser # Doesn't support import statements. STYLESHEET ← (CDO / CDC)* (RULESET/DECLARATIONS/COMMENT/ATRULE)* (CDO / CDC)* RULESET ← SELECTORS "{" DECLARATIONS? "}" SELECTORS ← SELECTOR ("," SELECTOR)* SELECTOR ← ( "*" / NAME ID? CLASS? PSEUDO_CLASS? / ID CLASS? PSEUDO_CLASS? / CLASS PSEUDO_CLASS? / PSEUDO_CLASS )+ PSEUDO_ELEMENT* / PSEUDO_ELEMENT ATRULE ← ATID (STRING / URL) ";" / ATID "{" DECLARATIONS "}" NAME ← DECLARATIONS ← DECLARATION (';' DECLARATION)* ';'? DECLARATION ← NAME ":" EXPR PRIO? / COMMENT OPERATOR ← '/' / ',' # UNARY_OPERATOR ← '-' / '+' PRIO ← IMPORTANT EXPR ← TERM (OPERATOR TERM)* TERM ← STRING / PERCENTAGE / LENGTH / HEXCOLOR / URL / RGB / NUM / IDENT ~COMMENT ← "/*" (!("*/").)* "*/" ATID ← < "@" [a-zA-Z][-_a-zA-Z0-9]+ > IMPORTANT ← < "!" WS "important" > IDENT ← < [-_a-zA-Z][-_a-zA-Z0-9]* > PERCENTAGE ← < NUM > "%" NUM ← < [+-]*[0-9]+ / [0-9]* "." [0-9]+ > LENGTH ← NUM UNIT UNIT ← <"pt" / "mm" / "pt" / "in" / "px" / "em" / "ex" > PSEUDO_ELEMENT ← <":first-letter" / ":first-line" > PSEUDO_CLASS ← <":hover" / ":link" / ":mark" / ":active" / ":visited" > HEXCOLOR ← "#" < ([0-9a-fA-F])+ > ID ← "#" < IDENT > CLASS ← "." < IDENT > # Raw string macro. RAWSM(O,C) ← O < (!(C).)* > C # Escaped string macro. ESCSM(O,C) ← O < (!(C)STRCHAR)* > C # String escapes STRESC1 ← "\\" [nrtfv\'\\"\[\]\\] STRESC2 ← "\\" [0-3] [0-7] [0-7] STRESC3 ← "\\" [0-7] [0-7]* STRESC4 ← "\\x" [0-9a-fA-F] [0-9a-fA-F]? STRESC5 ← "\\u" [0-9a-fA-F]+ STRNOESC ← (!('\\\\').) STRCHAR ← STRESC1 / STRESC2 / STRESC3 / STRESC4 / STRESC5 / STRNOESC # Strings STRING ← ESCSM("\"", "\"") / ESCSM("'", "'") URL ← "url(" STRING ")" RGB ← < "rgb("[ \t]*[0-9]+[ \t]* "," [ \t]*[0-9]+[ \t]* "," [ \t]*[0-9]+[ \t]* ")" > ~WS ← [ \t\n\r]* CDO ← "" %whitespace ← [ \t\n\r]* ` type CSS1Parser struct { *peg.Parser } type CSS1Result struct { * peg.Ast } func parserCheck(err error) { if perr, ok := err.(*peg.Error); ok { for _, d := range perr.Details { fmt.Println(d) } os.Exit(1) } } /** Creates a CS1 PEG parser. */ func NewCSS1Parser() (*CSS1Parser, error) { result := &CSS1Parser{} var err error result.Parser, err = peg.NewParser(CSS1PEG) if err == nil { result.EnableAst() } return result, err } var defaultCSS1Parser * CSS1Parser func InitDefaultParser() error { var err error defaultCSS1Parser, err = NewCSS1Parser() return err } func wrapResult(wrapme peg.Any) *CSS1Result { result := &CSS1Result{}; ast, ok := wrapme.(*peg.Ast) if ok { result.Ast = ast return result } return nil } func (parser CSS1Parser) Parse(source string) (*CSS1Result, error) { ast, err := parser.ParseAndGetValue(source, nil) return wrapResult(ast), err } func (parser CSS1Parser) ParseFile(filename string) (*CSS1Result, error) { source, err := ioutil.ReadFile(filename) if err == nil { return parser.Parse(string(source)) } else { return nil, err } } func (css1 CSS1Result) InitializeTheme(theme * Theme) { } func parse(source string) (*CSS1Result, error) { if defaultCSS1Parser == nil { return nil, errors.New("Default parser not initialized!") } return defaultCSS1Parser.Parse(source) } func parseFile(filename string) (*CSS1Result, error) { if defaultCSS1Parser == nil { return nil, errors.New("Default parser not initialized!") } return defaultCSS1Parser.ParseFile(filename) }