Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
Eclipse Projects
Eclipse Titan
titan.EclipsePlug-ins
Commits
ac5969e1
Commit
ac5969e1
authored
May 13, 2022
by
Arpad Lovassy
Browse files
Added parser logger to Tools
Signed-off-by:
zlovarp
<
arpad.lovassy@semcon.com
>
parent
c8f9d90a
Changes
8
Show whitespace changes
Inline
Side-by-side
Tools/org.eclipse.titan.parserutils/.classpath
0 → 100644
View file @
ac5969e1
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry
kind=
"src"
path=
"src"
/>
<classpathentry
kind=
"con"
path=
"org.eclipse.pde.core.requiredPlugins"
/>
<classpathentry
kind=
"con"
path=
"org.eclipse.jdt.launching.JRE_CONTAINER"
/>
<classpathentry
kind=
"output"
path=
"bin"
/>
</classpath>
Tools/org.eclipse.titan.parserutils/.gitignore
0 → 100644
View file @
ac5969e1
/bin
Tools/org.eclipse.titan.parserutils/.project
0 → 100644
View file @
ac5969e1
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>
org.eclipse.titan.parserutils
</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>
org.eclipse.jdt.core.javabuilder
</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>
org.eclipse.jdt.core.javanature
</nature>
</natures>
</projectDescription>
Tools/org.eclipse.titan.parserutils/META-INF/MANIFEST.MF
0 → 100644
View file @
ac5969e1
Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: TITAN Parser Utils
Bundle-SymbolicName: org.eclipse.titan.parserutils
Bundle-Version: 8.2.0._20220504-1000
Require-Bundle: org.antlr.runtime;bundle-version="4.7.1",
org.eclipse.equinox.app,
org.eclipse.core.variables,
org.eclipse.core.runtime;bundle-version="3.5.0"
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
Bundle-ClassPath: .
Bundle-ActivationPolicy: lazy
Export-Package: org.eclipse.titan.parserutils,
org.eclipse.titan.parserutils.log
Bundle-Vendor: Eclipse Titan Project
Tools/org.eclipse.titan.parserutils/src/org/eclipse/titan/parserutils/log/ConsolePrinter.java
0 → 100644
View file @
ac5969e1
/******************************************************************************
* Copyright (c) 2000-2022 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
package
org.eclipse.titan.parserutils.log
;
/**
* Simple printer, that prints on the standard output stream
* @author Arpad Lovassy
*/
public
class
ConsolePrinter
implements
IPrinter
{
@Override
public
void
print
(
final
String
aMsg
)
{
System
.
out
.
print
(
aMsg
);
}
@Override
public
void
println
()
{
System
.
out
.
println
();
}
@Override
public
void
println
(
final
String
aMsg
)
{
System
.
out
.
println
(
aMsg
);
}
}
Tools/org.eclipse.titan.parserutils/src/org/eclipse/titan/parserutils/log/IPrinter.java
0 → 100644
View file @
ac5969e1
/******************************************************************************
* Copyright (c) 2000-2022 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
package
org.eclipse.titan.parserutils.log
;
/**
* Used by {@link ParserLogger} for logging to different consoles
* @author Arpad Lovassy
*/
public
interface
IPrinter
{
void
print
(
final
String
aMsg
);
void
println
();
void
println
(
final
String
aMsg
);
}
Tools/org.eclipse.titan.parserutils/src/org/eclipse/titan/parserutils/log/Interval.java
0 → 100644
View file @
ac5969e1
/******************************************************************************
* Copyright (c) 2000-2022 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
package
org.eclipse.titan.parserutils.log
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* Simple class which stores the interval related data extracted from source files by the proper lexer/parser. Can be used to quickly find the
* smallest enclosing interval of an offset.
*
* @author Kristof Szabados
* */
public
class
Interval
{
public
enum
interval_type
{
/**
* multi line comment (usually starting with /* end ending with
* *\/).
*/
MULTILINE_COMMENT
,
/** single line comments. */
SINGLELINE_COMMENT
,
/** block statement (usually between {} ). */
NORMAL
,
/** array indexing (usually between [] ). */
INDEX
,
/** parameter encloser ( usually between () ). */
PARAMETER
}
private
int
startOffset
;
private
int
startLine
;
private
int
endOffset
;
private
int
endLine
;
private
final
interval_type
type
;
private
int
depth
;
private
boolean
erroneous
;
private
List
<
Interval
>
subIntervals
;
private
final
Interval
parent
;
public
Interval
(
final
Interval
parent
,
final
interval_type
type
)
{
this
.
parent
=
parent
;
if
(
parent
!=
null
)
{
parent
.
addSubIntervall
(
this
);
depth
=
parent
.
getDepth
()
+
1
;
}
else
{
depth
=
0
;
}
startOffset
=
-
1
;
startLine
=
-
1
;
endOffset
=
-
1
;
endLine
=
-
1
;
this
.
type
=
type
;
erroneous
=
false
;
subIntervals
=
null
;
}
/**
* @return the type of the interval.
* */
public
final
interval_type
getType
()
{
return
type
;
}
/**
* @return whether this interval is a comment type one or not.
**/
public
final
boolean
isComment
()
{
return
interval_type
.
MULTILINE_COMMENT
.
equals
(
type
)
||
interval_type
.
SINGLELINE_COMMENT
.
equals
(
type
);
}
public
final
boolean
getErroneous
()
{
return
erroneous
;
}
public
final
void
setErroneous
()
{
erroneous
=
true
;
}
/**
* Returns the parent of the interval.
*
* @return the parent of the interval or null if it is the root interval
* */
public
final
Interval
getParent
()
{
return
parent
;
}
/**
* Add a child interval to this interval.
*
* @param child the child interval to be added.
* */
private
void
addSubIntervall
(
final
Interval
child
)
{
if
(
subIntervals
==
null
)
{
subIntervals
=
new
ArrayList
<
Interval
>();
}
subIntervals
.
add
(
child
);
}
/**
* @return the direct subintervals of this interval.
* */
public
final
List
<
Interval
>
getSubIntervals
()
{
if
(
subIntervals
==
null
)
{
return
new
ArrayList
<
Interval
>();
}
return
subIntervals
;
}
/**
* @return the starting offset of the interval.
* */
public
final
int
getStartOffset
()
{
return
startOffset
;
}
/**
* Sets the starting offset of the interval.
*
* @param offset the offset to be used as starting offset
* */
public
final
void
setStartOffset
(
final
int
offset
)
{
startOffset
=
offset
;
}
/**
* @return the starting line of the interval.
* */
public
final
int
getStartLine
()
{
return
startLine
;
}
/**
* Sets the starting line of the interval.
*
* @param line the line number to be used as starting line
* */
public
final
void
setStartLine
(
final
int
line
)
{
startLine
=
line
;
}
/**
* @return the ending offset of the interval.
* */
public
final
int
getEndOffset
()
{
return
endOffset
;
}
/**
* Sets the ending offset of the interval.
*
* @param offset the offset to be set as endoffset
* */
public
final
void
setEndOffset
(
final
int
offset
)
{
endOffset
=
offset
;
}
/**
* @return the ending line of the interval.
* */
public
int
getEndLine
()
{
return
endLine
;
}
/**
* Sets the ending line of the interval.
*
* @param line the line number to be used as ending line
* */
public
final
void
setEndLine
(
final
int
line
)
{
endLine
=
line
;
}
/**
* Calculates the depth of the actual interval in the actual hierarchy it is in.
*
* @return the depth of the interval in the interval hierarchy
* */
public
final
int
getDepth
()
{
return
depth
;
}
/**
* Finds the smallest enclosing interval to an offset. For this recursively walks the subtrees of the actual interval.
*
* @param offset the offset
*
* @return the smallest enclosing interval
* */
public
final
Interval
getSmallestEnclosingInterval
(
final
int
offset
)
{
return
getSmallestEnclosingInterval
(
offset
,
offset
);
}
/**
* Finds the smallest enclosing interval to a range. For this recursively walks the subtrees of the actual interval.
*
* @param startOffset the starting offset of the range
* @param endOffset the ending offset of the range
*
* @return the smallest enclosing interval
* */
public
final
Interval
getSmallestEnclosingInterval
(
final
int
startOffset
,
final
int
endOffset
)
{
if
(
subIntervals
==
null
)
{
return
this
;
}
//if the enclosing bracket "}" is missing, then the endOffset of the last subInterval is -1
//handle as infinity
final
int
lastEndOffset
=
subIntervals
.
get
(
subIntervals
.
size
()
-
1
).
getEndOffset
();
if
(!
subIntervals
.
isEmpty
()
&&
subIntervals
.
get
(
0
).
getStartOffset
()
<=
startOffset
&&
(
endOffset
<=
lastEndOffset
||
lastEndOffset
==
-
1
))
{
int
lowLimit
=
0
;
int
highLimit
=
subIntervals
.
size
();
int
middle
;
Interval
testedInterval
;
while
(
true
)
{
middle
=
(
lowLimit
+
highLimit
)
/
2
;
testedInterval
=
subIntervals
.
get
(
middle
);
if
(
endOffset
<
testedInterval
.
startOffset
)
{
highLimit
=
middle
;
}
else
if
(
startOffset
>
testedInterval
.
endOffset
&&
testedInterval
.
endOffset
!=
-
1
)
{
lowLimit
=
middle
;
}
else
if
(
testedInterval
==
this
){
return
this
;
//to avoid infinite loop
}
else
{
return
testedInterval
.
getSmallestEnclosingInterval
(
startOffset
,
endOffset
);
}
if
(
middle
==
(
lowLimit
+
highLimit
)
/
2
)
{
return
this
;
}
}
}
return
this
;
}
/**
* Finds the offset of the parameters pair. For this recursively walks the subtrees of the actual interval.
*
* @param offset the offset on which the original element is
*
* @return the offset of the parameters pair, or -1 if it can not be found
* */
public
final
int
getPairLocation
(
final
int
offset
)
{
if
(
startOffset
==
offset
)
{
return
endOffset
;
}
else
if
(
endOffset
==
offset
)
{
return
startOffset
;
}
else
if
(
subIntervals
!=
null
&&
!
subIntervals
.
isEmpty
())
{
return
findPairInSubIntervals
(
offset
);
}
return
-
1
;
}
private
int
findPairInSubIntervals
(
final
int
offset
)
{
int
lowLimit
=
0
;
int
highLimit
=
subIntervals
.
size
();
int
middle
;
Interval
testedInterval
;
while
(
true
)
{
middle
=
(
lowLimit
+
highLimit
)
/
2
;
testedInterval
=
subIntervals
.
get
(
middle
);
if
(
offset
<
testedInterval
.
startOffset
)
{
highLimit
=
middle
;
}
else
if
(
offset
>
testedInterval
.
endOffset
)
{
lowLimit
=
middle
;
}
else
{
return
testedInterval
.
getPairLocation
(
offset
);
}
if
(
middle
==
(
lowLimit
+
highLimit
)
/
2
)
{
return
-
1
;
}
}
}
}
Tools/org.eclipse.titan.parserutils/src/org/eclipse/titan/parserutils/log/ParserLogger.java
0 → 100644
View file @
ac5969e1
/******************************************************************************
* Copyright (c) 2000-2022 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
package
org.eclipse.titan.parserutils.log
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.text.SimpleDateFormat
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
import
org.antlr.v4.runtime.CommonTokenStream
;
import
org.antlr.v4.runtime.NoViableAltException
;
import
org.antlr.v4.runtime.Parser
;
import
org.antlr.v4.runtime.ParserRuleContext
;
import
org.antlr.v4.runtime.RecognitionException
;
import
org.antlr.v4.runtime.Token
;
import
org.antlr.v4.runtime.TokenStream
;
import
org.antlr.v4.runtime.Vocabulary
;
import
org.antlr.v4.runtime.tree.ParseTree
;
import
org.antlr.v4.runtime.tree.TerminalNodeImpl
;
/**
* USED FOR LOGGING PURPOSES.<br>
* Logger utility to print parse tree and interval tree.
* @author Arpad Lovassy
*/
public
final
class
ParserLogger
{
/** date format in ISO 8601 */
private
static
final
SimpleDateFormat
DATE_FORMAT
=
new
SimpleDateFormat
(
"yyyy-MM-dd HH:mm:ss"
);
private
static
IPrinter
sPrinter
=
new
ConsolePrinter
();
private
ParserLogger
()
{
// intentionally private to disable instantiation
}
private
static
void
setPrinter
(
final
IPrinter
aPrinter
)
{
sPrinter
=
aPrinter
;
}
/**
* Logs a parse tree. (General version)
* @param aRoot parse tree
* @param aParser parser to get rule names
* @param aPrinter printer
* @param aDescription description of the parsing type, for the logging (for example: TTCN-3, Cfg, ASN.1)
*/
public
static
synchronized
void
log
(
final
ParseTree
aRoot
,
final
Parser
aParser
,
final
IPrinter
aPrinter
,
final
String
aDescription
)
{
if
(
!
aParser
.
getBuildParseTree
()
)
{
// Parse tree logging is not requested
return
;
}
setPrinter
(
aPrinter
);
aPrinter
.
println
(
"---- parse tree"
);
aPrinter
.
println
(
DATE_FORMAT
.
format
(
new
Date
()
)
)
;
aPrinter
.
println
(
"Parser type: "
+
aDescription
+
", Prediction mode: "
+
aParser
.
getInterpreter
().
getPredictionMode
()
);
aPrinter
.
println
(
"Call stack: "
+
printCallStackReverse
(
4
)
);
final
TokenStream
tokenStream
=
aParser
.
getTokenStream
();
if
(
!
(
tokenStream
instanceof
CommonTokenStream
)
)
{
aPrinter
.
println
(
"ERROR: tokenStream is not CommonTokenStream"
);
return
;
}
final
CommonTokenStream
commonTokenStream
=
(
CommonTokenStream
)
tokenStream
;
final
List
<
Token
>
tokens
=
commonTokenStream
.
getTokens
();
log
(
aRoot
,
aParser
,
tokens
);
}
/**
* Logs a parse tree
* @param aRoot parse tree
* @param aParser parser to get rule names
* @param aTokens token list to get tokens by index (for getting tokens of a rule)
*/
public
static
void
log
(
final
ParseTree
aRoot
,
final
Parser
aParser
,
final
List
<
Token
>
aTokens
)
{
try
{
log
(
aRoot
,
aParser
,
aTokens
,
new
ArrayList
<
Boolean
>(),
false
,
false
);
}
catch
(
Exception
e
)
{
final
StringWriter
sw
=
new
StringWriter
();
final
PrintWriter
pw
=
new
PrintWriter
(
sw
);
e
.
printStackTrace
(
pw
);
println
(
sw
.
toString
()
);
// stack trace as a string
}
}
/**
* Logs a parse tree.
* Internal version.
* RECURSIVE
* @param aRoot parse tree
* @param aParser parser to get rule name
* @param aTokens token list to get tokens by index (for getting tokens of a rule)
* @param aLevel a list, that tells, if tree section is drawn for that level (parent).
* If the parent of the given level is already the last child, tree sections are not drawn below.
* NOTE: indentation level is aLevel.size()
* @param aParentOneChild parent has 1 child
* @param aLastChild this node is the last child of its parent
*/
private
static
void
log
(
final
ParseTree
aRoot
,
final
Parser
aParser
,
final
List
<
Token
>
aTokens
,
final
List
<
Boolean
>
aLevel
,
final
boolean
aParentOneChild
,
final
boolean
aLastChild
)
{
if
(
aRoot
==
null
)
{
println
(
"ERROR: ParseTree root is null"
);
return
;
}
if
(
!
aParser
.
getBuildParseTree
()
)
{
println
(
"ERROR: ParseTree is not build. Call Parser.setBuildParseTree( true ); BEFORE parsing. Or do NOT call Parser.setBuildParseTree( false );"
);
return
;
}
if
(
aRoot
instanceof
ParserRuleContext
)
{
final
ParserRuleContext
rule
=
(
ParserRuleContext
)
aRoot
;
final
String
ruleInfo
=
getRuleInfo
(
rule
,
aParser
);
if
(
aParentOneChild
)
{
printArrow
(
ruleInfo
);
}
else
{
printIndent
(
ruleInfo
,
aLevel
);
}
final
int
count
=
rule
.
getChildCount
();
final
boolean
oneChild
=
count
==
1
&&
rule
.
exception
==
null
;
if
(
!
oneChild
)
{
println
(
": '"
+
getEscapedRuleText
(
rule
,
aTokens
)
+
"'"
+
getExceptionInfo
(
rule
,
aParser
)
);
}
for
(
int
i
=
0
;
i
<
count
;
i
++
)
{
final
ParseTree
child
=
rule
.
getChild
(
i
);
List
<
Boolean
>
level
=
aLevel
;
if
(
!
aParentOneChild
)
{
level
=
new
ArrayList
<
Boolean
>(
aLevel
);
if
(
aLastChild
)
{
level
.
set
(
level
.
size
()
-
1
,
false
);
}
level
.
add
(
true
);
}
log
(
child
,
aParser
,
aTokens
,
level
,
oneChild
,
i
==
count
-
1
);
}
}
else
if
(
aRoot
instanceof
TerminalNodeImpl
)
{
final
TerminalNodeImpl
tn
=
(
TerminalNodeImpl
)
aRoot
;
final
String
tokenInfo
=
getTokenInfo
(
tn
.
getSymbol
(),
aParser
);
if
(
aParentOneChild
)
{
printArrow
(
tokenInfo
);
}
else
{
printIndent
(
tokenInfo
,
aLevel
);
}
if
(
tn
.
parent
==
null
)
{
print
(
", parent == null <-------------------------------------------------------------- ERROR"
);
}
println
();
}
else
{
final
String
parseTreeInfo
=
"Custom ParseTree: '"
+
getEscapedText
(
aRoot
.
getText
()
)
+
"'"
;
if
(
aParentOneChild
)
{
println
(
parseTreeInfo
);
}
else
{
printIndent
(
parseTreeInfo
,
aLevel
);
}
if
(
aRoot
.
getParent
()
==
null
)
{
print
(
", parent == null <-------------------------------------------------------------- ERROR"
);
}
println
();
}
}
/**
* Rule exception info in string format for logging purpose
* @param aRule rule
* @param aParser parser to get token name
* @return exception stack trace + some other info from the exception object
*/
private
static
String
getExceptionInfo
(
final
ParserRuleContext
aRule
,
final
Parser
aParser
)
{
final
RecognitionException
e
=
aRule
.
exception
;
if
(
e
==
null
)
{
return
""
;
}
final
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
", ERROR: mismatch, expected tokens: ["<