1/*
2 * [The "BSD license"]
3 *  Copyright (c) 2010 Terence Parr
4 *  All rights reserved.
5 *
6 *  Redistribution and use in source and binary forms, with or without
7 *  modification, are permitted provided that the following conditions
8 *  are met:
9 *  1. Redistributions of source code must retain the above copyright
10 *      notice, this list of conditions and the following disclaimer.
11 *  2. Redistributions in binary form must reproduce the above copyright
12 *      notice, this list of conditions and the following disclaimer in the
13 *      documentation and/or other materials provided with the distribution.
14 *  3. The name of the author may not be used to endorse or promote products
15 *      derived from this software without specific prior written permission.
16 *
17 *  THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 *  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 *  OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 *  NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28package org.antlr.codegen;
29
30import org.antlr.Tool;
31import org.stringtemplate.v4.ST;
32import org.stringtemplate.v4.STGroup;
33import org.antlr.tool.Grammar;
34
35import java.io.IOException;
36
37public class CPPTarget extends Target {
38
39	public String escapeChar( int c ) {
40		// System.out.println("CPPTarget.escapeChar("+c+")");
41		switch (c) {
42		case '\n' : return "\\n";
43		case '\t' : return "\\t";
44		case '\r' : return "\\r";
45		case '\\' : return "\\\\";
46		case '\'' : return "\\'";
47		case '"' :  return "\\\"";
48		default :
49			if ( c < ' ' || c > 126 )
50			{
51				if (c > 255)
52				{
53					String s = Integer.toString(c,16);
54					// put leading zeroes in front of the thing..
55					while( s.length() < 4 )
56						s = '0' + s;
57					return "\\u" + s;
58				}
59				else {
60					return "\\" + Integer.toString(c,8);
61				}
62			}
63			else {
64				return String.valueOf((char)c);
65			}
66		}
67	}
68
69	/** Converts a String into a representation that can be use as a literal
70	 * when surrounded by double-quotes.
71	 *
72	 * Used for escaping semantic predicate strings for exceptions.
73	 *
74	 * @param s The String to be changed into a literal
75	 */
76	public String escapeString(String s)
77	{
78		StringBuffer retval = new StringBuffer();
79		for (int i = 0; i < s.length(); i++) {
80			retval.append(escapeChar(s.charAt(i)));
81		}
82
83		return retval.toString();
84	}
85
86	protected void genRecognizerHeaderFile(Tool tool,
87										   CodeGenerator generator,
88										   Grammar grammar,
89										   ST headerFileST,
90										   String extName)
91		throws IOException
92	{
93		generator.write(headerFileST, grammar.name+extName);
94	}
95
96	/** Convert from an ANTLR char literal found in a grammar file to
97	 *  an equivalent char literal in the target language.  For Java, this
98	 *  is the identify translation; i.e., '\n' -> '\n'.  Most languages
99	 *  will be able to use this 1-to-1 mapping.  Expect single quotes
100	 *  around the incoming literal.
101	 *  Depending on the charvocabulary the charliteral should be prefixed with a 'L'
102	 */
103	public String getTargetCharLiteralFromANTLRCharLiteral( CodeGenerator codegen, String literal) {
104		int c = Grammar.getCharValueFromGrammarCharLiteral(literal);
105		String prefix = "'";
106		if( codegen.grammar.getMaxCharValue() > 255 )
107			prefix = "L'";
108		else if( (c & 0x80) != 0 )	// if in char mode prevent sign extensions
109			return ""+c;
110		return prefix+escapeChar(c)+"'";
111	}
112
113	/** Convert from an ANTLR string literal found in a grammar file to
114	 *  an equivalent string literal in the target language.  For Java, this
115	 *  is the identify translation; i.e., "\"\n" -> "\"\n".  Most languages
116	 *  will be able to use this 1-to-1 mapping.  Expect double quotes
117	 *  around the incoming literal.
118	 *  Depending on the charvocabulary the string should be prefixed with a 'L'
119	 */
120	public String getTargetStringLiteralFromANTLRStringLiteral( CodeGenerator codegen, String literal) {
121		StringBuffer buf = Grammar.getUnescapedStringFromGrammarStringLiteral(literal);
122		String prefix = "\"";
123		if( codegen.grammar.getMaxCharValue() > 255 )
124			prefix = "L\"";
125		return prefix+escapeString(buf.toString())+"\"";
126	}
127	/** Character constants get truncated to this value.
128	 * TODO: This should be derived from the charVocabulary. Depending on it
129	 * being 255 or 0xFFFF the templates should generate normal character
130	 * constants or multibyte ones.
131	 */
132	public int getMaxCharValue( CodeGenerator codegen ) {
133		int maxval = 255; // codegen.grammar.get????();
134		if ( maxval <= 255 )
135			return 255;
136		else
137			return maxval;
138	}
139}
140