// ARQ/SPARQL Grammar - native syntax for the query engine #if 0 // (Run through cpp -P -C first) #endif #if !defined(ARQ) && !defined(SPARQL) #error Please define one of ARQ and SPARQL #endif #if defined(ARQ) && defined(SPARQL) #error Please define only one of ARQ and SPARQL #endif #ifdef SPARQL #define PACKAGE parser.sparql #define CLASS SPARQLParser #define PARSERBASE SPARQLParserBase #endif #ifdef ARQ #define PACKAGE parser.arq #define CLASS ARQParser #define PARSERBASE ARQParserBase #endif // // Author: Andy Seaborne andy.seaborne@hp.com // (c) Copyright 2004, 2005 Hewlett-Packard Development Company, LP // All rights reserved. // See end of file for details. // // Constraint expression is derived from Java : // example java1.2-a.jj grammer in JavaCC distribution // Much modifed over time. options { // Use \ u escapes in streams AND use a reader for the query // => get both raw and escaped unicode JAVA_UNICODE_ESCAPE = true; UNICODE_INPUT = false ; STATIC = false ; // DEBUG_PARSER = true ; // DEBUG_TOKEN_MANAGER = true ; } PARSER_BEGIN(CLASS) /* * (c) Copyright 2004, 2005 Hewlett-Packard Development Company, LP * All rights reserved. */ package com.hp.hpl.jena.query.PACKAGE ; import java.util.* ; import com.hp.hpl.jena.graph.* ; import com.hp.hpl.jena.query.* ; import com.hp.hpl.jena.query.core.* ; import com.hp.hpl.jena.query.expr.* ; public class CLASS extends PARSERBASE { } PARSER_END(CLASS) void CompilationUnit(): { } { Query() } void Query() : { } { Prolog() ( SelectClause() | ConstructClause() | DescribeClause() | AskClause() ) DatasetClause() ( WhereClause() ) ? ( OrderClause() ) ? ( LimitClause() ) ? ( OffsetClause() ) ? } void Prolog() : {} { ( BaseDecl() ) ? ( PrefixDecl() )* } void BaseDecl() : { Node n ; } { n = QuotedURIref() { getQuery().setBaseURI(n.getURI()) ; } } void PrefixDecl() : { Token t ; Node n ; } { t = n = QuotedURIref() { getQuery().setPrefix(fixupPrefix(t), n.getURI()) ; } } // ---- Query type clauses void SelectClause() : { Node v ; Token t = null ;} { ( LOOKAHEAD(3) // Need to hop "SELECT" and DISTINCT to look at ?var or STAR (t = )? { getQuery().setQueryResultStar(true) ; } ) { getQuery().setType(Query.QueryTypeSelect) ; getQuery().setDistinct( t != null ) ; } } void DescribeClause() : { Node n ; } { { getQuery().setType(Query.QueryTypeDescribe) ; } ( LOOKAHEAD(2) // Extra lookahead needs for URIs or Vars. ( n = VarOrURI() { getQuery().addDescribeNode(n) ; } )+ { getQuery().setQueryResultStar(false) ; } | { getQuery().setQueryResultStar(true) ; } ) } void ConstructClause() : { Template t ; } { { getQuery().setType(Query.QueryTypeConstruct) ; } t = ConstructTemplate() { getQuery().setQueryResultStar(false) ; getQuery().setConstructTemplate(t) ; } } void AskClause() : {} { { getQuery().setType(Query.QueryTypeAsk) ; } } void DatasetClause() : {} { (LOOKAHEAD(2) DefaultGraphClause())? (NamedGraphClause())* } void DefaultGraphClause() : { Node n ; } { n = SourceSelector() { getQuery().addGraphURI(n.getURI()) ; } } void NamedGraphClause() : { Node n ; } { n = SourceSelector() { getQuery().addNamedGraphURI(n.getURI()) ; } } Node SourceSelector() : { Node n ; } { n = URI() { if ( ! n.isURI() ) throw new QueryException("Not a URI: "+n.toString()) ; return n ; } } void WhereClause() : { Element el ; } { // LOOKAHEAD(2) // el = QueryPattern() { getQuery().setQueryElement(el) ; } // | ()? el = GroupGraphPattern() { getQuery().setQueryElement(el) ; } } void OrderClause() : { } { ( OrderCondition() )+ } void OrderCondition() : { int direction = Query.ASCENDING ; } { { direction = Query.ASCENDING ; } ( ( | { direction = Query.DESCENDING ; } ) OrderExpression(direction) | OrderExpression(direction) ) } void OrderExpression(int direction) : { Node v = null ; Expr expr = null ; } { ( expr = FunctionCall() | v = Var() ) { if ( v == null ) getQuery().addOrderBy(expr, direction) ; else getQuery().addOrderBy(v, direction) ; } } void LimitClause() : { Token t ; } { t = { getQuery().setLimit(integerValue(t.image)) ; } } void OffsetClause() : { Token t ; } { t = { getQuery().setOffset(integerValue(t.image)) ; } } // Element QueryPattern() : { Element el ; } // { // // el = GroupGraphPattern() { return el ; } // // { ElementGroup elg = new ElementGroup() ; } // ( // el = GraphPatternNotTriples() { elg.addElement(el) ; } // ()? // QueryPatternTail(elg) // | // Triples(elg) // ()? // ( el = GraphPatternNotTriples() { elg.addElement(el) ; } // ()? // QueryPatternTail(elg) // )? // ) // // { return compressGroupOfOneGroup(elg) ; } // } void QueryPatternTail(ElementGroup elg) : { Element el ;} { (Triples(elg) ()? )? ( el = GraphPatternNotTriples() { elg.addElement(el) ; } ()? QueryPatternTail(elg) )? } // ---- General Graph Pattern // Basic building block. Element GroupGraphPattern() : { Element el ; } { { ElementGroup elg = new ElementGroup() ; } GraphPatternList(elg) {return elg ; } } void GraphPatternList(ElementGroup elg) : { Element el = null ; } { (Triples(elg) ()? )? ( el = GraphPatternNotTriples() { elg.addElement(el) ; } ()? GraphPatternList(elg) | ) } // ---- All the elements that can make up a pattern void GraphPattern(ElementGroup elg) : { Element el = null ; } { // Combine? Triples(elg) | el = GraphPatternNotTriples() { elg.addElement(el) ; } } Element GraphPatternNotTriples() : { Element el = null ; } { el = OptionalGraphPattern() { return el ; } | LOOKAHEAD(3) // LOOKAHEAD needed to distinguish nested graph patterns // (plain {} in a group) {} UNION {} el = UnionGraphPattern() { return el ; } | el = GroupGraphPattern() { return el ; } | el = GraphGraphPattern() { return el ; } #ifdef ARQ | el = UnsaidGraphPattern() { return el ; } #endif | el = Constraint() { return el ; } } // ---- Definitions of each pattern element Element OptionalGraphPattern() : { Element el ; } { el = GroupGraphPattern() { return new ElementOptional(el) ; } } Element GraphGraphPattern() : { Element el ; Node n ;} { n = VarOrBNodeOrURI() el = GroupGraphPattern() { return new ElementNamedGraph(n, el) ; } } Element UnionGraphPattern() : { Element el = null ; ElementUnion el2 = null ; } { el = GroupGraphPattern() ( { if ( el2 == null ) { el2 = new ElementUnion() ; el2.addElement(el) ; } } el = GroupGraphPattern() { el2.addElement(el) ; } )* { return (el2==null)? el : el2 ; } } #ifdef ARQ Element UnsaidGraphPattern() : { Element el ; } { el = GroupGraphPattern() { el = new ElementUnsaid(el) ; return el ; } } #endif Element Constraint() : { Constraint c ; } { c = Expression() { ElementConstraints ec = new ElementConstraints() ; ec.addConstraint(c) ; return ec ; } } // -------- Construct patterns Template ConstructTemplate() : { Template t ; } { { TemplateGroup g = new TemplateGroup() ; } Triples(g) { return g ; } } // -------- Triple lists with property and object lists void Triples(TripleCollector acc) : { } { // Collect adjacent triples // Lookahead because can be followed by non-triples pattern. Triples1(acc) (LOOKAHEAD(2) Triples(acc))? } void Triples1(TripleCollector acc) : { Node s ; } { LOOKAHEAD(2) // Find [] s = VarOrTerm() PropertyListNotEmpty(s, acc) | // Any of the triple generating syntax elements s = TriplesNode(acc) PropertyList(s, acc) } void PropertyList(Node s, TripleCollector acc) : { } { ( LOOKAHEAD(2) PropertyListNotEmpty(s, acc) ) ? } void PropertyListNotEmpty(Node s, TripleCollector acc) : { Node p ; Node o ; } { p = Verb() ObjectList(s, p, acc) PropertyListTail(s, acc) // ( LOOKAHEAD(2) PropertyList(s, acc) ) ? #ifdef ARQ | Reification(s, acc) #endif } void PropertyListTail(Node s, TripleCollector acc) : { Node p ; Node o ; } { ( PropertyList(s, acc) ) ? } void ObjectList(Node s, Node p, TripleCollector acc): { Node o ; } { // The mark ensures that triples end up in a nicer order o = Object(acc) { Triple t = new Triple(s,p,o) ; acc.addTriple(t) ; } ObjectTail(s, p, acc) } void ObjectTail(Node s, Node p, TripleCollector acc): { Node o ; } { ( ObjectList(s, p , acc) )? } Node Verb() : {Node p ;} { ( p = VarOrURI() | { p = nRDFtype ; } ) { return p ; } } Node Object(TripleCollector acc) : { Node o ; } { ( LOOKAHEAD(2) // Distinguish [] from [:p :q] o = VarOrTerm() | o = TriplesNode(acc) ) { return o ; } } // -------- Triple expansions // Anything that can stand in a node slot and which is // a number of triples Node TriplesNode(TripleCollector acc) : { Node n ; } { n = Collection(acc) { return n ; } | n = BlankNodePropertyList(acc) { return n ; } #ifdef ARQ | n = Reification(null, acc) { return n ; } #endif } Node BlankNodePropertyList(TripleCollector acc) : { } { { Node n = createBNode() ; } PropertyList(n, acc) { return n ; } } #ifdef ARQ Node Reification(Node id, TripleCollector acc) : { Node s , p , o ; int mark ; } { // For generality, should be AndNode for s/p/o // Insert reification triple before the resulting subtriples (if any) "<<" { if ( id == null ) id = createBNode() ; mark = acc.mark() ; } s = GraphNode(acc) // VarOrTerm() { insert(acc, mark, id, nRDFsubject, s) ; } { mark = acc.mark() ; } p = GraphNode(acc) // VarOrURI() { insert(acc, mark, id, nRDFpredicate, p) ; } { mark = acc.mark() ; } o = GraphNode(acc) // VarOrTerm() { insert(acc, mark, id, nRDFobject, o) ; } ">>" { return id ; } } #endif // ------- RDF collections Node Collection(TripleCollector acc) : { Node listHead = nRDFnil ; Node lastCell = null ; int mark ; Node n ; } { ( { Node cell = createBNode() ; if ( listHead == nRDFnil ) listHead = cell ; if ( lastCell != null ) insert(acc, lastCell, nRDFrest, cell) ; mark = acc.mark() ; } n = GraphNode(acc) { insert(acc, mark, cell, nRDFfirst, n) ; lastCell = cell ; } ) + // Not * here - "()" is handled separately. { if ( lastCell != null ) insert(acc, lastCell, nRDFrest, nRDFnil) ; return listHead ; } } // -------- Nodes in a graph pattern or template Node GraphNode(TripleCollector acc) : { Node n ; } { LOOKAHEAD(2) // [] or [ :p :q ] n = VarOrTerm() { return n ; } | n = TriplesNode(acc) { return n ; } } Node VarOrTerm() : {Node n = null ; } { ( n = Var() | n = GraphTerm() ) { return n ; } } // Property + DESCRIBE Node VarOrURI() : {Node n = null ; } { ( n = Var() | n = URI() ) { return n ; } } // GRAPH Node VarOrBNodeOrURI() : {Node n = null ; } { ( n = Var() | n = BlankNode() | n = URI() ) { return n ; } } Node Var() : { Token t ;} { ( t = | t = ) { return Node.createVariable(t.image.substring(1)) ; } } Node GraphTerm() : { Node n ; } { n = RDFTerm() { return n ; } | { return nRDFnil ; } } // Constraint syntax follows. // **** Debug point Expr Expression() : { Expr n ; } { n = ConditionalOrExpression() { return n ; } } Expr ConditionalOrExpression() : { Expr n1, n2 ; } { n1 = ConditionalAndExpression() ( n2 = ConditionalAndExpression() { n1 = new E_LogicalOr(n1,n2) ; } )* { return n1 ; } } Expr ConditionalAndExpression() : { Expr n1, n2 ;} { n1 = ValueLogical() ( n2 = ValueLogical() { n1 = new E_LogicalAnd(n1,n2) ; } )* { return n1 ; } } // End of boolean expressions Expr ValueLogical() : { Expr n ; } { n = RelationalExpression() { return n ; } } Expr RelationalExpression() : { Expr n1, n2 ; } { n1 = NumericExpression() ( n2 = NumericExpression() { n1 = new E_Equal(n1,n2) ; } | n2 = NumericExpression() { n1 = new E_NotEqual(n1,n2) ; } | n2 = NumericExpression() { n1 = new E_LessThan(n1,n2) ; } | n2 = NumericExpression() { n1 = new E_GreaterThan(n1,n2) ; } | n2 = NumericExpression() { n1 = new E_LessThanOrEqual(n1,n2) ; } | n2 = NumericExpression() { n1 = new E_GreaterThanOrEqual(n1,n2) ; } )? { return n1 ; } } // **** Debug point Expr NumericExpression () : { Expr n ; } { n = AdditiveExpression() { return n ; } } Expr AdditiveExpression() : { Expr n1,n2 ; } { n1 = MultiplicativeExpression() ( n2 = MultiplicativeExpression() { n1 = new E_Add(n1, n2) ; } | n2 = MultiplicativeExpression() { n1 = new E_Subtract(n1, n2) ; } )* { return n1 ; } } Expr MultiplicativeExpression() : { Expr n1,n2 ; } { n1 = UnaryExpression() ( n2 = UnaryExpression() { n1 = new E_Multiply(n1, n2) ; } | n2 = UnaryExpression() { n1 = new E_Divide(n1, n2) ; } // | n2 = UnaryExpression() // { n1 = new E_Modulus(n1, n2) ; } )* { return n1 ; } } Expr UnaryExpression() : { Expr n ; } { n = CallExpression() { return new E_LogicalNot(n) ; } | n = CallExpression() { return new E_UnaryPlus(n) ; } | n = CallExpression() { return new E_UnaryMinus(n) ; } | n = CallExpression() { return n ; } } Expr CallExpression() : { Expr expr ; Node gn ; } { // STR expr = Expression() { return new E_Str(expr) ; } | // Lang expr = Expression() { return new E_Lang(expr) ; } | // Datatype expr = Expression() { return new E_Datatype(expr) ; } | // Regular expression matcher { String s1 = null ; String s2 = null ; } expr = Expression() s1 = String() ( s2 = String() )? { return new E_Regex(expr, s1, s2) ; } | gn = Var() { return new E_Bound(new NodeVar(gn)) ; } | expr = Expression() { return new E_IsURI(expr) ; } | expr = Expression() { return new E_IsBlank(expr) ; } | expr = Expression() { return new E_IsLiteral(expr) ; } | //Casts and functions LOOKAHEAD(2) // Differentiate "q:name()" and "q:name" expr = FunctionCall() { return expr ; } | expr = PrimaryExpression() { return expr ; } } Expr PrimaryExpression() : { Expr expr ; Node gn ; } { ( gn = Var() { return asExpr(gn) ; } | gn = RDFTerm() { return asExpr(gn) ; } | expr = Expression() { return expr ; } ) } Expr FunctionCall() : { Node fname ; List a ; } { fname = URI() a = ArgList() { Expr e = new E_Function(fname.getURI(), a) ; return e ; } } List ArgList() : { Expr expr ; } { { List args = new ArrayList() ; } ( expr = Expression() { args.add(expr) ; } ( expr = Expression() { args.add(expr) ; } )* )? { return args ; } } // Term as used in expressions Node RDFTerm() : { Node n ; } { n = URI() { return n ; } | n = RDFLiteral() { return n ; } | n = NumericLiteral() { return n ; } | n = BooleanLiteral() { return n ; } | n = BlankNode() { return n ; } } Node NumericLiteral() : { Node n ; } { n = Integer() { return n ; } | n = FloatingPoint() { return n ; } } Node RDFLiteral() : { Token t ; String lex = null ; } { lex = String() // Optional lang tag and datatype. { String lang = null ; Node uri = null ; } ( ( t = { lang = stripChars(t.image, 1) ; } ) | ( uri = URI() ) )? { return makeNode(lex, lang, uri) ; } } Node BooleanLiteral() : {} { { return XSD_TRUE ; } | { return XSD_FALSE ; } } String String() : { Token t ; String lex = null ; } { ( t = | t = | t = | t = ) { lex = stripQuotes(t.image) ; lex = unescape(lex) ; return lex ; } } Node URI() : { Node n ; } { n = QuotedURIref() { return n ; } | n = QName() { return n ; } } Node QName() : { Token t ; } { ( t = { return Node.createURI(fixupQName(t)) ; } | t = { return Node.createURI(fixupQName(t)) ; } ) } Node BlankNode() : { Token t = null ; } { t = { return createBNode(t.image) ; } | { return createBNode() ; } } Node QuotedURIref() : { Token t ; } { t = { String s = stripQuotes(t.image) ; s = fixupURI(s) ; return Node.createURI(s) ; } } Node Integer() : { Token t ; } { t = { return makeNodeInteger(t.image) ; } } Node FloatingPoint() : { Token t ; } { t = { return makeNodeDouble(t.image) ; } } // ------------------------------------------ // Tokens // Comments and whitespace SKIP : { " " | "\t" | "\n" | "\r" | "\f" } SPECIAL_TOKEN : { } // Main tokens */ TOKEN: { // Includes # for relative URIs // |"#"|"_"|"/"|"&") (~[">"," "])* ">" > "," "])* ">" > | )? ":" > | )? ":" ()? > | > | > | > | ()+("-" ()+)* > | <#A2Z: ["a"-"z","A"-"Z"]> | <#A2ZN: ["a"-"z","A"-"Z","0"-"9"]> } // ------------------------------------------------- TOKEN : { < INTEGER: /*(["-","+"])?*/ > | < FLOATING_POINT: //(["+","-"])? (["0"-"9"])+ "." (["0"-"9"])* ()? | "." (["0"-"9"])+ ()? | (["0"-"9"])+ //NB Must have exponent for this case. > | < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > | < #QUOTE_3D: "\"\"\""> | < #QUOTE_3S: "'''"> | < STRING_LITERAL1: // Single quoted string "'" ( (~["'","\\","\n","\r"]) | ("\\" ~["\n","\r"]) )* "'" > | < STRING_LITERAL2: // Double quoted string "\"" ( (~["\"","\\","\n","\r"]) | ("\\" ~["\n","\r"]) )* "\"" > | < STRING_LITERAL_LONG1: ( ~["\"","\\"] | ("\\" ~["\n","\r"]) | ("\"" ~["\""]) | ("\"\"" ~["\""]))* > | < STRING_LITERAL_LONG2: ( ~["'","\\"] | ("\\" ~["\n","\r"]) | ("'" ~["'"]) | ("''" ~["'"]))* > | < DIGITS: (["0"-"9"])+> } // ------------------------------------------------- // Keyworks : includes operators that are words and should be // before general things like IDENTIFIER which swallow almost // anything TOKEN : { } TOKEN [IGNORE_CASE] : { // Prologue < BASE: "base" > | < PREFIX: "prefix" > // Result forms | < SELECT: "select" > | < DISTINCT: "distinct" > | < DESCRIBE: "describe" > | < CONSTRUCT: "construct" > | < ASK: "ask" > | < LIMIT: "limit" > | < OFFSET: "offset" > | < ORDER: "order" > | < BY: "by" > | < ASC: "asc" > | < DESC: "desc" > // Dataset | < NAMED: "named" > | < FROM: "from" > // Graph pattern operators | < WHERE: "where" > | < AND: "and" > | < GRAPH: "graph" > | < OPTIONAL: "optional" > #ifdef SPARQL | < UNION: "union" > #endif #ifdef ARQ | < UNION: "union" | "or" > #endif #ifdef ARQ | < UNSAID: "unsaid" | "not" > #endif | < FILTER: "filter" > // Expression operators | < BOUND: "bound" > | < STR: "str" > | < DTYPE: "datatype" > | < LANG: "lang" > | < IS_URI: "isURI" > | < IS_BNODE: "isBlank" > | < IS_LITERAL: "isLiteral" > | < REGEX: "regex" > | | } TOKEN : { < LPAREN: "(" > | < RPAREN: ")" > | < LBRACE: "{" > | < RBRACE: "}" > | < LBRACKET: "[" > | < RBRACKET: "]" > | < SEMICOLON: ";" > | < COMMA: "," > | < DOT: "." > } // Operator TOKEN : { < EQ: "=" > | < NE: "!=" > | < GT: ">" > | < LT: "<" > | < LE: "<=" > // Maybe: | "=>" > | < GE: ">=" > // Maybe: | "=<" > | < BANG: "!" > | < TILDE: "~" > | < COLON: ":" > | < SC_OR: "||" > | < SC_AND: "&&" > | < PLUS: "+" > | < MINUS: "-" > | < STAR: "*" > | < SLASH: "/" > //| < AMP: "&" > //| < REM: "%" > | < DATATYPE: "^^"> | < AT: "@"> } // Notes: // XML 1.1 http://www.w3.org/TR/xml11/ // XML Namespces 1.1 http://www.w3.org/TR/xml-names11/ // Prefix ':' LocalPart // Prefix is an NCName // LocalPart is an NCName // // // An XML Name, minus the ":" // NCName ::= NCNameStartChar NCNameChar* // NCNameChar ::= NameChar - ':' // NCNameStartChar ::= NameStartChar - ':' // NameChar and NameSartChar defined in XML 1.1 // NameStartChar := ":" | [A-Z] | "_" | [a-z] | // was: [#xC0-#x2FF] | // now: [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | // [#x370-#x37D] | [#x37F-#x1FFF] | // [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | // [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | // [#x3001-#xD7FF] | [#xF900-#xEFFFF] // NameChar := NameStartChar | "-" | "." | [0-9] | #xB7 | // [#x0300-#x036F] | [#x203F-#x2040] TOKEN: { // XML 1.1 NCNameStartChar without "_" <#NCCHAR1: ["A"-"Z"] | ["a"-"z"] | ["\u00C0"-"\u00D6"] | ["\u00D8"-"\u00F6"] | ["\u00F8"-"\u02FF"] | ["\u0370"-"\u037D"] | ["\u037F"-"\u1FFF"] | ["\u200C"-"\u200D"] | ["\u2070"-"\u218F"] | ["\u2C00"-"\u2FEF"] | ["\u3001"-"\uD7FF"] | ["\uF900"-"\uFFFF"] > | // #NCCHAR <#NCCHAR: ( | "_" | "-" | "." | ["0"-"9"] | "\u00B7" )> | // NCNAME but no leading "_" <#NCNAME_PREFIX: ()* > | // With a leading "_" <#NCNAME: ("_"|) ()*> | // NCNAME without "-" and ".", allowing leading digits. <#VARNAME: ( | "_" | ["0"-"9"] | "\u00B7" )*> } /* * (c) Copyright 2004, 2005 Hewlett-Packard Development Company, LP * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /* # Local Variables: # tab-width: 4 # indent-tabs-mode: nil # comment-default-style: "//" # End: */