{- |
Description: Example implementation of a simplified version of the Java grammar.
License: GNU LGPLv3
Maintainer: paul.bittner@uni-ulm.de

Example implementation of a context free grammar.
This example represents a simplified subset of the Java programming language.
It contains the 'Grammar' implementation as well as functions to construct an 'AST' in this sub-language.
-}
module SimpleJava where

import Tree
import Control.Monad.State ( State )
import UUID ( UUID )
import AST
import Grammar
import ASTPrettyPrinter
import Data.List ( intersperse )

-- | Simplified subset of the Java grammar.
data SimpleJavaGrammar = 
    SJava_MethodDef -- ^ Rule for method definitions.
  | SJava_ParametersDef -- ^ Rule for a parameters list (e.g., in a method declaration).
  | SJava_Args -- ^ Rule for arguments passed to a method call (e.g., @(1 + 2, "arg2", null)@).
  | SJava_Statements -- ^ Rule for a sequential list of statements (e.g., inside a method).
  | SJava_ExprStatement -- ^ Rule for a statement that is a single expression (e.g., @x += 3@ that also returns the new value of @x@ is an expression statement).
  | SJava_Assignment -- ^ Rule for assignments of variables (e.g., @x = 3@).
  | SJava_Return -- ^ Rule for @return@ statements.
  | SJava_Condition -- ^ Rule for conditions (@if@).
  | SJava_FuncCall -- ^ Rule for function calls.
  | SJava_Expression -- ^ Rule for expressions (e.g., @1 + 1@).
  | SJava_UnaryOp -- ^ Rule for unary operations (e.g., @!@ or @-@).
  | SJava_BinaryOp -- ^ Rule for binary operations (e.g., @+@ or @*@).
  | SJava_VarDecl -- ^ Rule for variable declarations (e.g., @int x;@).
  | SJava_VarRef -- ^ Rule for variable references.
  | SJava_Literal -- ^ Rule for literals.
  | SJava_Type -- ^ Rule for types (e.g., @int@ in @int x;@).
  | SJava_File  -- ^ Rule that represents an entire file. Usually the root of the AST.
  deriving (SimpleJavaGrammar -> SimpleJavaGrammar -> Bool
(SimpleJavaGrammar -> SimpleJavaGrammar -> Bool)
-> (SimpleJavaGrammar -> SimpleJavaGrammar -> Bool)
-> Eq SimpleJavaGrammar
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: SimpleJavaGrammar -> SimpleJavaGrammar -> Bool
$c/= :: SimpleJavaGrammar -> SimpleJavaGrammar -> Bool
== :: SimpleJavaGrammar -> SimpleJavaGrammar -> Bool
$c== :: SimpleJavaGrammar -> SimpleJavaGrammar -> Bool
Eq, Int -> SimpleJavaGrammar -> ShowS
[SimpleJavaGrammar] -> ShowS
SimpleJavaGrammar -> String
(Int -> SimpleJavaGrammar -> ShowS)
-> (SimpleJavaGrammar -> String)
-> ([SimpleJavaGrammar] -> ShowS)
-> Show SimpleJavaGrammar
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [SimpleJavaGrammar] -> ShowS
$cshowList :: [SimpleJavaGrammar] -> ShowS
show :: SimpleJavaGrammar -> String
$cshow :: SimpleJavaGrammar -> String
showsPrec :: Int -> SimpleJavaGrammar -> ShowS
$cshowsPrec :: Int -> SimpleJavaGrammar -> ShowS
Show)

-- | An 'AST' build from the SimpleJavaGrammar.
type SJavaAST a = AST SimpleJavaGrammar a
-- | An 'AST' build from the SimpleJavaGrammar containing Strings as values.
type SSJavaAST = SJavaAST String
-- | A 'SSJavaAST' whose nodes are not yet assigned their 'UUID's (they are still states waiting for evaluation).
type SJavaState = Tree (State UUID (Node SimpleJavaGrammar String))

{- Grammar rules to build the 'AST' -}

-- | Construct a method definition with given (1) return type, (2) name, (3) parameters (pairs of type and name), and (4) the given content (list of statements).
sjava_methoddef :: String -> String -> [(String, String)] -> [SJavaState] -> SJavaState
sjava_methoddef :: String
-> String -> [(String, String)] -> [SJavaState] -> SJavaState
sjava_methoddef rettype :: String
rettype name :: String
name params :: [(String, String)]
params content :: [SJavaState]
content =
    (State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
name SimpleJavaGrammar
SJava_MethodDef) [
        String -> SJavaState
sjava_type String
rettype,
        [(String, String)] -> SJavaState
sjava_parametersdef [(String, String)]
params,
        [SJavaState] -> SJavaState
sjava_statements [SJavaState]
content
    ])

