| /*=============================================================================# |
| # Copyright (c) 2009, 2021 Stephan Wahlbrink and others. |
| # |
| # This program and the accompanying materials are made available under the |
| # terms of the Eclipse Public License 2.0 which is available at |
| # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0 |
| # which is available at https://www.apache.org/licenses/LICENSE-2.0. |
| # |
| # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 |
| # |
| # Contributors: |
| # Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation |
| #=============================================================================*/ |
| |
| package org.eclipse.statet.yaml.core.ast; |
| |
| import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert; |
| |
| import static org.eclipse.statet.ltk.ast.core.AstNode.NA_OFFSET; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS1_SYNTAX_MISSING_INDICATOR; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS2_SYNTAX_CHAR_INVALID; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS2_SYNTAX_COLLECTION_NOT_CLOSED; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS2_SYNTAX_ESCAPE_INVALID; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS2_SYNTAX_TOKEN_NOT_CLOSED; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS2_SYNTAX_TOKEN_UNEXPECTED; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS2_SYNTAX_TOKEN_UNKNOWN; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS3_FLOW_MAP; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS3_FLOW_SEQ; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS3_MAP_KEY; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS3_MAP_VALUE; |
| import static org.eclipse.statet.yaml.core.ast.YamlAstStatusConstants.STATUS3_SEQ_ENTRY; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.yaml.snakeyaml.error.Mark; |
| import org.yaml.snakeyaml.tokens.AliasToken; |
| import org.yaml.snakeyaml.tokens.ScalarToken; |
| import org.yaml.snakeyaml.tokens.TagToken; |
| import org.yaml.snakeyaml.tokens.TagTuple; |
| import org.yaml.snakeyaml.tokens.Token; |
| |
| import org.eclipse.statet.jcommons.lang.NonNullByDefault; |
| import org.eclipse.statet.jcommons.lang.Nullable; |
| |
| import org.eclipse.statet.internal.yaml.snakeyaml.scanner.ScannerConstants; |
| import org.eclipse.statet.internal.yaml.snakeyaml.scanner.ScannerImpl; |
| import org.eclipse.statet.internal.yaml.snakeyaml.scanner.StreamReader; |
| import org.eclipse.statet.ltk.ast.core.AstNode; |
| import org.eclipse.statet.ltk.ast.core.StatusDetail; |
| |
| |
| @NonNullByDefault |
| public class YamlParser { |
| |
| |
| private static class ProblemInfo { |
| |
| //private final byte context; |
| private final @Nullable Mark contextMark; |
| private final byte problem; |
| private final @Nullable Mark problemMark; |
| private final @Nullable String problemText; |
| |
| public ProblemInfo(final byte context, final @Nullable Mark contextMark, |
| final byte problem, final @Nullable Mark problemMark, final @Nullable String problemText) { |
| //this.context= context; |
| this.contextMark= contextMark; |
| this.problem= problem; |
| this.problemMark= problemMark; |
| this.problemText= problemText; |
| } |
| |
| } |
| |
| |
| private final ScannerImpl scanner= new ScannerImpl(new StreamReader(""), true, true, false) { //$NON-NLS-1$ |
| @Override |
| protected void handleComment(final int startIndex, final int endIndex) { |
| } |
| @Override |
| protected void handleSyntaxProblem(final byte context, final @Nullable Mark contextMark, |
| final byte problem, final @Nullable Mark problemMark, final @Nullable String problemArg1, final @Nullable String problemArg2) { |
| YamlParser.this.handleScannerProblem(new ProblemInfo(context, contextMark, |
| problem, problemMark, problemArg1 )); |
| } |
| }; |
| |
| |
| private @Nullable YamlAstNode currentNode; |
| |
| private int depth; |
| private final List<List<YamlAstNode>> childrenStack= new ArrayList<>(); |
| |
| private final List<ProblemInfo> problemInfos= new ArrayList<>(); |
| |
| |
| public YamlParser() { |
| } |
| |
| |
| public void setScalarText(final boolean create) { |
| this.scanner.setCreateScalarText(create); |
| } |
| |
| public SourceComponent parse(final String text, final @Nullable AstNode parent, final int offset) { |
| try { |
| this.depth= -1; |
| this.scanner.reset(text, offset); |
| |
| final SourceComponent sourceComponent= new SourceComponent(parent, offset, text.length()); |
| enterNode(sourceComponent); |
| |
| processTokens(); |
| |
| while (this.depth >= 0) { |
| exit(); |
| } |
| |
| return sourceComponent; |
| } |
| finally { |
| while (this.depth >= 0) { |
| final List<YamlAstNode> list= this.childrenStack.get(this.depth); |
| list.clear(); |
| this.depth--; |
| } |
| this.problemInfos.clear(); |
| } |
| } |
| |
| public SourceComponent parse(final String text) { |
| return parse(text, null, 0); |
| } |
| |
| |
| private void addChildTerm(final YamlAstNode node) { |
| addChild(node); |
| |
| checkExit(); |
| } |
| |
| private void addChild(final YamlAstNode node) { |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| if (currentNode.getNodeType() == NodeType.MAP_ENTRY) { |
| final Tuple entry= (Tuple) currentNode; |
| if (entry.keyNode == null && entry.valueIndicatorOffset == NA_OFFSET) { |
| entry.keyNode= node; |
| } |
| else { |
| entry.valueNode= node; |
| } |
| } |
| else { |
| final List<YamlAstNode> children= this.childrenStack.get(this.depth); |
| children.add(node); |
| |
| if (this.depth == 0) { |
| clearProblems(node.getStartOffset()); |
| } |
| } |
| } |
| |
| private void finish(final int endOffset) { |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| switch (currentNode.getNodeType()) { |
| case MAP_ENTRY: { |
| final Tuple entry= (Tuple) currentNode; |
| if (entry.keyNode == null) { |
| entry.keyNode= new Dummy(0, entry, // empty node |
| (entry.keyIndicatorOffset != NA_OFFSET) ? |
| entry.keyIndicatorOffset : entry.startOffset ); |
| } |
| if (entry.status == 0 && entry.valueIndicatorOffset == Integer.MAX_VALUE) { |
| entry.status= STATUS1_SYNTAX_MISSING_INDICATOR | STATUS3_MAP_VALUE; |
| } |
| if (entry.valueNode == null) { |
| entry.valueNode= new Dummy(0, entry, // empty node |
| (entry.valueIndicatorOffset != NA_OFFSET) ? |
| entry.valueIndicatorOffset : entry.keyNode.endOffset ); |
| } |
| final int min= entry.valueNode.endOffset; |
| if (entry.endOffset < min) { |
| entry.endOffset= min; |
| } |
| return; |
| } |
| case MAP: { |
| final Collection collection= (Collection) currentNode; |
| switch (collection.getOperator()) { |
| case '[': |
| if (collection.getCloseIndicatorOffset() == NA_OFFSET) { |
| collection.status= STATUS2_SYNTAX_COLLECTION_NOT_CLOSED | STATUS3_FLOW_SEQ; |
| } |
| break; |
| case '{': |
| if (collection.getCloseIndicatorOffset() == NA_OFFSET) { |
| collection.status= STATUS2_SYNTAX_COLLECTION_NOT_CLOSED | STATUS3_FLOW_MAP; |
| } |
| break; |
| } |
| break; // -> NContainer |
| } |
| default: |
| break; // -> NContainer |
| } |
| |
| { final NContainer container= (NContainer) currentNode; |
| if (endOffset != NA_OFFSET) { |
| container.endOffset= endOffset; |
| } |
| |
| final List<YamlAstNode> children= this.childrenStack.get(this.depth); |
| if (!children.isEmpty()) { |
| container.children= children.toArray(new YamlAstNode[children.size()]); |
| children.clear(); |
| |
| final int min= container.children[container.children.length - 1].getEndOffset(); |
| if (container.endOffset < min) { |
| container.endOffset= min; |
| } |
| } |
| } |
| } |
| |
| private void enterNode(final NContainer node) { |
| if (this.depth >= 0) { |
| addChild(node); |
| } |
| |
| this.depth++; |
| this.currentNode= node; |
| |
| while (this.depth >= this.childrenStack.size()) { |
| this.childrenStack.add(new ArrayList<YamlAstNode>()); |
| } |
| } |
| |
| private void enterNode(final Tuple node) { |
| addChild(node); |
| |
| this.depth++; |
| this.currentNode= node; |
| } |
| |
| private boolean exitTo(final Class<?> type1) { |
| while (this.depth > 1) { |
| if (this.currentNode.getClass() == type1) { |
| return true; |
| } |
| exit(); |
| } |
| return false; |
| } |
| |
| private boolean exitTo(final Class<?> type1, final Class<?> type2) { |
| while (this.depth > 1) { |
| if (this.currentNode.getClass() == type1 || this.currentNode.getClass() == type2) { |
| return true; |
| } |
| exit(); |
| } |
| return false; |
| } |
| |
| private boolean exitTo1(final Class<?> type1) { |
| while (this.depth > 1) { |
| if (this.currentNode.getClass() == type1) { |
| return true; |
| } |
| if (this.currentNode.getNodeType() == NodeType.MAP_ENTRY) { |
| exit(); |
| } |
| break; |
| } |
| int checkDepth= this.depth - 1; |
| YamlAstNode node= this.currentNode.getYamlParent(); |
| while (checkDepth > 1 && node != null) { |
| if (node.getClass() == type1) { |
| while (this.depth > checkDepth) { |
| exit(); |
| } |
| return true; |
| } |
| checkDepth--; |
| node= node.getYamlParent(); |
| } |
| return false; |
| } |
| |
| private boolean exitTo1(final Class<?> type1, final Class<?> type2) { |
| while (this.depth > 1) { |
| if (this.currentNode.getClass() == type1 || this.currentNode.getClass() == type2) { |
| return true; |
| } |
| if (this.currentNode.getNodeType() == NodeType.MAP_ENTRY) { |
| exit(); |
| } |
| break; |
| } |
| int checkDepth= this.depth - 1; |
| YamlAstNode node= this.currentNode.getYamlParent(); |
| while (checkDepth > 1 && node != null) { |
| if (node.getClass() == type1 || node.getClass() == type2) { |
| while (this.depth > checkDepth) { |
| exit(); |
| } |
| return true; |
| } |
| checkDepth--; |
| node= node.getYamlParent(); |
| } |
| return false; |
| } |
| |
| private boolean exitTo(final NodeType type1) { |
| while (this.depth > 1) { |
| if (this.currentNode.getNodeType() == type1) { |
| return true; |
| } |
| exit(); |
| } |
| return false; |
| } |
| |
| private boolean exitTo(final NodeType type1, final NodeType type2) { |
| while (this.depth > 1) { |
| if (this.currentNode.getNodeType() == type1 || this.currentNode.getNodeType() == type2) { |
| return true; |
| } |
| exit(); |
| } |
| return false; |
| } |
| |
| private void exitToSourceComponent(final int offset) { |
| while (this.depth > 1) { |
| exit(); |
| } |
| if (this.depth > 0) { |
| exit(offset); |
| } |
| } |
| |
| private void exit(final int offset) { |
| finish(offset); |
| this.currentNode= this.currentNode.yamlParent; |
| this.depth--; |
| |
| checkExit(); |
| } |
| |
| private void exit() { |
| finish(NA_OFFSET); |
| this.currentNode= this.currentNode.yamlParent; |
| this.depth--; |
| |
| checkExit(); |
| } |
| |
| private void checkExit() { |
| if (this.depth > 0 && this.currentNode.getNodeType() == NodeType.MAP_ENTRY |
| && ((Tuple) this.currentNode).valueNode != null) { |
| exit(); |
| } |
| } |
| |
| |
| private void processTokens() { |
| while (true) { |
| final Token token= this.scanner.nextToken(); |
| if (token == null) { |
| break; |
| } |
| |
| switch (token.getTokenId()) { |
| case StreamStart: |
| case StreamEnd: |
| continue; |
| |
| case Directive: { |
| exitToSourceComponent(token.getStartMark().getIndex()); |
| final Directive node= new Directive((SourceComponent) this.currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| addChildTerm(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| case DocumentStart: { |
| exitToSourceComponent(token.getStartMark().getIndex()); |
| final Instruction.DocStart node= new Instruction.DocStart((SourceComponent) this.currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| addChildTerm(node); |
| checkForProblem(token.getStartMark(), node); |
| enterNode(new DocContent((SourceComponent) this.currentNode, |
| token.getStartMark().getIndex() )); |
| continue; |
| } |
| case DocumentEnd: { |
| exitToSourceComponent(token.getStartMark().getIndex()); |
| final Instruction.DocEnd node= new Instruction.DocEnd((SourceComponent) this.currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| addChildTerm(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| |
| case BlockSequenceStart: { |
| final Collection.BlockSeq node= new Collection.BlockSeq(this.currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| enterNode(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| case BlockMappingStart: { |
| final Collection.BlockMap node= new Collection.BlockMap(this.currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| enterNode(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| case BlockEnd: { |
| final boolean found= exitTo(Collection.BlockSeq.class, Collection.BlockMap.class); |
| if (found) { |
| exit(token.getEndMark().getIndex()); |
| } |
| continue; |
| } |
| case FlowSequenceStart: { |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Collection.FlowCollection node= new Collection.FlowSeq(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| enterNode(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| case FlowSequenceEnd: { |
| final boolean found= exitTo(Collection.FlowSeq.class); |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Collection.FlowSeq collection; |
| if (found) { |
| collection= (Collection.FlowSeq) currentNode; |
| collection.closeIndicatorOffset= token.getStartMark().getIndex(); |
| exit(token.getEndMark().getIndex()); |
| } |
| else { |
| addChildTerm(new Dummy(STATUS2_SYNTAX_TOKEN_UNEXPECTED, currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() )); |
| } |
| continue; |
| } |
| case FlowMappingStart: { |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Collection.FlowCollection node= new Collection.FlowMap(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| enterNode(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| case FlowMappingEnd: { |
| final boolean found= exitTo(Collection.FlowMap.class); |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Collection.FlowMap node; |
| if (found) { |
| node= (Collection.FlowMap) currentNode; |
| node.closeIndicatorOffset= token.getStartMark().getIndex(); |
| exit(token.getEndMark().getIndex()); |
| } |
| else { |
| addChildTerm(new Dummy(STATUS2_SYNTAX_TOKEN_UNEXPECTED, currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() )); |
| } |
| continue; |
| } |
| |
| case BlockEntry: { |
| final boolean found= exitTo1(Collection.BlockSeq.class); |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Collection.BlockSeq node; |
| if (found) { |
| node= (Collection.BlockSeq) currentNode; |
| } |
| else { |
| node= new Collection.BlockSeq(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| enterNode(node); |
| checkForProblem(token.getStartMark(), node); |
| } |
| continue; |
| } |
| case FlowEntry: { |
| final boolean found= exitTo1(Collection.FlowSeq.class, Collection.FlowMap.class); |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| if (!found) { |
| addChildTerm(new Dummy(STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_SEQ_ENTRY, |
| currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() )); |
| } |
| continue; |
| } |
| |
| case Anchor: { |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Label node= new Label.Anchor(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex(), |
| ((AliasToken) token).getValue() ); |
| addChildTerm(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| case Alias: { |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Label node= new Label.Reference(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex(), |
| ((AliasToken) token).getValue() ); |
| addChildTerm(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| |
| case Key: { |
| final boolean found= exitTo(NodeType.MAP); |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Tuple node= new Tuple(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| if (!found) { |
| node.status|= STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_MAP_KEY; |
| } |
| enterNode(node); |
| checkForProblem(token.getStartMark(), node); |
| if (node.getLength() > 0) { // explicite |
| node.keyIndicatorOffset= node.startOffset; |
| } |
| continue; |
| } |
| case Value: { |
| final boolean found= exitTo(NodeType.MAP_ENTRY, NodeType.MAP); |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Tuple node; |
| if (currentNode.getNodeType() == NodeType.MAP_ENTRY) { |
| node= (Tuple) currentNode; |
| } |
| else { |
| node= new Tuple(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex() ); |
| if (!found) { |
| node.status|= STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_MAP_VALUE; |
| } |
| enterNode(node); |
| } |
| checkForProblem(token.getStartMark(), node); |
| node.valueIndicatorOffset= token.getStartMark().getIndex(); |
| node.endOffset= token.getEndMark().getIndex(); |
| continue; |
| } |
| |
| case Tag: { |
| final TagTuple tagTuple= ((TagToken) token).getValue(); |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Tag node= new Tag(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex(), |
| tagTuple.getHandle(), tagTuple.getSuffix() ); |
| addChildTerm(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| |
| case Scalar: { |
| final ScalarToken scalarToken= (ScalarToken) token; |
| final YamlAstNode currentNode= nonNullAssert(this.currentNode); |
| final Scalar node; |
| switch (scalarToken.getStyle()) { |
| case DOUBLE_QUOTED: |
| node= new Scalar.DQuoted(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex(), |
| scalarToken.getValue() ); |
| break; |
| case SINGLE_QUOTED: |
| node= new Scalar.SQuoated(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex(), |
| scalarToken.getValue() ); |
| break; |
| default: |
| node= new Scalar.Plain(currentNode, |
| token.getStartMark().getIndex(), token.getEndMark().getIndex(), |
| scalarToken.getValue() ); |
| break; |
| } |
| addChildTerm(node); |
| checkForProblem(token.getStartMark(), node); |
| continue; |
| } |
| |
| default: |
| continue; |
| } |
| } |
| } |
| |
| private void handleScannerProblem(final ProblemInfo p) { |
| if (p.contextMark == null) { |
| if (p.problemMark != null && p.problemText != null) { |
| switch ((p.problemText.length() == 1) ? p.problemText.charAt(0) : 0) { |
| case ':': |
| case ',': |
| case '%': |
| case '-': |
| case '.': |
| case '?': |
| case '|': |
| case '>': |
| addChildTerm(new Dummy(STATUS2_SYNTAX_TOKEN_UNEXPECTED, this.currentNode, |
| p.problemMark.getIndex(), p.problemMark.getIndex() + p.problemText.length() )); |
| break; |
| default: |
| addChildTerm(new Dummy(STATUS2_SYNTAX_TOKEN_UNKNOWN, this.currentNode, |
| p.problemMark.getIndex(), p.problemMark.getIndex() + p.problemText.length() )); |
| } |
| } |
| } |
| else { |
| keepProblem(p); |
| } |
| } |
| |
| private void keepProblem(final ProblemInfo p) { |
| final int contextIndex= p.contextMark.getIndex(); |
| int idx= this.problemInfos.size(); |
| while (idx > 0) { |
| if (this.problemInfos.get(idx - 1).contextMark.getIndex() <= contextIndex) { |
| break; |
| } |
| idx--; |
| } |
| this.problemInfos.add(idx, p); |
| } |
| |
| private void clearProblems(final int contextIndex) { |
| int idx= 0; |
| while (idx < this.problemInfos.size()) { |
| if (this.problemInfos.get(idx).contextMark.getIndex() < contextIndex) { |
| idx++; |
| } |
| else { |
| break; |
| } |
| } |
| if (idx > 1) { |
| if (idx == 2) { |
| this.problemInfos.remove(0); |
| } |
| else { |
| this.problemInfos.subList(0, idx - 1).clear(); |
| } |
| } |
| } |
| |
| private void checkForProblem(final Mark startMark, final YamlAstNode node) { |
| final int contextIndex= startMark.getIndex(); |
| for (int idx= 0; idx < this.problemInfos.size(); ) { |
| final ProblemInfo p= this.problemInfos.get(idx); |
| if (p.contextMark == startMark) { |
| if (attachProblem(node, p)) { |
| this.problemInfos.remove(idx); |
| continue; |
| } |
| } |
| if (p.contextMark.getIndex() > contextIndex) { |
| break; |
| } |
| idx++; |
| } |
| } |
| |
| private boolean attachProblem(final YamlAstNode node, final ProblemInfo p) { |
| if (node.getStatusCode() != 0) { |
| return false; |
| } |
| switch (p.problem) { |
| case ScannerConstants.UNEXPECTED_CHAR: |
| case ScannerConstants.UNEXPECTED_CHAR_2: |
| if (p.problemMark != null && p.problemMark.getIndex() >= node.getStartOffset() |
| && p.problemMark.getIndex() < node.getEndOffset() |
| && p.problemText != null) { |
| node.status= STATUS2_SYNTAX_CHAR_INVALID; |
| node.addAttachment(new StatusDetail( |
| p.problemMark.getIndex(), p.problemText.length(), |
| p.problemText )); |
| return true; |
| } |
| break; |
| case ScannerConstants.UNEXPECTED_ESCAPE_SEQUENCE: |
| if (node.getNodeType() == NodeType.SCALAR) { |
| node.status= STATUS2_SYNTAX_ESCAPE_INVALID; |
| if (p.problemMark != null && p.problemText != null) { |
| node.addAttachment(new StatusDetail( |
| p.problemMark.getIndex() - 1, p.problemText.length() + 1, |
| '\\' + p.problemText )); |
| } |
| return true; |
| } |
| break; |
| case ScannerConstants.NOT_CLOSED: |
| if (node.getNodeType() == NodeType.SCALAR) { |
| node.status= STATUS2_SYNTAX_TOKEN_NOT_CLOSED; |
| return true; |
| } |
| break; |
| case ScannerConstants.MISSING_DIRECTIVE_NAME: |
| case ScannerConstants.UNEXPECTED_CHAR_FOR_VERSION_NUMBER: |
| case ScannerConstants.MISSING_URI: |
| case ScannerConstants.MISSING_ANCHOR_NAME: |
| case ScannerConstants.MISSING_MAP_COLON: |
| case ScannerConstants.UNEXPECTED_BLOCK_SEQ_ENTRY: |
| if (node.getClass() == Collection.BlockSeq.class) { |
| node.status= STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_SEQ_ENTRY; |
| return true; |
| } |
| break; |
| case ScannerConstants.UNEXPECTED_MAP_KEY: |
| if (node.getNodeType() == NodeType.MAP_ENTRY) { |
| node.status= STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_MAP_KEY; |
| return true; |
| } |
| if (node.getYamlParent() != null |
| && node.getYamlParent().getNodeType() == NodeType.MAP_ENTRY |
| && node.getYamlParent().getStatusCode() == 0) { |
| node.getYamlParent().status= STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_MAP_KEY; |
| return true; |
| } |
| break; |
| case ScannerConstants.UNEXPECTED_MAP_VALUE: |
| if (node.getNodeType() == NodeType.MAP_ENTRY) { |
| node.status= STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_MAP_VALUE; |
| return true; |
| } |
| if (node.getYamlParent() != null |
| && node.getYamlParent().getNodeType() == NodeType.MAP_ENTRY |
| && node.getYamlParent().getStatusCode() == 0) { |
| node.getYamlParent().status= STATUS2_SYNTAX_TOKEN_UNEXPECTED | STATUS3_MAP_VALUE; |
| return true; |
| } |
| break; |
| default: |
| break; |
| } |
| return false; |
| } |
| |
| } |