diff --git a/extra/peg/javascript/javascript.factor b/extra/peg/javascript/javascript.factor new file mode 100644 index 0000000000..33fd6dd069 --- /dev/null +++ b/extra/peg/javascript/javascript.factor @@ -0,0 +1,247 @@ +! Copyright (C) 2007 Chris Double. +! See http://factorcode.org/license.txt for BSD license. +USING: kernel arrays strings math.parser sequences sequences.deep +peg peg.ebnf peg.parsers memoize namespaces math ; +IN: peg.javascript + +#! Grammar for JavaScript. Based on OMeta-JS example from: +#! http://jarrett.cs.ucla.edu/ometa-js/#JavaScript_Compiler + +USE: prettyprint + +TUPLE: ast-keyword value ; +TUPLE: ast-name value ; +TUPLE: ast-number value ; +TUPLE: ast-string value ; +TUPLE: ast-cond-expr condition then else ; +TUPLE: ast-set lhs rhs ; +TUPLE: ast-get value ; +TUPLE: ast-mset lhs rhs operator ; +TUPLE: ast-binop lhs rhs operator ; +TUPLE: ast-unop expr operator ; +TUPLE: ast-postop expr operator ; +TUPLE: ast-preop expr operator ; +TUPLE: ast-getp index expr ; +TUPLE: ast-send method expr args ; +TUPLE: ast-call expr args ; +TUPLE: ast-this ; +TUPLE: ast-new name args ; +TUPLE: ast-array values ; +TUPLE: ast-json bindings ; +TUPLE: ast-binding name value ; +TUPLE: ast-func fs body ; +TUPLE: ast-var name value ; +TUPLE: ast-begin statements ; +TUPLE: ast-if condition true false ; +TUPLE: ast-while condition statements ; +TUPLE: ast-do-while statements condition ; +TUPLE: ast-for i c u statements ; +TUPLE: ast-for-in v e statements ; +TUPLE: ast-switch expr statements ; +TUPLE: ast-break ; +TUPLE: ast-continue ; +TUPLE: ast-throw e ; +TUPLE: ast-try t e c f ; +TUPLE: ast-return e ; +TUPLE: ast-case c cs ; +TUPLE: ast-default cs ; +C: ast-name +C: ast-keyword +C: ast-number +C: ast-string +C: ast-cond-expr +C: ast-set +C: ast-get +C: ast-mset +C: ast-binop +C: ast-unop +C: ast-preop +C: ast-postop +C: ast-getp +C: ast-send +C: ast-call +C: ast-this +C: ast-new +C: ast-array +C: ast-json +C: ast-binding +C: ast-func +C: ast-var +C: ast-begin +C: ast-if +C: ast-while +C: ast-do-while +C: ast-for +C: ast-for-in +C: ast-switch +C: ast-break +C: ast-continue +C: ast-throw +C: ast-try +C: ast-return +C: ast-case +C: ast-default + +EBNF: javascript +Letter = [a-zA-Z] +Digit = [0-9] +Digits = (Digit)+ +SingleLineComment = "//" (!("\n") .)* "\n" => [[ drop ignore ]] +MultiLineComment = "/*" (!("*/") .)* "*/" => [[ drop ignore ]] +Space = " " | "\t" | "\n" | SingleLineComment | MultiLineComment +Spaces = (Space)* => [[ drop ignore ]] +NameFirst = Letter | "$" | "_" +NameRest = NameFirst | Digit +iName = NameFirst (NameRest)* => [[ first2 swap prefix >string ]] +Keyword = ("break" + | "case" + | "catch" + | "continue" + | "default" + | "delete" + | "do" + | "else" + | "finally" + | "for" + | "function" + | "if" + | "in" + | "instanceof" + | "new" + | "return" + | "switch" + | "this" + | "throw" + | "try" + | "typeof" + | "var" + | "void" + | "while" + | "with") => [[ ]] +Name = !(Keyword) (iName):n => [[ drop n ]] +Number = Digits:ws '.' Digits:fs => [[ drop ws "." fs 3array concat >string string>number ]] + | Digits => [[ >string string>number ]] + +EscapeChar = "\\n" => [[ drop 10 ]] + | "\\r" => [[ drop 13 ]] + | "\\t" => [[ drop 9 ]] +StringChars1 = (EscapeChar | !('"""') .)* => [[ >string ]] +StringChars2 = (EscapeChar | !('"') .)* => [[ >string ]] +StringChars3 = (EscapeChar | !("'") .)* => [[ >string ]] +Str = '"""' StringChars1:cs '"""' => [[ drop cs ]] + | '"' StringChars2:cs '"' => [[ drop cs ]] + | "'" StringChars3:cs "'" => [[ drop cs ]] +Special = "(" | ")" | "{" | "}" | "[" | "]" | "," | ";" + | "?" | ":" | "!==" | "~=" | "===" | "==" | "=" | ">=" + | ">" | "<=" | "<" | "++" | "+=" | "+" | "--" | "-=" + | "-" | "*=" | "*" | "/=" | "/" | "%=" | "%" | "&&=" + | "&&" | "||=" | "||" | "." | "!" +Tok = Spaces (Name | Keyword | Number | Str | Special ) +Toks = (Tok)* Spaces +SpacesNoNl = (!("\n") Space)* => [[ drop ignore ]] + +Expr = OrExpr:e "?" Expr:t ":" Expr:f => [[ drop e t f ]] + | OrExpr:e "=" Expr:rhs => [[ drop e rhs ]] + | OrExpr:e "+=" Expr:rhs => [[ drop e rhs "+" ]] + | OrExpr:e "-=" Expr:rhs => [[ drop e rhs "-" ]] + | OrExpr:e "*=" Expr:rhs => [[ drop e rhs "*" ]] + | OrExpr:e "/=" Expr:rhs => [[ drop e rhs "/" ]] + | OrExpr:e "%=" Expr:rhs => [[ drop e rhs "%" ]] + | OrExpr:e "&&=" Expr:rhs => [[ drop e rhs "&&" ]] + | OrExpr:e "||=" Expr:rhs => [[ drop e rhs "||" ]] + | OrExpr:e => [[ drop e ]] + +OrExpr = OrExpr:x "||" AndExpr:y => [[ drop x y "||" ]] + | AndExpr +AndExpr = AndExpr:x "&&" EqExpr:y => [[ drop x y "&&" ]] + | EqExpr +EqExpr = EqExpr:x "==" RelExpr:y => [[ drop x y "==" ]] + | EqExpr:x "!=" RelExpr:y => [[ drop x y "!=" ]] + | EqExpr:x "===" RelExpr:y => [[ drop x y "===" ]] + | EqExpr:x "!==" RelExpr:y => [[ drop x y "!==" ]] + | RelExpr +RelExpr = RelExpr:x ">" AddExpr:y => [[ drop x y ">" ]] + | RelExpr:x ">=" AddExpr:y => [[ drop x y ">=" ]] + | RelExpr:x "<" AddExpr:y => [[ drop x y "<" ]] + | RelExpr:x "<=" AddExpr:y => [[ drop x y "<=" ]] + | RelExpr:x "instanceof" AddExpr:y => [[ drop x y "instanceof" ]] + | AddExpr +AddExpr = AddExpr:x "+" MulExpr:y => [[ drop x y "+" ]] + | AddExpr:x "-" MulExpr:y => [[ drop x y "-" ]] + | MulExpr +MulExpr = MulExpr:x "*" MulExpr:y => [[ drop x y "*" ]] + | MulExpr:x "/" MulExpr:y => [[ drop x y "/" ]] + | MulExpr:x "%" MulExpr:y => [[ drop x y "%" ]] + | Unary +Unary = "-" Postfix:p => [[ drop p "-" ]] + | "+" Postfix:p => [[ drop p ]] + | "++" Postfix:p => [[ drop p "++" ]] + | "--" Postfix:p => [[ drop p "--" ]] + | "!" Postfix:p => [[ drop p "!" ]] + | Postfix +Postfix = PrimExpr:p SpacesNoNl "++" => [[ drop p "++" ]] + | PrimExpr:p SpacesNoNl "--" => [[ drop p "--" ]] + | PrimExpr +Args = Expr ("," Expr)* => [[ first2 swap prefix ]] +PrimExpr = PrimExpr:p "[" Expr:i "]" => [[ drop i p ]] + | PrimExpr:p "." Name:m "(" Args:as ")" => [[ drop m p as ]] + | PrimExpr:p "." Name:f => [[ drop f p ]] + | PrimExpr:p "(" Args:as ")" => [[ drop p as ]] + | PrimExprHd +PrimExprHd = "(" Expr:e ")" => [[ drop e ]] + | "this" => [[ drop ]] + | Name => [[ ]] + | Number => [[ ]] + | Str => [[ ]] + | "function" FuncRest:fr => [[ drop fr ]] + | "new" Name:n "(" Args:as ")" => [[ drop n as ]] + | "[" Args:es "]" => [[ drop es ]] + | Json +JsonBindings = JsonBinding ("," JsonBinding)* => [[ first2 swap prefix ]] +Json = "{" JsonBindings:bs "}" => [[ drop bs ]] +JsonBinding = JsonPropName:n ":" Expr:v => [[ drop n v ]] +JsonPropName = Name | Number | Str +Formal = Spaces Name +Formals = Formal ("," Formal)* => [[ first2 swap prefix ]] +FuncRest = "(" Formals:fs ")" "{" SrcElems:body "}" => [[ drop fs body ]] +Sc = SpacesNoNl ("\n" | "}")| ";" +Binding = Name:n "=" Expr:v => [[ drop n v ]] + | Name:n => [[ drop n "undefined" ]] +Block = "{" SrcElems:ss "}" => [[ drop ss ]] +Bindings = Binding ("," Binding)* => [[ first2 swap prefix ]] +For1 = "var" Binding => [[ second ]] + | Expr + | Spaces => [[ "undefined" ]] +For2 = Expr + | Spaces => [[ "true" ]] +For3 = Expr + | Spaces => [[ "undefined" ]] +ForIn1 = "var" Name:n => [[ drop n "undefined" ]] + | Expr +Switch1 = "case" Expr:c ":" SrcElems:cs => [[ drop c cs ]] + | "default" ":" SrcElems:cs => [[ drop cs ]] +SwitchBody = (Switch1)* +Finally = "finally" Block:b => [[ drop b ]] + | Spaces => [[ drop "undefined" ]] +Stmt = Block + | "var" Bindings:bs Sc => [[ drop bs ]] + | "if" "(" Expr:c ")" Stmt:t "else" Stmt:f => [[ drop c t f ]] + | "if" "(" Expr:c ")" Stmt:t => [[ drop c t "undefined" ]] + | "while" "(" Expr:c ")" Stmt:s => [[ drop c s ]] + | "do" Stmt:s "while" "(" Expr:c ")" Sc => [[ drop s c ]] + | "for" "(" For1:i ";" For2:c ";" For3:u ")" Stmt:s => [[ drop i c u s ]] + | "for" "(" ForIn1:v "in" Expr:e ")" Stmt:s => [[ drop v e s ]] + | "switch" "(" Expr:e ")" "{" SwitchBody:cs "}" => [[ drop e cs ]] + | "break" Sc => [[ drop ]] + | "continue" Sc => [[ drop ]] + | "throw" SpacesNoNl Expr:e Sc => [[ drop e ]] + | "try" Block:t "catch" "(" Name:e ")" Block:c Finally:f => [[ drop t e c f ]] + | "return" Expr:e Sc => [[ drop e ]] + | "return" Sc => [[ drop "undefined" ]] + | Expr:e Sc => [[ drop e ]] + | ";" => [[ drop "undefined" ]] +SrcElem = "function" Name:n FuncRest:f => [[ drop n f ]] + | Stmt +SrcElems = (SrcElem)* => [[ ]] +TopLevel = SrcElems Spaces +;EBNF \ No newline at end of file