-- | Construct a definition of parameters subtree from the given pairs of type and name.
sjava_parametersdef :: [(String, String)] -> SJavaState
sjava_parametersdef :: [(String, String)] -> SJavaState
sjava_parametersdef params :: [(String, String)]
params = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
forall a. Monoid a => a
mempty SimpleJavaGrammar
SJava_ParametersDef) ([SJavaState] -> SJavaState) -> [SJavaState] -> SJavaState
forall a b. (a -> b) -> a -> b
$ SJavaState -> SJavaState
sjava_expr(SJavaState -> SJavaState)
-> ((String, String) -> SJavaState)
-> (String, String)
-> SJavaState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.((String -> String -> SJavaState) -> (String, String) -> SJavaState
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry String -> String -> SJavaState
sjava_vardecl) ((String, String) -> SJavaState)
-> [(String, String)] -> [SJavaState]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [(String, String)]
params

-- | Construct an arguments subtree from the given list of subtrees (e.g., @(1 + 2, "arg2", null)@).
sjava_args :: [SJavaState] -> SJavaState
sjava_args :: [SJavaState] -> SJavaState
sjava_args params :: [SJavaState]
params = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
forall a. Monoid a => a
mempty SimpleJavaGrammar
SJava_Args) ([SJavaState] -> SJavaState) -> [SJavaState] -> SJavaState
forall a b. (a -> b) -> a -> b
$ SJavaState -> SJavaState
sjava_expr(SJavaState -> SJavaState)
-> (SJavaState -> SJavaState) -> SJavaState -> SJavaState
forall b c a. (b -> c) -> (a -> b) -> a -> c
.SJavaState -> SJavaState
sjava_expr (SJavaState -> SJavaState) -> [SJavaState] -> [SJavaState]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [SJavaState]
params

-- | Construct a statements block from a list of statements.
sjava_statements :: [SJavaState] -> SJavaState
sjava_statements :: [SJavaState] -> SJavaState
sjava_statements statements :: [SJavaState]
statements = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
forall a. Monoid a => a
mempty SimpleJavaGrammar
SJava_Statements) [SJavaState]
statements

-- | Wrap the given subtree in an expression statement. The given tree should be an expression.
-- Pseudocode example: @sjava_exprstatement 'x = 3  ==  'x + 3;'@.
sjava_exprstatement :: SJavaState -> SJavaState
sjava_exprstatement :: SJavaState -> SJavaState
sjava_exprstatement expression :: SJavaState
expression = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
forall a. Monoid a => a
mempty SimpleJavaGrammar
SJava_ExprStatement) [SJavaState -> SJavaState
sjava_expr SJavaState
expression]

-- | Constructs an assignment where parameter
--
-- (1) represents the left side of the assignment (e.g., a variable that should be assigned a value),
-- (2) is the operator's name to use (e.g., @"="@), and
-- (3) is the expression to assign (e.g. "1 + 2").
sjava_assignment :: SJavaState -> String -> SJavaState -> SJavaState
sjava_assignment :: SJavaState -> String -> SJavaState -> SJavaState
sjava_assignment lhs :: SJavaState
lhs op :: String
op expr :: SJavaState
expr = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
op SimpleJavaGrammar
SJava_Assignment) [SJavaState
lhs, SJavaState -> SJavaState
sjava_expr SJavaState
expr]

-- | Constructs a return statement that returns the given expression.
sjava_return :: SJavaState -> SJavaState
sjava_return :: SJavaState -> SJavaState
sjava_return expr :: SJavaState
expr = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
forall a. Monoid a => a
mempty SimpleJavaGrammar
SJava_Return) [SJavaState -> SJavaState
sjava_expr SJavaState
expr]

-- | Constructs an if-block (without else case) with the given condition (first argument) and sequence of statements to run when the condition is met.
sjava_condition :: SJavaState -> [SJavaState] -> SJavaState
sjava_condition :: SJavaState -> [SJavaState] -> SJavaState
sjava_condition cond :: SJavaState
cond block :: [SJavaState]
block =
    State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
