Specification
$flags: [ 'WORD_BOUNDARY', 'FLEXIBLE_WHITESPACE' ]
Comment: ['//.*', '(?s)/\*.*?\*/']
Keyword:
Class: 'class'
If: 'if'
Else: 'else'
For: 'for'
While: 'while'
Try: 'try'
Catch: 'catch'
Finally: 'finally'
Return: 'return'
Throw: 'throw'
Modifier: ['public', 'private', 'protected', 'static', 'final', 'abstract']
Type:
KnownClass: [ 'String', 'System', 'ArithmeticException' ]
Primitive: [ 'void', 'boolean', 'int', 'long', 'double', 'char' ]
Array:
$fields: { elementType: Type }
$patterns: '#{elementType}\[\]'
Expression:
Identifier: '${!Keyword}[A-Za-z_][A-Za-z0-9_]*'
StringLiteral: '"([^"\\]|\\.)*"'
NumberLiteral: '\d+(\.\d+)?'
BooleanLiteral: 'true|false'
NullLiteral: 'null'
MethodCall:
$flags: OPTIONAL_WHITESPACE
$types:
NamePart:
KnownClass: '${Type::KnownClass}'
Identifier: '${Expression::Identifier}'
QualifiedName:
$fields:
parts: NamePart[]
$patterns: '#{parts}(\.#{parts})*'
$fields:
receiver: QualifiedName
methodName: Expression::Identifier
arguments: Expression[]
$patterns:
- '#{receiver}\.#{methodName}\((#{arguments}(, #{arguments})*)?\)'
- '#{methodName}\((#{arguments}(, #{arguments})*)?\)'
Operation:
Binary:
$flags: OPTIONAL_WHITESPACE
$fields:
left: Expression
right: Expression
Addition: '#{left} \+ #{right}'
Subtraction: '#{left} - #{right}'
Multiplication: '#{left} \* #{right}'
Division: '#{left} / #{right}'
Unary:
$fields:
value: Expression
Increment: '#{value}\+\+'
Decrement: '#{value}--'
Comparison:
$flags: OPTIONAL_WHITESPACE
$fields:
left: Expression
right: Expression
Equality: '#{left} == #{right}'
Inequality: '#{left} != #{right}'
LessThan: '#{left} < #{right}'
GreaterThan: '#{left} > #{right}'
LessOrEqual: '#{left} <= #{right}'
GreaterOrEqual: '#{left} >= #{right}'
Declaration:
Parameter:
$fields:
type: Type
name: Expression::Identifier
$patterns: '#{type} #{name}(?=,|\))'
CodeElement:
CommentStatement: '${Comment}'
MethodCallStatement:
$flags: OPTIONAL_WHITESPACE
$fields:
call: Expression::MethodCall
$patterns: '#{call};'
VariableDeclaration:
$fields:
type: Type
name: Expression::Identifier
value: Expression
$patterns: '#{type} #{name} = #{value};'
Block:
$flags: OPTIONAL_WHITESPACE
$fields:
statements: CodeElement[]
$patterns: '\{ (#{statements}( #{statements})*)? \}'
ReturnStatement:
$fields:
value: Expression
$patterns: '${Keyword::Return} #{value};'
ThrowStatement:
$fields:
value: Expression
$patterns: '${Keyword::Throw} #{value};'
IfElseStatement:
$fields:
condition: Expression::Comparison
ifBody: CodeElement
elseBody: CodeElement
$patterns: '${Keyword::If} \(#{condition}\) #{ifBody}( ${Keyword::Else} #{elseBody})?'
ForStatement:
$fields:
type: Type
name: Expression::Identifier
initialValue: Expression
condition: Expression::Comparison
step: Expression::Operation::Unary::Increment
body: CodeElement
$patterns: '${Keyword::For} \(#{type} #{name} = #{initialValue}; #{condition}; #{step}\)\s*#{body}'
WhileStatement:
$fields:
condition: Expression::Comparison
body: CodeElement
$patterns: '${Keyword::While} \(#{condition}\) #{body}'
TryCatchFinallyStatement:
$fields:
tryBody: CodeElement
exception: Declaration::Parameter
catchBody: CodeElement
finallyBody: CodeElement
$patterns: '${Keyword::Try} #{tryBody}( ${Keyword::Catch} \(#{exception}\) #{catchBody})?( ${Keyword::Finally} #{finallyBody})?'
MethodDeclaration:
$fields:
modifiers: Keyword::Modifier[]
returnType: Type
name: Expression::Identifier
parameters: Declaration::Parameter[]
body: CodeElement::Block
$patterns: '(#{modifiers} )*#{returnType} #{name}\((#{parameters}(, #{parameters})*)?\) #{body}'
ClassDeclaration:
$fields:
modifiers: Keyword::Modifier[]
name: Expression::Identifier
body: CodeElement::Block
$patterns: '(#{modifiers} )*${Keyword::Class} #{name} #{body}'Sample input
/* Compact Java-like fragment. */
public class Example {
public static void main(String[] args) {
int x = 10;
if (x > 5) {
System.out.println("large");
} else {
System.out.println("small");
}
}
}
Result
[
{
"type": "CodeElement::CommentStatement",
"text": "/* Compact Java-like fragment. */",
"start": 0,
"end": 33
},
{
"type": "CodeElement::ClassDeclaration",
"text": "public class Example {\n public static void main(String[] args) {\n int x = 10;\n if (x > 5) {\n System.out.println(\"large\");\n } else {\n System.out.println(\"small\");\n }\n }\n}",
"start": 34,
"end": 259,
"fields": [
{
"type": "Keyword::Modifier[]",
"field": "modifiers",
"text": "public",
"start": 34,
"end": 40,
"items": [
{
"type": "Keyword::Modifier",
"text": "public",
"start": 34,
"end": 40
}
]
},
{
"type": "Expression::Identifier",
"field": "name",
"text": "Example",
"start": 47,
"end": 54
},
{
"type": "CodeElement::Block",
"field": "body",
"text": "{\n public static void main(String[] args) {\n int x = 10;\n if (x > 5) {\n System.out.println(\"large\");\n } else {\n System.out.println(\"small\");\n }\n }\n}",
"start": 55,
"end": 259,
"fields": [
{
"type": "CodeElement[]",
"field": "statements",
"text": "public static void main(String[] args) {\n int x = 10;\n if (x > 5) {\n System.out.println(\"large\");\n } else {\n System.out.println(\"small\");\n }\n }",
"start": 61,
"end": 257,
"items": [
{
"type": "CodeElement::MethodDeclaration",
"text": "public static void main(String[] args) {\n int x = 10;\n if (x > 5) {\n System.out.println(\"large\");\n } else {\n System.out.println(\"small\");\n }\n }",
"start": 61,
"end": 257,
"fields": [
{
"type": "Keyword::Modifier[]",
"field": "modifiers",
"text": "public static",
"start": 61,
"end": 74,
"items": [
{
"type": "Keyword::Modifier",
"text": "public",
"start": 61,
"end": 67
},
{
"type": "Keyword::Modifier",
"text": "static",
"start": 68,
"end": 74
}
]
},
{
"type": "Type::Primitive",
"field": "returnType",
"text": "void",
"start": 75,
"end": 79
},
{
"type": "Expression::Identifier",
"field": "name",
"text": "main",
"start": 80,
"end": 84
},
{
"type": "Declaration::Parameter[]",
"field": "parameters",
"text": "String[] args",
"start": 85,
"end": 98,
"items": [
{
"type": "Declaration::Parameter",
"text": "String[] args",
"start": 85,
"end": 98,
"fields": [
{
"type": "Type::Array",
"field": "type",
"text": "String[]",
"start": 85,
"end": 93,
"fields": [
{
"type": "Type::KnownClass",
"field": "elementType",
"text": "String",
"start": 85,
"end": 91
}
]
},
{
"type": "Expression::Identifier",
"field": "name",
"text": "args",
"start": 94,
"end": 98
}
]
}
]
},
{
"type": "CodeElement::Block",
"field": "body",
"text": "{\n int x = 10;\n if (x > 5) {\n System.out.println(\"large\");\n } else {\n System.out.println(\"small\");\n }\n }",
"start": 100,
"end": 257,
"fields": [
{
"type": "CodeElement[]",
"field": "statements",
"text": "int x = 10;\n if (x > 5) {\n System.out.println(\"large\");\n } else {\n System.out.println(\"small\");\n }",
"start": 110,
"end": 251,
"items": [
{
"type": "CodeElement::VariableDeclaration",
"text": "int x = 10;",
"start": 110,
"end": 121,
"fields": [
{
"type": "Type::Primitive",
"field": "type",
"text": "int",
"start": 110,
"end": 113
},
{
"type": "Expression::Identifier",
"field": "name",
"text": "x",
"start": 114,
"end": 115
},
{
"type": "Expression::NumberLiteral",
"field": "value",
"text": "10",
"start": 118,
"end": 120
}
]
},
{
"type": "CodeElement::IfElseStatement",
"text": "if (x > 5) {\n System.out.println(\"large\");\n } else {\n System.out.println(\"small\");\n }",
"start": 130,
"end": 251,
"fields": [
{
"type": "Expression::Comparison::GreaterThan",
"field": "condition",
"text": "x > 5",
"start": 134,
"end": 139,
"fields": [
{
"type": "Expression::Identifier",
"field": "left",
"text": "x",
"start": 134,
"end": 135
},
{
"type": "Expression::NumberLiteral",
"field": "right",
"text": "5",
"start": 138,
"end": 139
}
]
},
{
"type": "CodeElement::Block",
"field": "ifBody",
"text": "{\n System.out.println(\"large\");\n }",
"start": 141,
"end": 193,
"fields": [
{
"type": "CodeElement[]",
"field": "statements",
"text": "System.out.println(\"large\");",
"start": 155,
"end": 183,
"items": [
{
"type": "CodeElement::MethodCallStatement",
"text": "System.out.println(\"large\");",
"start": 155,
"end": 183,
"fields": [
{
"type": "Expression::MethodCall",
"field": "call",
"text": "System.out.println(\"large\")",
"start": 155,
"end": 182,
"fields": [
{
"type": "QualifiedName",
"field": "receiver",
"text": "System.out",
"start": 155,
"end": 165,
"fields": [
{
"type": "NamePart[]",
"field": "parts",
"text": "System.out",
"start": 155,
"end": 165,
"items": [
{
"type": "NamePart::KnownClass",
"text": "System",
"start": 155,
"end": 161
},
{
"type": "NamePart::Identifier",
"text": "out",
"start": 162,
"end": 165
}
]
}
]
},
{
"type": "Expression::Identifier",
"field": "methodName",
"text": "println",
"start": 166,
"end": 173
},
{
"type": "Expression[]",
"field": "arguments",
"text": "\"large\"",
"start": 174,
"end": 181,
"items": [
{
"type": "Expression::StringLiteral",
"text": "\"large\"",
"start": 174,
"end": 181
}
]
}
]
}
]
}
]
}
]
},
{
"type": "CodeElement::Block",
"field": "elseBody",
"text": "{\n System.out.println(\"small\");\n }",
"start": 199,
"end": 251,
"fields": [
{
"type": "CodeElement[]",
"field": "statements",
"text": "System.out.println(\"small\");",
"start": 213,
"end": 241,
"items": [
{
"type": "CodeElement::MethodCallStatement",
"text": "System.out.println(\"small\");",
"start": 213,
"end": 241,
"fields": [
{
"type": "Expression::MethodCall",
"field": "call",
"text": "System.out.println(\"small\")",
"start": 213,
"end": 240,
"fields": [
{
"type": "QualifiedName",
"field": "receiver",
"text": "System.out",
"start": 213,
"end": 223,
"fields": [
{
"type": "NamePart[]",
"field": "parts",
"text": "System.out",
"start": 213,
"end": 223,
"items": [
{
"type": "NamePart::KnownClass",
"text": "System",
"start": 213,
"end": 219
},
{
"type": "NamePart::Identifier",
"text": "out",
"start": 220,
"end": 223
}
]
}
]
},
{
"type": "Expression::Identifier",
"field": "methodName",
"text": "println",
"start": 224,
"end": 231
},
{
"type": "Expression[]",
"field": "arguments",
"text": "\"small\"",
"start": 232,
"end": 239,
"items": [
{
"type": "Expression::StringLiteral",
"text": "\"small\"",
"start": 232,
"end": 239
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]
}
]Notes
# Java Code Fragments
Recognize a constrained Java-like subset as semantic code fragments.
## Notice
- `Type` separates known classes, primitive types, and arrays.
- `Expression` covers literals, identifiers, method calls, arithmetic, and comparisons.
- `Expression::MethodCall` models the call separately from the trailing statement semicolon.
- Scoped `$types` inside method calls model qualified receivers such as `System.out`.
- `Declaration::Parameter` is scoped to method signatures.
- `CodeElement` composes blocks, `if/else`, methods, and classes.
- Modifiers and block statements are repeatable fields.
Try adding a simple declaration or another `System.out.println(...)` call.