forall a. Monoid a => a
mempty SimpleJavaGrammar
SJava_Condition) [
        SJavaState -> SJavaState
sjava_expr SJavaState
cond,
        [SJavaState] -> SJavaState
sjava_statements [SJavaState]
block
    ]

-- | Constructs a call to a function the given name and a list of arguments to pass.
sjava_funccall :: String -> [SJavaState] -> SJavaState
sjava_funccall :: String -> [SJavaState] -> SJavaState
sjava_funccall name :: String
name params :: [SJavaState]
params =
    State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
name SimpleJavaGrammar
SJava_FuncCall) [
        [SJavaState] -> SJavaState
sjava_args [SJavaState]
params
    ]

-- | Wraps an tree in an expression.
-- For example, a literal is an expression.
-- Thus a literal can be used anywhere an expression required but should be wrapped into an expression first.
sjava_expr :: SJavaState -> SJavaState
sjava_expr :: SJavaState -> SJavaState
sjava_expr inner :: SJavaState
inner = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node "Expression" SimpleJavaGrammar
SJava_Expression) [SJavaState
inner]

-- | Constructs a unary operation (e.g. @-3@) from a given name (@-@) that is applied to the given expression (@3@).
sjava_unaryop :: String -> SJavaState -> SJavaState
sjava_unaryop :: String -> SJavaState -> SJavaState
sjava_unaryop op :: String
op expr :: SJavaState
expr = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
op SimpleJavaGrammar
SJava_UnaryOp) [SJavaState -> SJavaState
sjava_expr SJavaState
expr]

-- | Constructs a binary operator from a given name and two expressions.
sjava_binaryop :: SJavaState -> String -> SJavaState -> SJavaState
sjava_binaryop :: SJavaState -> String -> SJavaState -> SJavaState
sjava_binaryop lhs :: SJavaState
lhs op :: String
op rhs :: SJavaState
rhs =
    State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
op SimpleJavaGrammar
SJava_BinaryOp) [
        SJavaState -> SJavaState
sjava_expr SJavaState
lhs,
        SJavaState -> SJavaState
sjava_expr SJavaState
rhs
    ]

-- | Constructs a variable declaration (e.g., @int x;@) from a type (e.g., @int@) and a name (e.g., @x@).
sjava_vardecl :: String -> String -> SJavaState
sjava_vardecl :: String -> String -> SJavaState
sjava_vardecl vartype :: String
vartype varname :: String
varname =
    (State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
forall a. Monoid a => a
mempty SimpleJavaGrammar
SJava_VarDecl)) [
        String -> SJavaState
sjava_type String
vartype,
        String -> SJavaState
sjava_literal String
varname
    ]

-- | Constructs a reference to a variable with the given name. The returned tree is a leaf.
sjava_varref :: String -> SJavaState
sjava_varref :: String -> SJavaState
sjava_varref name :: String
name = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
name SimpleJavaGrammar
SJava_VarRef) []

-- | Constructs a literal with the given name. The returned tree is a leaf.
sjava_literal :: String -> SJavaState
sjava_literal :: String -> SJavaState
sjava_literal val :: String
val = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
val SimpleJavaGrammar
SJava_Literal) []

-- | Constructs a type with the given name. The returned tree is a leaf.
sjava_type :: String -> SJavaState
sjava_type :: String -> SJavaState
sjava_type val :: String
val = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
val SimpleJavaGrammar
SJava_Type) []

-- | Constructs a file with the given name and content.
sjava_file :: String -> [SJavaState] -> SJavaState
sjava_file :: String -> [SJavaState] -> SJavaState
sjava_file name :: String
name content :: [SJavaState]
content = State Int (Node SimpleJavaGrammar String)
-> [SJavaState] -> SJavaState
forall a. a -> [Tree a] -> Tree a
Tree (String
-> SimpleJavaGrammar -> State Int (Node SimpleJavaGrammar String)
forall g a. Grammar g => a -> g -> State Int (Node g a)
node String
name SimpleJavaGrammar
SJava_File) [SJavaState]
content

-- | Define optionality for all node types in our Java grammar
instance Grammar SimpleJavaGrammar where
    nodetypeof :: SimpleJavaGrammar -> NodeType
nodetypeof SJava_MethodDef = NodeType
Optional
    nodetypeof SJava_Return = NodeType
Optional --leaf
    nodetypeof SJava_File = NodeType
Optional
    nodetypeof SJava_ExprStatement = NodeType
Optional
    nodetypeof SJava_VarDecl = NodeType
Mandatory
    nodetypeof SJava_Condition = NodeType
Wrapper
    nodetypeof SJava_UnaryOp = NodeType
Wrapper
    nodetypeof SJava_Type = NodeType
Optional -- leaf
    nodetypeof SJava_Expression = NodeType
Mandatory
    nodetypeof SJava_ParametersDef = NodeType
Mandatory
    nodetypeof SJava_Args = NodeType
Mandatory
    nodetypeof SJava_Statements = NodeType
Mandatory
    nodetypeof SJava_BinaryOp = NodeType
Optional
    nodetypeof SJava_FuncCall = NodeType
Optional
    nodetypeof SJava_VarRef = NodeType
Optional -- leaf
    nodetypeof SJava_Literal = NodeType
Optional -- leaf
    nodetypeof SJava_Assignment = NodeType
Mandatory

instance ASTPrettyPrinter SimpleJavaGrammar where
    -- | Prints 'AST' as source code
    prettyPrint :: b
-> (Node SimpleJavaGrammar a -> Int -> b)
-> (Node SimpleJavaGrammar a -> String -> b)
-> (Node SimpleJavaGrammar a -> b)
-> AST SimpleJavaGrammar a
-> b
prettyPrint i :: b
i indentGenerator :: Node SimpleJavaGrammar a -> Int -> b
indentGenerator prtStrWithContext :: Node SimpleJavaGrammar a -> String -> b
prtStrWithContext prtNode :: Node SimpleJavaGrammar a -> b
prtNode (Tree n :: Node SimpleJavaGrammar a
n children :: [AST SimpleJavaGrammar a]
children) =
        [b] -> b
forall a. Monoid a => [a] -> a
mconcat ([b] -> b) -> [b] -> b
forall a b. (a -> b) -> a -> b
$
        let indentLen :: Int
indentLen = 2
            indent :: b
indent = b -> b -> b
forall a. Monoid a => a -> a -> a
mappend b
i (b -> b) -> b -> b
forall a b. (a -> b) -> a -> b
$ Node SimpleJavaGrammar a -> Int -> b
indentGenerator Node SimpleJavaGrammar a
n Int
indentLen
            prtStr :: String -> b
prtStr = Node SimpleJavaGrammar a -> String -> b
prtStrWithContext Node SimpleJavaGrammar a
n
            me :: b
me = Node SimpleJavaGrammar a -> b
prtNode Node SimpleJavaGrammar a
n
            showList :: String -> [AST SimpleJavaGrammar a] -> b
showList sep :: String
sep l :: [AST SimpleJavaGrammar a]
l = b -> [AST SimpleJavaGrammar a] -> b
showList' (String -> b
prtStr String
sep) [AST SimpleJavaGrammar a]
l
            showList' :: b -> [AST SimpleJavaGrammar a] -> b
showList' sep :: b
sep l :: [AST SimpleJavaGrammar a]
l = [b] -> b
forall a. Monoid a => [a] -> a
mconcat ([b] -> b) -> [b] -> b
forall a b. (a -> b) -> a -> b
$ b -> [b] -> [b]
forall a. a -> [a] -> [a]
intersperse b
sep ([b] -> [b]) -> [b] -> [b]
forall a b. (a -> b) -> a -> b
$ (b
-> (Node SimpleJavaGrammar a -> Int -> b)
-> (Node SimpleJavaGrammar a -> String -> b)
-> (Node SimpleJavaGrammar a -> b)
-> AST SimpleJavaGrammar a
-> b
forall b g a.
(Monoid b, ASTPrettyPrinter g) =>
b
-> (Node g a -> Int -> b)
-> (Node g a -> String -> b)
-> (Node g a -> b)
-> AST g a
-> b
showCodeAs b
indent Node SimpleJavaGrammar a -> Int -> b
indentGenerator Node SimpleJavaGrammar a -> String -> b
prtStrWithContext Node SimpleJavaGrammar a -> b
prtNode) (AST SimpleJavaGrammar a -> b) -> [AST SimpleJavaGrammar a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [AST SimpleJavaGrammar a]
l
            showListNoIndentIncrease :: String -> [AST SimpleJavaGrammar a] -> b
showListNoIndentIncrease sep :: String
sep l :: [AST SimpleJavaGrammar a]
l = [b] -> b
forall a. Monoid a => [a] -> a
mconcat ([b] -> b) -> [b] -> b
forall a b. (a -> b) -> a -> b
$ b -> [b] -> [b]
forall a. a -> [a] -> [a]
intersperse (String -> b
prtStr String
sep) ([b] -> [b]) -> [b] -> [b]
forall a b. (a -> b) -> a -> b
$ b
-> (Node SimpleJavaGrammar a -> Int -> b)
-> (Node SimpleJavaGrammar a -> String -> b)
-> (Node SimpleJavaGrammar a -> b)
-> AST SimpleJavaGrammar a
-> b
forall b g a.
(Monoid b, ASTPrettyPrinter g) =>
b
-> (Node g a -> Int -> b)
-> (Node g a -> String -> b)
-> (Node g a -> b)
-> AST g a
-> b
showCodeAs b
i Node SimpleJavaGrammar a -> Int -> b
indentGenerator Node SimpleJavaGrammar a -> String -> b
prtStrWithContext Node SimpleJavaGrammar a -> b
prtNode (AST SimpleJavaGrammar a -> b) -> [AST SimpleJavaGrammar a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [AST SimpleJavaGrammar a]
l
            showHead :: b
showHead = b
-> (Node SimpleJavaGrammar a -> Int -> b)
-> (Node SimpleJavaGrammar a -> String -> b)
-> (Node SimpleJavaGrammar a -> b)
-> AST SimpleJavaGrammar a
-> b
forall b g a.
(Monoid b, ASTPrettyPrinter g) =>
b
-> (Node g a -> Int -> b)
-> (Node g a -> String -> b)
-> (Node g a -> b)
-> AST g a
-> b
showCodeAs b
indent Node SimpleJavaGrammar a -> Int -> b
indentGenerator Node SimpleJavaGrammar a -> String -> b
prtStrWithContext Node SimpleJavaGrammar a -> b
prtNode (AST SimpleJavaGrammar a -> b) -> AST SimpleJavaGrammar a -> b
forall a b. (a -> b) -> a -> b
$ [AST SimpleJavaGrammar a] -> AST SimpleJavaGrammar a
forall a. [a] -> a
head [AST SimpleJavaGrammar a]
children
            in case Node SimpleJavaGrammar a -> SimpleJavaGrammar
forall g a. Node g a -> g
grammartype Node SimpleJavaGrammar a
n of
                SJava_MethodDef -> [b
indent, b
showHead, String -> b
prtStr " ", b
me, String -> [AST SimpleJavaGrammar a] -> b
showList " " ([AST SimpleJavaGrammar a] -> b) -> [AST SimpleJavaGrammar a] -> b
forall a b. (a -> b) -> a -> b
$ [AST SimpleJavaGrammar a] -> [AST SimpleJavaGrammar a]
forall a. [a] -> [a]
tail [AST SimpleJavaGrammar a]
children]
                SJava_ParametersDef -> [String -> b
prtStr "(", String -> [AST SimpleJavaGrammar a] -> b
showList ", " [AST SimpleJavaGrammar a]
children, String -> b
prtStr ")"]
                SJava_Args -> [String -> b
prtStr "(", String -> [AST SimpleJavaGrammar a] -> b
showList ", " [AST SimpleJavaGrammar a]
children, String -> b
prtStr ")"]
                SJava_Statements -> [
                    -- prtStr "\n",
                    -- i,
                    String -> b
prtStr "{\n",
                    if [AST SimpleJavaGrammar a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [AST SimpleJavaGrammar a]
children
                    then b
forall a. Monoid a => a
mempty
                    else (b -> b -> b
forall a. Monoid a => a -> a -> a
mappend (String -> [AST SimpleJavaGrammar a] -> b
showListNoIndentIncrease "\n" [AST SimpleJavaGrammar a]
children) (String -> b
prtStr "\n")),
                    b
i, String -> b
prtStr "}"]
                SJava_ExprStatement -> [b
indent, String -> [AST SimpleJavaGrammar a] -> b
showList " " [AST SimpleJavaGrammar a]
children, String -> b
prtStr ";"]
                SJava_Assignment -> [b -> [AST SimpleJavaGrammar a] -> b
showList' ([b] -> b
forall a. Monoid a => [a] -> a
mconcat [String -> b
prtStr" ",b
me,String -> b
prtStr" "]) [AST SimpleJavaGrammar a]
children]
                SJava_Return -> [b
indent, String -> b
prtStr "return ", String -> [AST SimpleJavaGrammar a] -> b
showList " " [AST SimpleJavaGrammar a]
children, String -> b
prtStr ";"]
                SJava_Condition -> [b
indent, String -> b
prtStr "if (", b
showHead, String -> b
prtStr ") ", String -> [AST SimpleJavaGrammar a] -> b
showList " " ([AST SimpleJavaGrammar a] -> b) -> [AST SimpleJavaGrammar a] -> b
forall a b. (a -> b) -> a -> b
$ [AST SimpleJavaGrammar a] -> [AST SimpleJavaGrammar a]
forall a. [a] -> [a]
tail [AST SimpleJavaGrammar a]
children]
                SJava_FuncCall -> [b
me, String -> [AST SimpleJavaGrammar a] -> b
showList ", " [AST SimpleJavaGrammar a]
children]
                SJava_Expression -> b -> [b]
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> [b]) -> b -> [b]
forall a b. (a -> b) -> a -> b
$ if [AST SimpleJavaGrammar a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [AST SimpleJavaGrammar a]
children Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1 then b
showHead else String -> b
forall a. HasCallStack => String -> a
error "Expressios can only have one child"
                SJava_UnaryOp -> b -> [b]
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> [b]) -> b -> [b]
forall a b. (a -> b) -> a -> b
$ if [AST SimpleJavaGrammar a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [AST SimpleJavaGrammar a]
children Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1 then b -> b -> b
forall a. Monoid a => a -> a -> a
mappend b
me b
showHead else String -> b
forall a. HasCallStack => String -> a
error "Unary operations can only have one child"
                SJava_BinaryOp -> if [AST SimpleJavaGrammar a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [AST SimpleJavaGrammar a]
children Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 2 then [b
showHead, String -> b
prtStr " ", b
me, String -> b
prtStr " ", b
-> (Node SimpleJavaGrammar a -> Int -> b)
-> (Node SimpleJavaGrammar a -> String -> b)
-> (Node SimpleJavaGrammar a -> b)
-> AST SimpleJavaGrammar a
-> b
forall b g a.
(Monoid b, ASTPrettyPrinter g) =>
b
-> (Node g a -> Int -> b)
-> (Node g a -> String -> b)
-> (Node g a -> b)
-> AST g a
-> b
showCodeAs b
indent Node SimpleJavaGrammar a -> Int -> b
indentGenerator Node SimpleJavaGrammar a -> String -> b
prtStrWithContext Node SimpleJavaGrammar a -> b
prtNode (AST SimpleJavaGrammar a -> b) -> AST SimpleJavaGrammar a -> b
forall a b. (a -> b) -> a -> b
$ [AST SimpleJavaGrammar a] -> AST SimpleJavaGrammar a
forall a. [a] -> a
head ([AST SimpleJavaGrammar a] -> AST SimpleJavaGrammar a)
-> [AST SimpleJavaGrammar a] -> AST SimpleJavaGrammar a
forall a b. (a -> b) -> a -> b
$ [AST SimpleJavaGrammar a] -> [AST SimpleJavaGrammar a]
forall a. [a] -> [a]
tail [AST SimpleJavaGrammar a]
children] else String -> [b]
forall a. HasCallStack => String -> a
error "Binary operations must have exactly two children"
                SJava_VarDecl -> b -> [b]
forall (m :: * -> *) a. Monad m => a -> m a
return (b -> [b]) -> b -> [b]
forall a b. (a -> b) -> a -> b
$ String -> [AST SimpleJavaGrammar a] -> b
showList " " [AST SimpleJavaGrammar a]
children
                SJava_VarRef -> b -> [b]
forall (m :: * -> *) a. Monad m => a -> m a
return b
me
                SJava_Literal -> b -> [b]
forall (m :: * -> *) a. Monad m => a -> m a
return b
me
                SJava_Type -> b -> [b]
forall (m :: * -> *) a. Monad m => a -> m a
return b
me
                SJava_File -> [b
indent, String -> b
prtStr "FILE [", b
me, String -> b
prtStr (String -> b) -> String -> b
forall a b. (a -> b) -> a -> b
$ "] {\n", String -> [AST SimpleJavaGrammar a] -> b
showList "\n" [AST SimpleJavaGrammar a]
children, String -> b
prtStr "\n", b
indent, String -> b
prtStr "}"]